void Hiptmair<MatrixType>:: applyHiptmairSmoother(const Tpetra::MultiVector<typename MatrixType::scalar_type, typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type>& X, Tpetra::MultiVector<typename MatrixType::scalar_type, typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type>& Y) const { using Teuchos::RCP; using Teuchos::rcp; using Teuchos::rcpFromRef; typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type> MV; const scalar_type ZERO = STS::zero (); const scalar_type ONE = STS::one (); RCP<MV> res1 = rcp (new MV (A_->getRowMap (), X.getNumVectors ())); RCP<MV> vec1 = rcp (new MV (A_->getRowMap (), X.getNumVectors ())); RCP<MV> res2 = rcp (new MV (PtAP_->getRowMap (), X.getNumVectors ())); RCP<MV> vec2 = rcp (new MV (PtAP_->getRowMap (), X.getNumVectors ())); if (preOrPost_ == "pre" || preOrPost_ == "both") { // apply initial relaxation to primary space A_->apply (Y, *res1); res1->update (ONE, X, -ONE); vec1->putScalar (ZERO); ifpack2_prec1_->apply (*res1, *vec1); Y.update (ONE, *vec1, ONE); } // project to auxiliary space and smooth A_->apply (Y, *res1); res1->update (ONE, X, -ONE); P_->apply (*res1, *res2, Teuchos::TRANS); vec2->putScalar (ZERO); ifpack2_prec2_->apply (*res2, *vec2); P_->apply (*vec2, *vec1, Teuchos::NO_TRANS); Y.update (ONE,*vec1,ONE); if (preOrPost_ == "post" || preOrPost_ == "both") { // smooth again on primary space A_->apply (Y, *res1); res1->update (ONE, X, -ONE); vec1->putScalar (ZERO); ifpack2_prec1_->apply (*res1, *vec1); Y.update (ONE, *vec1, ONE); } }
void IdentitySolver<MatrixType>:: apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X, Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y, Teuchos::ETransp /*mode*/, scalar_type alpha, scalar_type beta) const { using Teuchos::RCP; typedef Teuchos::ScalarTraits<scalar_type> STS; typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type> MV; TEUCHOS_TEST_FOR_EXCEPTION( ! isComputed (), std::runtime_error, "Ifpack2::IdentitySolver::apply: If compute() has not yet been called, " "or if you have changed the matrix via setMatrix(), " "you must call compute() before you may call this method."); // "Identity solver" does what it says: it's the identity operator. // We have to Export if the domain and range Maps are not the same. // Otherwise, this operator would be a permutation, not the identity. if (export_.is_null ()) { Y.update (alpha, X, beta); } else { if (alpha == STS::one () && beta == STS::zero ()) { // the common case Y.doExport (X, *export_, Tpetra::REPLACE); } else { // We know that the domain and range Maps are compatible. First // bring X into the range Map via Export. Then compute in place // in Y. MV X_tmp (Y.getMap (), Y.getNumVectors ()); X_tmp.doExport (X, *export_, Tpetra::REPLACE); Y.update (alpha, X_tmp, beta); } } ++numApply_; }