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...
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.
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.
size_t getNumVectors() const
Number of columns in the multivector.
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > exportMV_
Row Map MultiVector used in apply().
bool isConstantStride() const
Whether this multivector has constant stride between columns.
One or more distributed dense vectors.
bool isDistributed() const
Whether this is a globally distributed object.
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.
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...
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. ...
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.
Forward declaration of Tpetra::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.
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.
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.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
dual_view_type::t_dev getLocalViewDevice() const
A local Kokkos::View of device memory.
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 .
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.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.