42 #ifndef TPETRA_CRSMATRIXMULTIPLYOP_HPP 43 #define TPETRA_CRSMATRIXMULTIPLYOP_HPP 51 #include "Tpetra_CrsMatrix.hpp" 55 #include "Tpetra_LocalCrsMatrixOperator.hpp" 95 template <
class Scalar,
101 public Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node>
111 using local_matrix_type =
124 localMultiply_ (std::make_shared<local_matrix_type> (A->getLocalMatrix ()))
139 Teuchos::ETransp mode = Teuchos::NO_TRANS,
140 Scalar alpha = Teuchos::ScalarTraits<Scalar>::one (),
141 Scalar beta = Teuchos::ScalarTraits<Scalar>::zero ())
const override 143 TEUCHOS_TEST_FOR_EXCEPTION
144 (!
matrix_->isFillComplete (), std::runtime_error,
145 Teuchos::typeName (*
this) <<
"::apply(): underlying matrix is not fill-complete.");
146 TEUCHOS_TEST_FOR_EXCEPTION
148 Teuchos::typeName (*
this) <<
"::apply(X,Y): X and Y must have the same number of vectors.");
149 TEUCHOS_TEST_FOR_EXCEPTION
150 (Teuchos::ScalarTraits<Scalar>::isComplex && mode == Teuchos::TRANS, std::logic_error,
151 Teuchos::typeName (*
this) <<
"::apply() does not currently support transposed multiplications for complex scalar types.");
152 if (mode == Teuchos::NO_TRANS) {
203 const Scalar& dampingFactor,
205 const int numSweeps)
const 210 using Teuchos::rcpFromRef;
211 using Teuchos::rcp_const_cast;
217 TEUCHOS_TEST_FOR_EXCEPTION
218 (numSweeps < 0, std::invalid_argument,
219 "gaussSeidel: The number of sweeps must be nonnegative, " 220 "but you provided numSweeps = " << numSweeps <<
" < 0.");
225 if (direction == Forward) {
226 localDirection = Forward;
228 else if (direction == Backward) {
229 localDirection = Backward;
231 else if (direction == Symmetric) {
233 localDirection = Forward;
236 TEUCHOS_TEST_FOR_EXCEPTION
237 (
true, std::invalid_argument,
238 "gaussSeidel: The 'direction' enum does not have any of its valid " 239 "values: Forward, Backward, or Symmetric.");
242 if (numSweeps == 0) {
249 RCP<const import_type> importer =
matrix_->getGraph()->getImporter();
250 RCP<const export_type> exporter =
matrix_->getGraph()->getExporter();
251 TEUCHOS_TEST_FOR_EXCEPTION
252 (! exporter.is_null (), std::runtime_error,
253 "Tpetra's gaussSeidel implementation requires that the row, domain, " 254 "and range Maps be the same. This cannot be the case, because the " 255 "matrix has a nontrivial Export object.");
257 RCP<const map_type> domainMap =
matrix_->getDomainMap ();
258 RCP<const map_type> rangeMap =
matrix_->getRangeMap ();
259 RCP<const map_type> rowMap =
matrix_->getGraph ()->getRowMap ();
260 RCP<const map_type> colMap =
matrix_->getGraph ()->getColMap ();
267 TEUCHOS_TEST_FOR_EXCEPTION
268 (! X.
getMap ()->isSameAs (*domainMap), std::runtime_error,
269 "Tpetra::CrsMatrix::gaussSeidel requires that the input " 270 "multivector X be in the domain Map of the matrix.");
271 TEUCHOS_TEST_FOR_EXCEPTION
272 (! B.
getMap ()->isSameAs (*rangeMap), std::runtime_error,
273 "Tpetra::CrsMatrix::gaussSeidel requires that the input " 274 "B be in the range Map of the matrix.");
275 TEUCHOS_TEST_FOR_EXCEPTION
276 (! D.
getMap ()->isSameAs (*rowMap), std::runtime_error,
277 "Tpetra::CrsMatrix::gaussSeidel requires that the input " 278 "D be in the row Map of the matrix.");
279 TEUCHOS_TEST_FOR_EXCEPTION
280 (! rowMap->isSameAs (*rangeMap), std::runtime_error,
281 "Tpetra::CrsMatrix::gaussSeidel requires that the row Map and the " 282 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
283 TEUCHOS_TEST_FOR_EXCEPTION
284 (! domainMap->isSameAs (*rangeMap), std::runtime_error,
285 "Tpetra::CrsMatrix::gaussSeidel requires that the domain Map and " 286 "the range Map of the matrix be the same.");
295 RCP<const OSMV> B_in;
297 B_in = rcpFromRef (B);
304 RCP<OSMV> B_in_nonconst = getRowMapMultiVector (B,
true);
306 B_in = rcp_const_cast<
const OSMV> (B_in_nonconst);
310 "gaussSeidel: The current implementation of the Gauss-Seidel kernel " 311 "requires that X and B both have constant stride. Since B does not " 312 "have constant stride, we had to make a copy. This is a limitation of " 313 "the current implementation and not your fault, but we still report it " 314 "as an efficiency warning for your information.");
323 RCP<OSMV> X_domainMap;
325 bool copiedInput =
false;
327 if (importer.is_null ()) {
329 X_domainMap = rcpFromRef (X);
330 X_colMap = X_domainMap;
337 X_colMap = getColumnMapMultiVector (X,
true);
338 X_domainMap = X_colMap;
343 "gaussSeidel: The current implementation of the Gauss-Seidel kernel " 344 "requires that X and B both have constant stride. Since X does not " 345 "have constant stride, we had to make a copy. This is a limitation of " 346 "the current implementation and not your fault, but we still report it " 347 "as an efficiency warning for your information.");
352 X_domainMap = rcpFromRef (X);
356 X_colMap = X_domainMap->offsetViewNonConst (colMap, 0);
360 X_colMap->doImport (X, *importer,
INSERT);
368 X_colMap = getColumnMapMultiVector (X,
true);
369 X_domainMap = X_colMap->offsetViewNonConst (domainMap, 0);
370 X_colMap->doImport (X, *importer,
INSERT);
374 "gaussSeidel: The current implementation of the Gauss-Seidel kernel " 375 "requires that X and B both have constant stride. Since X does not " 376 "have constant stride, we had to make a copy. This is a limitation of " 377 "the current implementation and not your fault, but we still report it " 378 "as an efficiency warning for your information.");
382 for (
int sweep = 0; sweep < numSweeps; ++sweep) {
383 if (! importer.is_null () && sweep > 0) {
385 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
389 if (direction != Symmetric) {
390 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
395 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
399 if (! importer.is_null ()) {
400 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
402 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
441 const Scalar& dampingFactor,
443 const int numSweeps)
const 448 using Teuchos::rcpFromRef;
449 using Teuchos::rcp_const_cast;
455 TEUCHOS_TEST_FOR_EXCEPTION
456 (numSweeps < 0, std::invalid_argument,
457 "gaussSeidelCopy: The number of sweeps must be nonnegative, " 458 "but you provided numSweeps = " << numSweeps <<
" < 0.");
463 if (direction == Forward) {
464 localDirection = Forward;
466 else if (direction == Backward) {
467 localDirection = Backward;
469 else if (direction == Symmetric) {
471 localDirection = Forward;
474 TEUCHOS_TEST_FOR_EXCEPTION
475 (
true, std::invalid_argument,
476 "gaussSeidelCopy: The 'direction' enum does not have any of its " 477 "valid values: Forward, Backward, or Symmetric.");
480 if (numSweeps == 0) {
484 RCP<const import_type> importer =
matrix_->getGraph()->getImporter();
485 RCP<const export_type> exporter =
matrix_->getGraph()->getExporter();
486 TEUCHOS_TEST_FOR_EXCEPTION
487 (! exporter.is_null (),
489 "Tpetra's gaussSeidelCopy implementation requires that the row, domain, " 490 "and range Maps be the same. This cannot be the case, because the " 491 "matrix has a nontrivial Export object.");
493 RCP<const map_type> domainMap =
matrix_->getDomainMap ();
494 RCP<const map_type> rangeMap =
matrix_->getRangeMap ();
495 RCP<const map_type> rowMap =
matrix_->getGraph ()->getRowMap ();
496 RCP<const map_type> colMap =
matrix_->getGraph ()->getColMap ();
503 TEUCHOS_TEST_FOR_EXCEPTION
504 (! X.
getMap ()->isSameAs (*domainMap), std::runtime_error,
505 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input " 506 "multivector X be in the domain Map of the matrix.");
507 TEUCHOS_TEST_FOR_EXCEPTION
508 (! B.
getMap ()->isSameAs (*rangeMap), std::runtime_error,
509 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input " 510 "B be in the range Map of the matrix.");
511 TEUCHOS_TEST_FOR_EXCEPTION
512 (! D.
getMap ()->isSameAs (*rowMap), std::runtime_error,
513 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input " 514 "D be in the row Map of the matrix.");
515 TEUCHOS_TEST_FOR_EXCEPTION
516 (! rowMap->isSameAs (*rangeMap), std::runtime_error,
517 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the row Map and the " 518 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
519 TEUCHOS_TEST_FOR_EXCEPTION
520 (! domainMap->isSameAs (*rangeMap), std::runtime_error,
521 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the domain Map and " 522 "the range Map of the matrix be the same.");
534 RCP<OSMV> X_domainMap;
535 bool copyBackOutput =
false;
536 if (importer.is_null ()) {
538 X_colMap = rcpFromRef (X);
539 X_domainMap = rcpFromRef (X);
544 X_colMap = getColumnMapMultiVector (X,
true);
548 X_domainMap = X_colMap;
550 copyBackOutput =
true;
553 "gaussSeidelCopy: The current implementation of the Gauss-Seidel " 554 "kernel requires that X and B both have constant stride. Since X " 555 "does not have constant stride, we had to make a copy. This is a " 556 "limitation of the current implementation and not your fault, but we " 557 "still report it as an efficiency warning for your information.");
561 X_colMap = getColumnMapMultiVector (X);
562 X_domainMap = X_colMap->offsetViewNonConst (domainMap, 0);
572 X_colMap->doImport (X, *importer,
INSERT);
574 copyBackOutput =
true;
580 RCP<const OSMV> B_in;
582 B_in = rcpFromRef (B);
588 RCP<OSMV> B_in_nonconst = getRowMapMultiVector (B,
true);
590 B_in = rcp_const_cast<
const OSMV> (B_in_nonconst);
594 "gaussSeidelCopy: The current implementation requires that B have " 595 "constant stride. Since B does not have constant stride, we had to " 596 "copy it into a separate constant-stride multivector. This is a " 597 "limitation of the current implementation and not your fault, but we " 598 "still report it as an efficiency warning for your information.");
601 for (
int sweep = 0; sweep < numSweeps; ++sweep) {
602 if (! importer.is_null () && sweep > 0) {
604 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
608 if (direction != Symmetric) {
609 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
614 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
618 if (! importer.is_null ()) {
619 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
621 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
627 if (copyBackOutput) {
643 return matrix_->getDomainMap ();
648 return matrix_->getRangeMap ();
657 const Teuchos::RCP<const crs_matrix_type>
matrix_;
675 mutable Teuchos::RCP<MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
importMV_;
689 mutable Teuchos::RCP<MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
exportMV_;
696 Teuchos::ETransp mode,
705 using STS = Teuchos::ScalarTraits<Scalar>;
711 RCP<const import_type> importer =
matrix_->getGraph()->getImporter();
712 RCP<const export_type> exporter =
matrix_->getGraph()->getExporter();
716 const bool Y_is_overwritten = (beta == STS::zero ());
717 const int myRank =
matrix_->getComm ()->getRank ();
718 if (Y_is_replicated && myRank != 0) {
727 X = Teuchos::rcp (
new MV (X_in, Teuchos::Copy));
731 X = Teuchos::rcpFromRef (X_in);
735 if (importer != null) {
743 if (exporter != null) {
753 if (exporter != null) {
758 auto X_lcl = X->getLocalViewDevice ();
762 if (importer != null) {
763 auto Y_lcl =
importMV_->getLocalViewDevice ();
767 if (Y_is_overwritten) {
780 MV Y (Y_in, Teuchos::Copy);
795 if (Y_is_replicated) {
808 using Teuchos::NO_TRANS;
811 using Teuchos::rcp_const_cast;
812 using Teuchos::rcpFromRef;
815 typedef Teuchos::ScalarTraits<Scalar> STS;
817 if (alpha == STS::zero ()) {
818 if (beta == STS::zero ()) {
820 }
else if (beta != STS::one ()) {
835 RCP<const import_type> importer =
matrix_->getGraph()->getImporter();
836 RCP<const export_type> exporter =
matrix_->getGraph()->getExporter();
842 const bool Y_is_overwritten = (beta == STS::zero());
845 const bool Y_is_replicated =
855 if (Y_is_replicated &&
matrix_->getComm ()->getRank () > 0) {
862 RCP<const MV> X_colMap;
863 if (importer.is_null ()) {
871 RCP<MV> X_colMapNonConst = getColumnMapMultiVector (X_in,
true);
873 X_colMap = rcp_const_cast<
const MV> (X_colMapNonConst);
878 X_colMap = rcpFromRef (X_in);
882 ProfilingRegion regionImport (
"Tpetra::CrsMatrixMultiplyOp::apply: Import");
888 RCP<MV> X_colMapNonConst = getColumnMapMultiVector (X_in);
891 X_colMapNonConst->doImport (X_in, *importer,
INSERT);
892 X_colMap = rcp_const_cast<
const MV> (X_colMapNonConst);
899 RCP<MV> Y_rowMap = getRowMapMultiVector (Y_in);
901 auto X_lcl = X_colMap->getLocalViewDevice ();
908 if (! exporter.is_null ()) {
909 auto Y_lcl = Y_rowMap->getLocalViewDevice ();
910 Y_rowMap->modify_device ();
912 alpha, STS::zero ());
914 ProfilingRegion regionExport (
"Tpetra::CrsMatrixMultiplyOp::apply: Export");
920 if (Y_is_overwritten) {
947 Y_rowMap = getRowMapMultiVector (Y_in,
true);
951 if (beta != STS::zero ()) {
955 auto Y_lcl = Y_rowMap->getLocalViewDevice ();
956 Y_rowMap->modify_device ();
971 if (Y_is_replicated) {
972 ProfilingRegion regionReduce (
"Tpetra::CrsMatrixMultiplyOp::apply: Reduce Y");
999 const bool force =
false)
const 1001 using Teuchos::null;
1007 RCP<const import_type> importer =
matrix_->getGraph ()->getImporter ();
1008 RCP<const map_type> colMap =
matrix_->getColMap ();
1021 if (! importer.is_null () || force) {
1023 X_colMap = rcp (
new MV (colMap, numVecs));
1062 getRowMapMultiVector (
const MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y_rangeMap,
1063 const bool force =
false)
const 1065 using Teuchos::null;
1068 typedef Export<LocalOrdinal,GlobalOrdinal,Node> export_type;
1070 const size_t numVecs = Y_rangeMap.getNumVectors ();
1071 RCP<const export_type> exporter =
matrix_->getGraph ()->getExporter ();
1072 RCP<const map_type> rowMap =
matrix_->getRowMap ();
1084 if (! exporter.is_null () || force) {
1086 Y_rowMap = rcp (
new MV (rowMap, numVecs));
1104 template <
class OpScalar,
1107 class GlobalOrdinal,
1110 CrsMatrixMultiplyOp<OpScalar, MatScalar, LocalOrdinal, GlobalOrdinal, Node> >
1115 GlobalOrdinal, Node> op_type;
1116 return Teuchos::rcp (
new op_type (A));
1121 #endif // TPETRA_CRSMATRIXMULTIPLYOP_HPP Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void gaussSeidel(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &D, const Scalar &dampingFactor, const ESweepDirection direction, const int numSweeps) const
"Hybrid" Jacobi + (Gauss-Seidel or SOR) on .
Abstract interface for local operators (e.g., matrices and preconditioners).
Sparse matrix that presents a row-oriented interface that lets users read or modify entries...
KokkosSparse::CrsMatrix< impl_scalar_type, local_ordinal_type, device_type, void, typename local_graph_type::size_type > local_matrix_type
The specialization of Kokkos::CrsMatrix that represents the part of the sparse matrix on each MPI pro...
Teuchos::RCP< const map_type > getRangeMap() const override
The range Map of this Operator.
void applyTranspose(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X_in, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Y_in, Teuchos::ETransp mode, Scalar alpha, Scalar beta) const
Apply the transpose or conjugate transpose of the matrix to X_in, producing Y_in. ...
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
void putScalar(const Scalar &value)
Set all values in the multivector with the given value.
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > exportMV_
Row Map MultiVector used in apply().
void gaussSeidelCopy(MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &D, const Scalar &dampingFactor, const ESweepDirection direction, const int numSweeps) const
Version of gaussSeidel(), with fewer requirements on X.
One or more distributed dense vectors.
static bool debug()
Whether Tpetra is in debug mode.
Teuchos::RCP< const map_type > getDomainMap() const override
The domain Map of this Operator.
void apply(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=Teuchos::ScalarTraits< Scalar >::one(), Scalar beta=Teuchos::ScalarTraits< Scalar >::zero()) const override
Compute Y = beta*Y + alpha*Op(A)*X, where Op(A) is either A, , or .
bool hasTransposeApply() const override
Whether this Operator's apply() method can apply the transpose or conjugate transpose.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > importMV_
Column Map MultiVector used in apply().
~CrsMatrixMultiplyOp() override=default
Destructor (virtual for memory safety of derived classes).
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
CrsMatrixMultiplyOp(const Teuchos::RCP< const crs_matrix_type > &A)
Constructor.
LocalCrsMatrixOperator< Scalar, MatScalar, typename crs_matrix_type::device_type > localMultiply_
Implementation of local sparse matrix-vector multiply.
Insert new values that don't currently exist.
void scale(const Scalar &alpha)
Scale in place: this = alpha*this.
Abstract interface for operators (e.g., matrices and preconditioners).
const Teuchos::RCP< const crs_matrix_type > matrix_
The underlying CrsMatrix object.
ESweepDirection
Sweep direction for Gauss-Seidel or Successive Over-Relaxation (SOR).
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
dual_view_type::t_dev getLocalViewDevice() const
A local Kokkos::View of device memory.
size_t getNumVectors() const
Number of columns in the multivector.
Sum new values into existing values.
void modify_device()
Mark data as modified on the device side.
typename Node::device_type device_type
The Kokkos device type.
#define TPETRA_EFFICIENCY_WARNING(throw_exception_test, Exception, msg)
Print or throw an efficency warning.
bool isConstantStride() const
Whether this multivector has constant stride between columns.
Forward declaration of Tpetra::CrsMatrixMultiplyOp.
A parallel distribution of indices over processes.
void doExport(const SrcDistObject &source, const Export< LocalOrdinal, GlobalOrdinal, Node > &exporter, const CombineMode CM, const bool restrictedMode=false)
Export data into this object using an Export object ("forward mode").
A class for wrapping a CrsMatrix multiply in a Operator.
bool isDistributed() const
Whether this is a globally distributed object.
Stand-alone utility functions and macros.
void reduce()
Sum values of a locally replicated multivector across all processes.
Teuchos::RCP< CrsMatrixMultiplyOp< OpScalar, MatScalar, LocalOrdinal, GlobalOrdinal, Node > > createCrsMatrixMultiplyOp(const Teuchos::RCP< const CrsMatrix< MatScalar, LocalOrdinal, GlobalOrdinal, Node > > &A)
Non-member function to create a CrsMatrixMultiplyOp.
void applyNonTranspose(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X_in, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Y_in, Scalar alpha, Scalar beta) const
Apply the matrix (not its transpose) to X_in, producing Y_in.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.