void RILUK<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 { typedef Teuchos::ScalarTraits<scalar_type> STS; TEUCHOS_TEST_FOR_EXCEPTION(!isComputed(), std::runtime_error, "Ifpack2::RILUK::apply() ERROR, compute() hasn't been called yet."); TEUCHOS_TEST_FOR_EXCEPTION( alpha != STS::one (), std::logic_error, "Ifpack2::RILUK::apply() does not currently allow alpha != 1."); TEUCHOS_TEST_FOR_EXCEPTION( beta != STS::zero (), std::logic_error, "Ifpack2::RILUK::apply() does not currently allow zero != 0."); // // This function finds Y such that // LDU Y = X, or // U(trans) D L(trans) Y = X // for multiple RHS // // First generate X and Y as needed for this function Teuchos::RCP<const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> > X1; Teuchos::RCP<Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> > Y1; generateXY(mode, X, Y, X1, Y1); scalar_type one = Teuchos::ScalarTraits<scalar_type>::one(); scalar_type zero = Teuchos::ScalarTraits<scalar_type>::zero(); if (mode == Teuchos::NO_TRANS) { L_->localSolve(*X1, *Y1,mode); Y1->elementWiseMultiply(one, *D_, *Y1, zero); // y = D*y (D_ has inverse of diagonal) U_->localSolve(*Y1, *Y1,mode); // Solve Uy = y if (isOverlapped_) { // Export computed Y values if needed Y.doExport(*Y1,*L_->getGraph()->getExporter(), OverlapMode_); } } else { U_->localSolve(*X1, *Y1,mode); // Solve Uy = y Y1->elementWiseMultiply(one, *D_, *Y1, zero); // y = D*y (D_ has inverse of diagonal) L_->localSolve(*Y1, *Y1,mode); if (isOverlapped_) {Y.doExport(*Y1,*U_->getGraph()->getImporter(), OverlapMode_);} // Export computed Y values if needed } ++numApply_; }
void OverlappingRowMatrix<MatrixType>:: exportMultiVector (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &OvX, Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &X, Tpetra::CombineMode CM) { X.doExport (OvX, *Importer_, CM); }
int RILUK<MatrixType>::Multiply(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) const { // // This function finds X such that LDU Y = X or U(trans) D L(trans) Y = X for multiple RHS // // First generate X and Y as needed for this function Teuchos::RCP<const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> > X1; Teuchos::RCP<Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> > Y1; generateXY(mode, X, Y, X1, Y1); // Epetra_Flops * counter = this->GetFlopCounter(); // if (counter!=0) { // L_->SetFlopCounter(*counter); // Y1->SetFlopCounter(*counter); // U_->SetFlopCounter(*counter); // } if (!mode == Teuchos::NO_TRANS) { U_->apply(*X1, *Y1,mode); // Y1->update(1.0, *X1, 1.0); // Y1 = Y1 + X1 (account for implicit unit diagonal) Y1->elementWiseMultiply(1.0, *D_, *Y1, 0.0); // y = D*y (D_ has inverse of diagonal) Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> Y1temp(*Y1); // Need a temp copy of Y1 L_->apply(Y1temp, *Y1,mode); Y1->update(1.0, Y1temp, 1.0); // (account for implicit unit diagonal) if (isOverlapped_) {Y.doExport(*Y1,*L_->getGraph()->getExporter(), OverlapMode_);} // Export computed Y values if needed } else { L_->apply(*X1, *Y1,mode); Y1->update(1.0, *X1, 1.0); // Y1 = Y1 + X1 (account for implicit unit diagonal) Y1->elementWiseMultiply(1, *D_, *Y1, 0); // y = D*y (D_ has inverse of diagonal) Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> Y1temp(*Y1); // Need a temp copy of Y1 U_->apply(Y1temp, *Y1,mode); Y1->update(1.0, Y1temp, 1.0); // (account for implicit unit diagonal) if (isOverlapped_) {Y.doExport(*Y1,*L_->getGraph()->getExporter(), OverlapMode_);} } return(0); }
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_; }
void OverlappingRowMatrix<MatrixType>::exportMultiVectorTempl(const Tpetra::MultiVector<OpScalar,LocalOrdinal,GlobalOrdinal,Node> &OvX, Tpetra::MultiVector<OpScalar,LocalOrdinal,GlobalOrdinal,Node> &X, Tpetra::CombineMode CM) { X.doExport(OvX,*Importer_,CM); }
void LocalSparseTriangularSolver<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; using Teuchos::rcp; using Teuchos::rcpFromRef; typedef scalar_type ST; typedef Teuchos::ScalarTraits<ST> STS; const char prefix[] = "Ifpack2::LocalSparseTriangularSolver::apply: "; if (! out_.is_null ()) { *out_ << ">>> DEBUG " << prefix; if (A_crs_.is_null ()) { *out_ << "A_crs_ is null!" << std::endl; } else { const std::string uplo = A_crs_->isUpperTriangular () ? "U" : (A_crs_->isLowerTriangular () ? "L" : "N"); const std::string trans = (mode == Teuchos::CONJ_TRANS) ? "C" : (mode == Teuchos::TRANS ? "T" : "N"); const std::string diag = (A_crs_->getNodeNumDiags () < A_crs_->getNodeNumRows ()) ? "U" : "N"; *out_ << "uplo=\"" << uplo << "\", trans=\"" << trans << "\", diag=\"" << diag << "\"" << std::endl; } } TEUCHOS_TEST_FOR_EXCEPTION (! isComputed (), std::runtime_error, prefix << "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."); // If isComputed() is true, it's impossible for the matrix to be // null, or for it not to be a Tpetra::CrsMatrix. TEUCHOS_TEST_FOR_EXCEPTION (A_.is_null (), std::logic_error, prefix << "A_ is null. " "Please report this bug to the Ifpack2 developers."); TEUCHOS_TEST_FOR_EXCEPTION (A_crs_.is_null (), std::logic_error, prefix << "A_crs_ is null. " "Please report this bug to the Ifpack2 developers."); // However, it _is_ possible that the user called resumeFill() on // the matrix, after calling compute(). This is NOT allowed. TEUCHOS_TEST_FOR_EXCEPTION (! A_crs_->isFillComplete (), std::runtime_error, "If you call this " "method, the matrix must be fill complete. It is not. This means that " " you must have called resumeFill() on the matrix before calling apply(). " "This is NOT allowed. Note that this class may use the matrix's data in " "place without copying it. Thus, you cannot change the matrix and expect " "the solver to stay the same. If you have changed the matrix, first call " "fillComplete() on it, then call compute() on this object, before you call" " apply(). You do NOT need to call setMatrix, as long as the matrix " "itself (that is, its address in memory) is the same."); auto G = A_->getGraph (); TEUCHOS_TEST_FOR_EXCEPTION (G.is_null (), std::logic_error, prefix << "A_ and A_crs_ are nonnull, " "but A_'s RowGraph G is null. " "Please report this bug to the Ifpack2 developers."); auto importer = G->getImporter (); auto exporter = G->getExporter (); if (! importer.is_null ()) { if (X_colMap_.is_null () || X_colMap_->getNumVectors () != X.getNumVectors ()) { X_colMap_ = rcp (new MV (importer->getTargetMap (), X.getNumVectors ())); } else { X_colMap_->putScalar (STS::zero ()); } // See discussion of Github Issue #672 for why the Import needs to // use the ZERO CombineMode. The case where the Export is // nontrivial is likely never exercised. X_colMap_->doImport (X, *importer, Tpetra::ZERO); } RCP<const MV> X_cur = importer.is_null () ? rcpFromRef (X) : Teuchos::rcp_const_cast<const MV> (X_colMap_); if (! exporter.is_null ()) { if (Y_rowMap_.is_null () || Y_rowMap_->getNumVectors () != Y.getNumVectors ()) { Y_rowMap_ = rcp (new MV (exporter->getSourceMap (), Y.getNumVectors ())); } else { Y_rowMap_->putScalar (STS::zero ()); } Y_rowMap_->doExport (Y, *importer, Tpetra::ADD); } RCP<MV> Y_cur = exporter.is_null () ? rcpFromRef (Y) : Y_rowMap_; localApply (*X_cur, *Y_cur, mode, alpha, beta); if (! exporter.is_null ()) { Y.putScalar (STS::zero ()); Y.doExport (*Y_cur, *exporter, Tpetra::ADD); } ++numApply_; }