42 #ifndef TPETRA_CRSMATRIXMULTIPLYOP_HPP
43 #define TPETRA_CRSMATRIXMULTIPLYOP_HPP
50 #include "Tpetra_CrsMatrix.hpp"
121 template <
class Scalar,
122 class MatScalar = Scalar,
124 class GlobalOrdinal = ::Tpetra::Details::DefaultTypes::global_ordinal_type,
127 public Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node>
164 Teuchos::ETransp mode = Teuchos::NO_TRANS,
165 Scalar alpha = Teuchos::ScalarTraits<Scalar>::one (),
166 Scalar beta = Teuchos::ScalarTraits<Scalar>::zero ())
const
168 TEUCHOS_TEST_FOR_EXCEPTION
169 (!
matrix_->isFillComplete (), std::runtime_error,
170 Teuchos::typeName (*
this) <<
"::apply(): underlying matrix is not fill-complete.");
171 TEUCHOS_TEST_FOR_EXCEPTION
173 Teuchos::typeName (*
this) <<
"::apply(X,Y): X and Y must have the same number of vectors.");
174 TEUCHOS_TEST_FOR_EXCEPTION
175 (Teuchos::ScalarTraits<Scalar>::isComplex && mode == Teuchos::TRANS, std::logic_error,
176 Teuchos::typeName (*
this) <<
"::apply() does not currently support transposed multiplications for complex scalar types.");
177 if (mode == Teuchos::NO_TRANS) {
228 const Scalar& dampingFactor,
230 const int numSweeps)
const
235 using Teuchos::rcpFromRef;
236 using Teuchos::rcp_const_cast;
242 TEUCHOS_TEST_FOR_EXCEPTION
243 (numSweeps < 0, std::invalid_argument,
244 "gaussSeidel: The number of sweeps must be nonnegative, "
245 "but you provided numSweeps = " << numSweeps <<
" < 0.");
250 if (direction == Forward) {
251 localDirection = Forward;
253 else if (direction == Backward) {
254 localDirection = Backward;
256 else if (direction == Symmetric) {
258 localDirection = Forward;
261 TEUCHOS_TEST_FOR_EXCEPTION
262 (
true, std::invalid_argument,
263 "gaussSeidel: The 'direction' enum does not have any of its valid "
264 "values: Forward, Backward, or Symmetric.");
267 if (numSweeps == 0) {
274 RCP<const import_type> importer =
matrix_->getGraph()->getImporter();
275 RCP<const export_type> exporter =
matrix_->getGraph()->getExporter();
276 TEUCHOS_TEST_FOR_EXCEPTION
277 (! exporter.is_null (), std::runtime_error,
278 "Tpetra's gaussSeidel implementation requires that the row, domain, "
279 "and range Maps be the same. This cannot be the case, because the "
280 "matrix has a nontrivial Export object.");
282 RCP<const map_type> domainMap =
matrix_->getDomainMap ();
283 RCP<const map_type> rangeMap =
matrix_->getRangeMap ();
284 RCP<const map_type> rowMap =
matrix_->getGraph ()->getRowMap ();
285 RCP<const map_type> colMap =
matrix_->getGraph ()->getColMap ();
292 TEUCHOS_TEST_FOR_EXCEPTION
293 (! X.
getMap ()->isSameAs (*domainMap), std::runtime_error,
294 "Tpetra::CrsMatrix::gaussSeidel requires that the input "
295 "multivector X be in the domain Map of the matrix.");
296 TEUCHOS_TEST_FOR_EXCEPTION
297 (! B.
getMap ()->isSameAs (*rangeMap), std::runtime_error,
298 "Tpetra::CrsMatrix::gaussSeidel requires that the input "
299 "B be in the range Map of the matrix.");
300 TEUCHOS_TEST_FOR_EXCEPTION
301 (! D.
getMap ()->isSameAs (*rowMap), std::runtime_error,
302 "Tpetra::CrsMatrix::gaussSeidel requires that the input "
303 "D be in the row Map of the matrix.");
304 TEUCHOS_TEST_FOR_EXCEPTION
305 (! rowMap->isSameAs (*rangeMap), std::runtime_error,
306 "Tpetra::CrsMatrix::gaussSeidel requires that the row Map and the "
307 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
308 TEUCHOS_TEST_FOR_EXCEPTION
309 (! domainMap->isSameAs (*rangeMap), std::runtime_error,
310 "Tpetra::CrsMatrix::gaussSeidel requires that the domain Map and "
311 "the range Map of the matrix be the same.");
320 RCP<const OSMV> B_in;
322 B_in = rcpFromRef (B);
329 RCP<OSMV> B_in_nonconst = getRowMapMultiVector (B,
true);
331 B_in = rcp_const_cast<
const OSMV> (B_in_nonconst);
335 "gaussSeidel: The current implementation of the Gauss-Seidel kernel "
336 "requires that X and B both have constant stride. Since B does not "
337 "have constant stride, we had to make a copy. This is a limitation of "
338 "the current implementation and not your fault, but we still report it "
339 "as an efficiency warning for your information.");
348 RCP<OSMV> X_domainMap;
350 bool copiedInput =
false;
352 if (importer.is_null ()) {
354 X_domainMap = rcpFromRef (X);
355 X_colMap = X_domainMap;
362 X_colMap = getColumnMapMultiVector (X,
true);
363 X_domainMap = X_colMap;
368 "gaussSeidel: The current implementation of the Gauss-Seidel kernel "
369 "requires that X and B both have constant stride. Since X does not "
370 "have constant stride, we had to make a copy. This is a limitation of "
371 "the current implementation and not your fault, but we still report it "
372 "as an efficiency warning for your information.");
377 X_domainMap = rcpFromRef (X);
381 X_colMap = X_domainMap->offsetViewNonConst (colMap, 0);
385 X_colMap->doImport (X, *importer,
INSERT);
393 X_colMap = getColumnMapMultiVector (X,
true);
394 X_domainMap = X_colMap->offsetViewNonConst (domainMap, 0);
395 X_colMap->doImport (X, *importer,
INSERT);
399 "gaussSeidel: The current implementation of the Gauss-Seidel kernel "
400 "requires that X and B both have constant stride. Since X does not "
401 "have constant stride, we had to make a copy. This is a limitation of "
402 "the current implementation and not your fault, but we still report it "
403 "as an efficiency warning for your information.");
407 for (
int sweep = 0; sweep < numSweeps; ++sweep) {
408 if (! importer.is_null () && sweep > 0) {
410 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
414 if (direction != Symmetric) {
415 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
420 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
424 if (! importer.is_null ()) {
425 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
427 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
466 const Scalar& dampingFactor,
468 const int numSweeps)
const
473 using Teuchos::rcpFromRef;
474 using Teuchos::rcp_const_cast;
480 TEUCHOS_TEST_FOR_EXCEPTION
481 (numSweeps < 0, std::invalid_argument,
482 "gaussSeidelCopy: The number of sweeps must be nonnegative, "
483 "but you provided numSweeps = " << numSweeps <<
" < 0.");
488 if (direction == Forward) {
489 localDirection = Forward;
491 else if (direction == Backward) {
492 localDirection = Backward;
494 else if (direction == Symmetric) {
496 localDirection = Forward;
499 TEUCHOS_TEST_FOR_EXCEPTION
500 (
true, std::invalid_argument,
501 "gaussSeidelCopy: The 'direction' enum does not have any of its "
502 "valid values: Forward, Backward, or Symmetric.");
505 if (numSweeps == 0) {
509 RCP<const import_type> importer =
matrix_->getGraph()->getImporter();
510 RCP<const export_type> exporter =
matrix_->getGraph()->getExporter();
511 TEUCHOS_TEST_FOR_EXCEPTION
512 (! exporter.is_null (),
514 "Tpetra's gaussSeidelCopy implementation requires that the row, domain, "
515 "and range Maps be the same. This cannot be the case, because the "
516 "matrix has a nontrivial Export object.");
518 RCP<const map_type> domainMap =
matrix_->getDomainMap ();
519 RCP<const map_type> rangeMap =
matrix_->getRangeMap ();
520 RCP<const map_type> rowMap =
matrix_->getGraph ()->getRowMap ();
521 RCP<const map_type> colMap =
matrix_->getGraph ()->getColMap ();
528 TEUCHOS_TEST_FOR_EXCEPTION
529 (! X.
getMap ()->isSameAs (*domainMap), std::runtime_error,
530 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
531 "multivector X be in the domain Map of the matrix.");
532 TEUCHOS_TEST_FOR_EXCEPTION
533 (! B.
getMap ()->isSameAs (*rangeMap), std::runtime_error,
534 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
535 "B be in the range Map of the matrix.");
536 TEUCHOS_TEST_FOR_EXCEPTION
537 (! D.
getMap ()->isSameAs (*rowMap), std::runtime_error,
538 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
539 "D be in the row Map of the matrix.");
540 TEUCHOS_TEST_FOR_EXCEPTION
541 (! rowMap->isSameAs (*rangeMap), std::runtime_error,
542 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the row Map and the "
543 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
544 TEUCHOS_TEST_FOR_EXCEPTION
545 (! domainMap->isSameAs (*rangeMap), std::runtime_error,
546 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the domain Map and "
547 "the range Map of the matrix be the same.");
559 RCP<OSMV> X_domainMap;
560 bool copyBackOutput =
false;
561 if (importer.is_null ()) {
563 X_colMap = rcpFromRef (X);
564 X_domainMap = rcpFromRef (X);
569 X_colMap = getColumnMapMultiVector (X,
true);
573 X_domainMap = X_colMap;
575 copyBackOutput =
true;
578 "gaussSeidelCopy: The current implementation of the Gauss-Seidel "
579 "kernel requires that X and B both have constant stride. Since X "
580 "does not have constant stride, we had to make a copy. This is a "
581 "limitation of the current implementation and not your fault, but we "
582 "still report it as an efficiency warning for your information.");
586 X_colMap = getColumnMapMultiVector (X);
587 X_domainMap = X_colMap->offsetViewNonConst (domainMap, 0);
597 X_colMap->doImport (X, *importer,
INSERT);
599 copyBackOutput =
true;
605 RCP<const OSMV> B_in;
607 B_in = rcpFromRef (B);
613 RCP<OSMV> B_in_nonconst = getRowMapMultiVector (B,
true);
615 B_in = rcp_const_cast<
const OSMV> (B_in_nonconst);
619 "gaussSeidelCopy: The current implementation requires that B have "
620 "constant stride. Since B does not have constant stride, we had to "
621 "copy it into a separate constant-stride multivector. This is a "
622 "limitation of the current implementation and not your fault, but we "
623 "still report it as an efficiency warning for your information.");
626 for (
int sweep = 0; sweep < numSweeps; ++sweep) {
627 if (! importer.is_null () && sweep > 0) {
629 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
633 if (direction != Symmetric) {
634 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
639 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
643 if (! importer.is_null ()) {
644 X_colMap->doImport (*X_domainMap, *importer,
INSERT);
646 matrix_->template localGaussSeidel<OS,OS> (*B_in, *X_colMap, D,
652 if (copyBackOutput) {
668 return matrix_->getDomainMap ();
673 return matrix_->getRangeMap ();
682 const Teuchos::RCP<const crs_matrix_type>
matrix_;
696 mutable Teuchos::RCP<MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
importMV_;
710 mutable Teuchos::RCP<MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
exportMV_;
717 Teuchos::ETransp mode,
721 typedef Teuchos::ScalarTraits<Scalar> ST;
724 const int myImageID = Teuchos::rank(*
matrix_->getComm());
730 Teuchos::RCP<const Import<LocalOrdinal,GlobalOrdinal,Node> > importer =
matrix_->getGraph()->getImporter();
731 Teuchos::RCP<const Export<LocalOrdinal,GlobalOrdinal,Node> > exporter =
matrix_->getGraph()->getExporter();
733 Teuchos::RCP<const MV> X;
737 Y_is_overwritten = (beta == ST::zero());
738 if (Y_is_replicated && myImageID > 0) {
745 X = Teuchos::rcp(
new MV(X_in));
749 X = Teuchos::rcp(&X_in,
false);
753 if (importer != null) {
759 if (exporter != null) {
767 if (exporter != null) {
778 if (importer != null) {
780 matrix_->template localMultiply<Scalar, Scalar>(*X, *
importMV_, mode, alpha, ST::zero());
781 if (Y_is_overwritten) Y_in.
putScalar(ST::zero());
782 else Y_in.
scale(beta);
794 matrix_->template localMultiply<Scalar, Scalar>(*X, Y, mode, alpha, beta);
798 matrix_->template localMultiply<Scalar, Scalar>(*X, Y_in, mode, alpha, beta);
802 if (Y_is_replicated) {
817 using Teuchos::rcp_const_cast;
818 using Teuchos::rcpFromRef;
821 typedef Teuchos::ScalarTraits<Scalar> STS;
823 if (alpha == STS::zero ()) {
824 if (beta == STS::zero ()) {
826 }
else if (beta != STS::one ()) {
841 RCP<const import_type> importer =
matrix_->getGraph()->getImporter();
842 RCP<const export_type> exporter =
matrix_->getGraph()->getExporter();
848 const bool Y_is_overwritten = (beta == STS::zero());
851 const bool Y_is_replicated =
861 if (Y_is_replicated &&
matrix_->getComm ()->getRank () > 0) {
868 RCP<const MV> X_colMap;
869 if (importer.is_null ()) {
877 RCP<MV> X_colMapNonConst = getColumnMapMultiVector (X_in,
true);
879 X_colMap = rcp_const_cast<
const MV> (X_colMapNonConst);
884 X_colMap = rcpFromRef (X_in);
888 ProfilingRegion regionImport (
"Tpetra::CrsMatrixMultiplyOp::apply: Import");
894 RCP<MV> X_colMapNonConst = getColumnMapMultiVector (X_in);
897 X_colMapNonConst->doImport (X_in, *importer,
INSERT);
898 X_colMap = rcp_const_cast<
const MV> (X_colMapNonConst);
905 RCP<MV> Y_rowMap = getRowMapMultiVector (Y_in);
912 if (! exporter.is_null ()) {
913 matrix_->template localMultiply<Scalar, Scalar> (*X_colMap, *Y_rowMap,
917 ProfilingRegion regionExport (
"Tpetra::CrsMatrixMultiplyOp::apply: Export");
923 if (Y_is_overwritten) {
950 Y_rowMap = getRowMapMultiVector (Y_in,
true);
954 if (beta != STS::zero ()) {
957 matrix_->template localMultiply<Scalar, Scalar> (*X_colMap,
964 matrix_->template localMultiply<Scalar, Scalar> (*X_colMap, Y_in,
974 if (Y_is_replicated) {
975 ProfilingRegion regionReduce (
"Tpetra::CrsMatrixMultiplyOp::apply: Reduce Y");
1002 const bool force =
false)
const
1004 using Teuchos::null;
1010 RCP<const import_type> importer =
matrix_->getGraph ()->getImporter ();
1011 RCP<const map_type> colMap =
matrix_->getColMap ();
1024 if (! importer.is_null () || force) {
1026 X_colMap = rcp (
new MV (colMap, numVecs));
1065 getRowMapMultiVector (
const MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y_rangeMap,
1066 const bool force =
false)
const
1068 using Teuchos::null;
1071 typedef Export<LocalOrdinal,GlobalOrdinal,Node> export_type;
1073 const size_t numVecs = Y_rangeMap.getNumVectors ();
1074 RCP<const export_type> exporter =
matrix_->getGraph ()->getExporter ();
1075 RCP<const map_type> rowMap =
matrix_->getRowMap ();
1087 if (! exporter.is_null () || force) {
1089 Y_rowMap = rcp (
new MV (rowMap, numVecs));
1107 template <
class OpScalar,
1110 class GlobalOrdinal,
1113 CrsMatrixMultiplyOp<OpScalar, MatScalar, LocalOrdinal, GlobalOrdinal, Node> >
1118 GlobalOrdinal, Node> op_type;
1119 return Teuchos::rcp (
new op_type (A));
1124 #endif // TPETRA_CRSMATRIXMULTIPLYOP_HPP
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
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
Compute Y = beta*Y + alpha*Op(A)*X, where Op(A) is either A, , or .
Sparse matrix that presents a row-oriented interface that lets users read or modify entries...
CrsMatrix< MatScalar, LocalOrdinal, GlobalOrdinal, Node > crs_matrix_type
The specialization of CrsMatrix which this class wraps.
Teuchos::RCP< const map_type > getDomainMap() const
The domain 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.
int local_ordinal_type
Default value of Scalar template parameter.
Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > importMV_
Column Map MultiVector used in apply().
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.
bool hasTransposeApply() const
Whether this Operator's apply() method can apply the transpose or conjugate transpose.
CrsMatrixMultiplyOp(const Teuchos::RCP< const crs_matrix_type > &A)
Constructor.
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.
Map< LocalOrdinal, GlobalOrdinal, Node > map_type
The specialization of Map which this class uses.
#define TPETRA_EFFICIENCY_WARNING(throw_exception_test, Exception, msg)
Print or throw an efficency warning.
::Kokkos::Compat::KokkosDeviceWrapperNode< execution_space > node_type
Default value of Node template parameter.
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< const map_type > getRangeMap() const
The range Map of this Operator.
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.
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 .
virtual ~CrsMatrixMultiplyOp()
Destructor (virtual for memory safety of derived classes).
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.