/*! \brief Apply the preconditoner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { // Extract part of d corresponding to elliptic part. // Note: Assumes that the elliptic part comes first. std::copy_n(d.begin(), de_.size(), de_.begin()); // Solve elliptic part, extend solution to full. // reset result ve_ = 0; solveElliptic( ve_, de_ ); //reset return value v = 0.0; // Again assuming that the elliptic part comes first. std::copy(ve_.begin(), ve_.end(), v.begin()); // Subtract elliptic residual from initial residual. // dmodified = d - A * vfull dmodified_ = d; A_.mmv(v, dmodified_); // A is not parallel, do communication manually. comm_.copyOwnerToAll(dmodified_, dmodified_); // Apply Preconditioner for whole system (relax will be applied already) pre_->apply( vilu_, dmodified_); // don't apply relaxation if relax_ == 1 if( std::abs( param_.cpr_relax_ - 1.0 ) < 1e-12 ) { v += vilu_; } else { v *= param_.cpr_relax_; v += vilu_; } }
/*! \brief Apply the preconditoner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (X& v, const Y& d) { // Extract part of d corresponding to elliptic part. Y de(Ae_.N()); // Note: Assumes that the elliptic part comes first. std::copy_n(d.begin(), Ae_.N(), de.begin()); // Solve elliptic part, extend solution to full. Y ve = solveElliptic(de); Y vfull(ILU_.N()); vfull = 0.0; // Again assuming that the elliptic part comes first. std::copy(ve.begin(), ve.end(), vfull.begin()); // Subtract elliptic residual from initial residual. // dmodified = d - A * vfull Y dmodified = d; A_.mmv(vfull, dmodified); // Apply ILU0. Y vilu(ILU_.N()); Dune::bilu_backsolve(ILU_, vilu, dmodified); v = vfull; v += vilu; v *= relax_; }