10 #ifndef PACKAGES_XPETRA_SUP_UTILS_XPETRA_MATRIXMATRIX_DECL_HPP_
11 #define PACKAGES_XPETRA_SUP_UTILS_XPETRA_MATRIXMATRIX_DECL_HPP_
15 #include "Xpetra_BlockedCrsMatrix.hpp"
16 #include "Xpetra_CrsMatrixWrap.hpp"
17 #include "Xpetra_MapExtractor.hpp"
18 #include "Xpetra_Map.hpp"
19 #include "Xpetra_MatrixFactory.hpp"
20 #include "Xpetra_Matrix.hpp"
21 #include "Xpetra_StridedMapFactory.hpp"
22 #include "Xpetra_StridedMap.hpp"
24 #include "Xpetra_Helpers.hpp"
26 #ifdef HAVE_XPETRA_EPETRA
30 #ifdef HAVE_XPETRA_EPETRAEXT
31 #include <EpetraExt_MatrixMatrix.h>
32 #include <EpetraExt_RowMatrixOut.h>
33 #include <Epetra_RowMatrixTransposer.h>
34 #endif // HAVE_XPETRA_EPETRAEXT
36 #ifdef HAVE_XPETRA_TPETRA
37 #include <TpetraExt_MatrixMatrix.hpp>
38 #include <Tpetra_RowMatrixTransposer.hpp>
39 #include <MatrixMarket_Tpetra.hpp>
40 #include <Xpetra_TpetraCrsMatrix.hpp>
41 #include <Xpetra_TpetraBlockCrsMatrix.hpp>
42 #include <Tpetra_BlockCrsMatrix_Helpers.hpp>
43 #include <Xpetra_TpetraMultiVector.hpp>
44 #include <Xpetra_TpetraVector.hpp>
45 #endif // HAVE_XPETRA_TPETRA
49 template <
class Scalar,
54 #undef XPETRA_MATRIXMATRIX_SHORT
83 const Matrix& B,
bool transposeB,
85 bool call_FillComplete_on_result =
true,
86 bool doOptimizeStorage =
true,
87 const std::string& label = std::string(),
88 const RCP<ParameterList>& params = null);
112 static RCP<Matrix>
Multiply(
const Matrix& A,
bool transposeA,
const Matrix& B,
bool transposeB, RCP<Matrix> C_in,
113 Teuchos::FancyOStream& fos,
114 bool doFillComplete =
true,
115 bool doOptimizeStorage =
true,
116 const std::string& label = std::string(),
117 const RCP<ParameterList>& params = null);
129 static RCP<Matrix>
Multiply(
const Matrix& A,
bool transposeA,
const Matrix& B,
bool transposeB, Teuchos::FancyOStream& fos,
130 bool callFillCompleteOnResult =
true,
bool doOptimizeStorage =
true,
const std::string& label = std::string(),
131 const RCP<ParameterList>& params = null);
133 #ifdef HAVE_XPETRA_EPETRAEXT
136 const Epetra_CrsMatrix& epB,
137 Teuchos::FancyOStream& fos);
138 #endif // ifdef HAVE_XPETRA_EPETRAEXT
152 Teuchos::FancyOStream& fos,
153 bool doFillComplete =
true,
154 bool doOptimizeStorage =
true);
185 const Matrix& B,
bool transposeB,
const SC& beta,
186 RCP<Matrix>& C, Teuchos::FancyOStream& fos,
bool AHasFixedNnzPerRow =
false);
190 #ifdef HAVE_XPETRA_EPETRA
226 const Matrix& B,
bool transposeB,
228 bool call_FillComplete_on_result =
true,
229 bool doOptimizeStorage =
true,
230 const std::string& label = std::string(),
231 const RCP<ParameterList>& params = null) {
232 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
false && C.
getRowMap()->isSameAs(*A.
getRowMap()) ==
false,
234 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
true && C.
getRowMap()->isSameAs(*A.
getDomainMap()) ==
false,
240 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
245 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
246 helpers::epetraExtMult(A, transposeA, B, transposeB, C, haveMultiplyDoFillComplete);
251 #ifdef HAVE_XPETRA_TPETRA
252 #if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \
253 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT))))
256 if (helpers::isTpetraCrs(A) && helpers::isTpetraCrs(B) && helpers::isTpetraCrs(C)) {
258 const Tpetra::CrsMatrix<SC, LO, GO, NO>& tpA = helpers::Op2TpetraCrs(A);
259 const Tpetra::CrsMatrix<SC, LO, GO, NO>& tpB = helpers::Op2TpetraCrs(B);
260 Tpetra::CrsMatrix<SC, LO, GO, NO>& tpC = helpers::Op2NonConstTpetraCrs(C);
264 Tpetra::MatrixMatrix::Multiply(tpA, transposeA, tpB, transposeB, tpC, haveMultiplyDoFillComplete, label, params);
265 }
else if (helpers::isTpetraBlockCrs(A) && helpers::isTpetraBlockCrs(B)) {
270 if (!A.
getRowMap()->getComm()->getRank())
271 std::cout <<
"WARNING: Using inefficient BlockCrs Multiply Placeholder" << std::endl;
275 using CRS = Tpetra::CrsMatrix<SC, LO, GO, NO>;
276 RCP<const CRS> Acrs = Tpetra::convertToCrsMatrix(tpA);
277 RCP<const CRS> Bcrs = Tpetra::convertToCrsMatrix(tpB);
280 RCP<ParameterList> new_params;
281 if (!params.is_null()) {
282 new_params = rcp(
new Teuchos::ParameterList(*params));
283 new_params->set(
"compute global constants",
true);
287 RCP<CRS> tempAc = Teuchos::rcp(
new CRS(Acrs->getRowMap(), 0));
288 Tpetra::MatrixMatrix::Multiply(*Acrs, transposeA, *Bcrs, transposeB, *tempAc, haveMultiplyDoFillComplete, label, new_params);
291 RCP<Tpetra::BlockCrsMatrix<SC, LO, GO, NO> > Ac_t = Tpetra::convertToBlockCrsMatrix(*tempAc, A.
GetStorageBlockSize());
293 RCP<Xpetra::CrsMatrix<SC, LO, GO, NO> > Ac_p = Ac_x;
300 TEUCHOS_TEST_FOR_EXCEPTION(1,
Exceptions::RuntimeError,
"Mix-and-match Crs/BlockCrs Multiply not currently supported");
308 if (call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
309 RCP<Teuchos::ParameterList> fillParams = rcp(
new Teuchos::ParameterList());
310 fillParams->set(
"Optimize Storage", doOptimizeStorage);
317 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(A));
318 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(B));
319 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
345 const Matrix& B,
bool transposeB,
347 Teuchos::FancyOStream& fos,
348 bool doFillComplete =
true,
349 bool doOptimizeStorage =
true,
350 const std::string& label = std::string(),
351 const RCP<ParameterList>& params = null) {
357 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) && defined(HAVE_XPETRA_ML_MMM)
363 RCP<Matrix> C = Convert_Epetra_CrsMatrix_ToXpetra_CrsMatrixWrap<SC, LO, GO, NO>(epC);
364 if (doFillComplete) {
365 RCP<Teuchos::ParameterList> fillParams = rcp(
new Teuchos::ParameterList());
366 fillParams->set(
"Optimize Storage", doOptimizeStorage);
373 C->CreateView(
"stridedMaps", rcpFromRef(A), transposeA, rcpFromRef(B), transposeB);
377 #endif // EPETRA + EPETRAEXT + ML
380 RCP<Matrix> C = C_in;
382 if (C == Teuchos::null) {
383 double nnzPerRow = Teuchos::as<double>(0);
392 nnzPerRow *= nnzPerRow;
395 if (totalNnz < minNnz)
399 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
410 fos <<
"Reuse C pattern" << std::endl;
413 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
429 const Matrix& B,
bool transposeB,
430 Teuchos::FancyOStream& fos,
431 bool callFillCompleteOnResult =
true,
432 bool doOptimizeStorage =
true,
433 const std::string& label = std::string(),
434 const RCP<ParameterList>& params = null) {
435 return Multiply(A, transposeA, B, transposeB, Teuchos::null, fos, callFillCompleteOnResult, doOptimizeStorage, label, params);
438 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
441 const Epetra_CrsMatrix& epB,
442 Teuchos::FancyOStream& fos) {
443 #if defined(HAVE_XPETRA_ML_MMM) // Note: this is currently not supported
445 ML_Comm_Create(&comm);
446 fos <<
"****** USING ML's MATRIX MATRIX MULTIPLY ******" << std::endl;
449 const Epetra_MpiComm* Mcomm =
dynamic_cast<const Epetra_MpiComm*
>(&(epA.Comm()));
451 ML_Comm_Set_UsrComm(comm, Mcomm->GetMpiComm());
454 EpetraExt::CrsMatrix_SolverMap Atransform;
455 EpetraExt::CrsMatrix_SolverMap Btransform;
456 const Epetra_CrsMatrix& A = Atransform(const_cast<Epetra_CrsMatrix&>(epA));
457 const Epetra_CrsMatrix& B = Btransform(const_cast<Epetra_CrsMatrix&>(epB));
463 ML_Operator* ml_As = ML_Operator_Create(comm);
464 ML_Operator* ml_Bs = ML_Operator_Create(comm);
465 ML_Operator_WrapEpetraCrsMatrix(const_cast<Epetra_CrsMatrix*>(&A), ml_As);
466 ML_Operator_WrapEpetraCrsMatrix(const_cast<Epetra_CrsMatrix*>(&B), ml_Bs);
467 ML_Operator* ml_AtimesB = ML_Operator_Create(comm);
469 Teuchos::TimeMonitor tm(*Teuchos::TimeMonitor::getNewTimer(
"ML_2matmult kernel"));
470 ML_2matmult(ml_As, ml_Bs, ml_AtimesB, ML_CSR_MATRIX);
472 ML_Operator_Destroy(&ml_As);
473 ML_Operator_Destroy(&ml_Bs);
478 int N_local = ml_AtimesB->invec_leng;
479 ML_CommInfoOP* getrow_comm = ml_AtimesB->getrow->pre_comm;
481 ML_Comm* comm_AB = ml_AtimesB->comm;
482 if (N_local != B.DomainMap().NumMyElements())
487 for (
int i = 0; i < getrow_comm->N_neighbors; i++) {
488 N_rcvd += (getrow_comm->neighbors)[i].N_rcv;
489 N_send += (getrow_comm->neighbors)[i].N_send;
490 if (((getrow_comm->neighbors)[i].N_rcv != 0) &&
491 ((getrow_comm->neighbors)[i].rcv_list != NULL)) flag = 1;
495 std::vector<double> dtemp(N_local + N_rcvd + 1);
496 std::vector<int> cmap(N_local + N_rcvd + 1);
497 for (
int i = 0; i < N_local; ++i) {
498 cmap[i] = B.DomainMap().GID(i);
499 dtemp[i] = (double)cmap[i];
501 ML_cheap_exchange_bdry(&dtemp[0], getrow_comm, N_local, N_send, comm_AB);
504 const int neighbors = getrow_comm->N_neighbors;
505 for (
int i = 0; i < neighbors; i++) {
506 const int nrcv = getrow_comm->neighbors[i].N_rcv;
507 for (
int j = 0; j < nrcv; j++)
508 cmap[getrow_comm->neighbors[i].rcv_list[j]] = (
int)dtemp[count++];
511 for (
int i = 0; i < N_local + N_rcvd; ++i)
512 cmap[i] = (
int)dtemp[i];
517 Epetra_Map gcmap(-1, N_local + N_rcvd, &cmap[0], B.ColMap().IndexBase(), A.Comm());
524 const int myrowlength = A.RowMap().NumMyElements();
525 const Epetra_Map& rowmap = A.RowMap();
530 int educatedguess = 0;
531 for (
int i = 0; i < myrowlength; ++i) {
533 ML_get_matrix_row(ml_AtimesB, 1, &i, &allocated, &bindx, &val, &rowlength, 0);
534 if (rowlength > educatedguess)
535 educatedguess = rowlength;
539 RCP<Epetra_CrsMatrix> result = rcp(
new Epetra_CrsMatrix(::Copy, A.RangeMap(), gcmap, educatedguess,
false));
541 std::vector<int> gcid(educatedguess);
542 for (
int i = 0; i < myrowlength; ++i) {
543 const int grid = rowmap.GID(i);
545 ML_get_matrix_row(ml_AtimesB, 1, &i, &allocated, &bindx, &val, &rowlength, 0);
546 if (!rowlength)
continue;
547 if ((
int)gcid.size() < rowlength) gcid.resize(rowlength);
548 for (
int j = 0; j < rowlength; ++j) {
549 gcid[j] = gcmap.GID(bindx[j]);
553 int err = result->InsertGlobalValues(grid, rowlength, val, &gcid[0]);
554 if (err != 0 && err != 1) {
555 std::ostringstream errStr;
556 errStr <<
"Epetra_CrsMatrix::InsertGlobalValues returned err=" << err;
561 if (bindx) ML_free(bindx);
562 if (val) ML_free(val);
563 ML_Operator_Destroy(&ml_AtimesB);
564 ML_Comm_Destroy(&comm);
572 "No ML multiplication available. This feature is currently not supported by Xpetra.");
573 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
576 #endif // ifdef HAVE_XPETRA_EPETRAEXT
590 Teuchos::FancyOStream& fos,
591 bool doFillComplete =
true,
592 bool doOptimizeStorage =
true) {
594 "TwoMatrixMultiply for BlockedCrsMatrix not implemented for transposeA==true or transposeB==true");
603 RCP<BlockedCrsMatrix> C = rcp(
new BlockedCrsMatrix(rgmapextractor, domapextractor, 33 ));
605 for (
size_t i = 0; i < A.
Rows(); ++i) {
606 for (
size_t j = 0; j < B.
Cols(); ++j) {
609 for (
size_t l = 0; l < B.
Rows(); ++l) {
613 if (crmat1.is_null() || crmat2.is_null())
621 if (unwrap1.is_null() != unwrap2.is_null()) {
622 if (unwrap1 != Teuchos::null && unwrap1->Rows() == 1 && unwrap1->Cols() == 1)
624 if (unwrap2 != Teuchos::null && unwrap2->Rows() == 1 && unwrap2->Cols() == 1)
625 crmat2 = unwrap2->getCrsMatrix();
629 RCP<CrsMatrixWrap> crop1 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat1);
630 RCP<CrsMatrixWrap> crop2 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat2);
632 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
635 if (!crop1.is_null())
636 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
637 if (!crop2.is_null())
638 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
641 "crmat1 does not have global constants");
643 "crmat2 does not have global constants");
645 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
649 RCP<Matrix> temp = Teuchos::null;
651 if (crop1 != Teuchos::null && crop2 != Teuchos::null)
652 temp =
Multiply(*crop1,
false, *crop2,
false, fos);
654 RCP<BlockedCrsMatrix> bop1 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat1);
655 RCP<BlockedCrsMatrix> bop2 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat2);
656 TEUCHOS_TEST_FOR_EXCEPTION(bop1.is_null() ==
true,
Xpetra::Exceptions::BadCast,
"A is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
657 TEUCHOS_TEST_FOR_EXCEPTION(bop2.is_null() ==
true,
Xpetra::Exceptions::BadCast,
"B is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
658 TEUCHOS_TEST_FOR_EXCEPTION(bop1->Cols() != bop2->Rows(),
Xpetra::Exceptions::RuntimeError,
"A has " << bop1->Cols() <<
" columns and B has " << bop2->Rows() <<
" rows. Matrices are not compatible! (TwoMatrixMultiplyBlock)");
659 TEUCHOS_TEST_FOR_EXCEPTION(bop1->getDomainMap()->isSameAs(*(bop2->getRangeMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Domain map of A is not the same as range map of B. Matrices are not compatible! (TwoMatrixMultiplyBlock)");
662 temp =
TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
664 RCP<BlockedCrsMatrix> btemp = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(temp);
665 TEUCHOS_TEST_FOR_EXCEPTION(btemp->Rows() != bop1->Rows(),
Xpetra::Exceptions::RuntimeError,
"Number of block rows of local blocked operator is " << btemp->Rows() <<
" but should be " << bop1->Rows() <<
". (TwoMatrixMultiplyBlock)");
666 TEUCHOS_TEST_FOR_EXCEPTION(btemp->Cols() != bop2->Cols(),
Xpetra::Exceptions::RuntimeError,
"Number of block cols of local blocked operator is " << btemp->Cols() <<
" but should be " << bop2->Cols() <<
". (TwoMatrixMultiplyBlock)");
667 TEUCHOS_TEST_FOR_EXCEPTION(btemp->getRangeMapExtractor()->getFullMap()->isSameAs(*(bop1->getRangeMapExtractor()->getFullMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Range map of local blocked operator should be same as first operator. (TwoMatrixMultiplyBlock)");
668 TEUCHOS_TEST_FOR_EXCEPTION(btemp->getDomainMapExtractor()->getFullMap()->isSameAs(*(bop2->getDomainMapExtractor()->getFullMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Domain map of local blocked operator should be same as second operator. (TwoMatrixMultiplyBlock)");
669 TEUCHOS_TEST_FOR_EXCEPTION(btemp->getRangeMapExtractor()->getThyraMode() != bop1->getRangeMapExtractor()->getThyraMode(),
Xpetra::Exceptions::RuntimeError,
"Thyra mode of local range map extractor incompatible with range map extractor of A (TwoMatrixMultiplyBlock)");
670 TEUCHOS_TEST_FOR_EXCEPTION(btemp->getDomainMapExtractor()->getThyraMode() != bop2->getDomainMapExtractor()->getThyraMode(),
Xpetra::Exceptions::RuntimeError,
"Thyra mode of local domain map extractor incompatible with domain map extractor of B (TwoMatrixMultiplyBlock)");
675 RCP<Matrix> addRes = null;
684 if (!Cij.is_null()) {
685 if (Cij->isFillComplete())
688 C->setMatrix(i, j, Cij);
690 C->setMatrix(i, j, Teuchos::null);
715 "TwoMatrixAdd: matrix row maps are not the same.");
718 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
723 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, beta);
727 std::ostringstream buf;
732 #ifdef HAVE_XPETRA_TPETRA
733 #if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \
734 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT))))
740 Tpetra::MatrixMatrix::Add(tpA, transposeA, alpha, tpB, beta);
763 const Matrix& B,
bool transposeB,
const SC& beta,
764 RCP<Matrix>& C, Teuchos::FancyOStream& fos,
bool AHasFixedNnzPerRow =
false) {
766 RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
767 RCP<const Matrix> rcpB = Teuchos::rcpFromRef(B);
768 RCP<const BlockedCrsMatrix> rcpBopA = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpA);
769 RCP<const BlockedCrsMatrix> rcpBopB = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpB);
771 if (rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
777 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
778 const Epetra_CrsMatrix& epA = helpers::Op2EpetraCrs(A);
779 const Epetra_CrsMatrix& epB = helpers::Op2EpetraCrs(B);
783 size_t numLocalRows = 0;
790 if (maxNzInA == 1 || maxNzInB == 1 || AHasFixedNnzPerRow) {
793 Teuchos::ArrayRCP<size_t> exactNnzPerRow(numLocalRows);
795 if ((maxNzInA == 1 && maxNzInB > 1) || AHasFixedNnzPerRow) {
796 for (
size_t i = 0; i < numLocalRows; ++i)
800 for (
size_t i = 0; i < numLocalRows; ++i)
804 fos <<
"MatrixMatrix::TwoMatrixAdd : special case detected (one matrix has a fixed nnz per row)"
805 <<
", using static profiling" << std::endl;
814 fos <<
"MatrixMatrix::TwoMatrixAdd : ** WARNING ** estimate could be badly wrong because second summand is transposed" << std::endl;
816 RCP<Epetra_CrsMatrix> epC = helpers::Op2NonConstEpetraCrs(C);
817 Epetra_CrsMatrix* ref2epC = &*epC;
820 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, transposeB, beta, ref2epC);
828 #ifdef HAVE_XPETRA_TPETRA
829 #if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \
830 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT))))
833 using tcrs_matrix_type = Tpetra::CrsMatrix<SC, LO, GO, NO>;
834 const tcrs_matrix_type& tpA = helpers::Op2TpetraCrs(A);
835 const tcrs_matrix_type& tpB = helpers::Op2TpetraCrs(B);
836 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
844 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
845 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
849 else if (rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
850 RCP<const MapExtractor> rgmapextractor = rcpBopB->getRangeMapExtractor();
851 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
857 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
858 RCP<Matrix> Cij = Teuchos::null;
859 if (rcpA != Teuchos::null &&
860 rcpBopB->getMatrix(i, j) != Teuchos::null) {
863 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
864 Cij, fos, AHasFixedNnzPerRow);
865 }
else if (rcpA == Teuchos::null &&
866 rcpBopB->getMatrix(i, j) != Teuchos::null) {
867 Cij = rcpBopB->getMatrix(i, j);
868 }
else if (rcpA != Teuchos::null &&
869 rcpBopB->getMatrix(i, j) == Teuchos::null) {
870 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpA);
875 if (!Cij.is_null()) {
876 if (Cij->isFillComplete())
879 bC->setMatrix(i, j, Cij);
881 bC->setMatrix(i, j, Teuchos::null);
886 else if (rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
887 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
888 RCP<const MapExtractor> domapextractor = rcpBopA->getDomainMapExtractor();
894 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
895 RCP<Matrix> Cij = Teuchos::null;
896 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
897 rcpB != Teuchos::null) {
899 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
900 *rcpB, transposeB, beta,
901 Cij, fos, AHasFixedNnzPerRow);
902 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
903 rcpB != Teuchos::null) {
904 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpB);
905 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
906 rcpB == Teuchos::null) {
907 Cij = rcpBopA->getMatrix(i, j);
912 if (!Cij.is_null()) {
913 if (Cij->isFillComplete())
916 bC->setMatrix(i, j, Cij);
918 bC->setMatrix(i, j, Teuchos::null);
927 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->Rows() != rcpBopB->Rows(),
Xpetra::Exceptions::RuntimeError,
"A has " << rcpBopA->Rows() <<
" rows and B has " << rcpBopA->Rows() <<
" rows. Matrices are not compatible! (TwoMatrixAdd)");
928 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->Rows() != rcpBopB->Rows(),
Xpetra::Exceptions::RuntimeError,
"A has " << rcpBopA->Cols() <<
" cols and B has " << rcpBopA->Cols() <<
" cols. Matrices are not compatible! (TwoMatrixAdd)");
929 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->getRangeMap()->isSameAs(*(rcpBopB->getRangeMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Range map of A is not the same as range map of B. Matrices are not compatible! (TwoMatrixAdd)");
930 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->getDomainMap()->isSameAs(*(rcpBopB->getDomainMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Domain map of A is not the same as domain map of B. Matrices are not compatible! (TwoMatrixAdd)");
931 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->getRangeMapExtractor()->getThyraMode() != rcpBopB->getRangeMapExtractor()->getThyraMode(),
Xpetra::Exceptions::RuntimeError,
"Different Thyra/Xpetra style gids in RangeMapExtractor of A and B. Matrices are not compatible! (TwoMatrixAdd)");
932 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->getDomainMapExtractor()->getThyraMode() != rcpBopB->getDomainMapExtractor()->getThyraMode(),
Xpetra::Exceptions::RuntimeError,
"Different Thyra/Xpetra style gids in DomainMapExtractor of A and B. Matrices are not compatible! (TwoMatrixAdd)");
934 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
935 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
940 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
941 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
943 RCP<Matrix> Cij = Teuchos::null;
944 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
945 rcpBopB->getMatrix(i, j) != Teuchos::null) {
948 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
949 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
950 Cij, fos, AHasFixedNnzPerRow);
951 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
952 rcpBopB->getMatrix(i, j) != Teuchos::null) {
953 Cij = rcpBopB->getMatrix(i, j);
954 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
955 rcpBopB->getMatrix(i, j) == Teuchos::null) {
956 Cij = rcpBopA->getMatrix(i, j);
961 if (!Cij.is_null()) {
962 if (Cij->isFillComplete())
966 bC->setMatrix(i, j, Cij);
968 bC->setMatrix(i, j, Teuchos::null);
1012 const Matrix& B,
bool transposeB,
1014 bool call_FillComplete_on_result =
true,
1015 bool doOptimizeStorage =
true,
1016 const std::string& label = std::string(),
1017 const RCP<ParameterList>& params = null) {
1019 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
false && C.
getRowMap()->isSameAs(*A.
getRowMap()) ==
false,
1021 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
true && C.
getRowMap()->isSameAs(*A.
getDomainMap()) ==
false,
1027 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
1030 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
1031 helpers::epetraExtMult(A, transposeA, B, transposeB, C, haveMultiplyDoFillComplete);
1036 #ifdef HAVE_XPETRA_TPETRA
1037 #if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \
1038 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))))
1041 if (helpers::isTpetraCrs(A) && helpers::isTpetraCrs(B) && helpers::isTpetraCrs(C)) {
1043 const Tpetra::CrsMatrix<SC, LO, GO, NO>& tpA = helpers::Op2TpetraCrs(A);
1044 const Tpetra::CrsMatrix<SC, LO, GO, NO>& tpB = helpers::Op2TpetraCrs(B);
1045 Tpetra::CrsMatrix<SC, LO, GO, NO>& tpC = helpers::Op2NonConstTpetraCrs(C);
1049 Tpetra::MatrixMatrix::Multiply(tpA, transposeA, tpB, transposeB, tpC, haveMultiplyDoFillComplete, label, params);
1050 }
else if (helpers::isTpetraBlockCrs(A) && helpers::isTpetraBlockCrs(B)) {
1055 if (!A.
getRowMap()->getComm()->getRank())
1056 std::cout <<
"WARNING: Using inefficient BlockCrs Multiply Placeholder" << std::endl;
1060 using CRS = Tpetra::CrsMatrix<SC, LO, GO, NO>;
1061 RCP<const CRS> Acrs = Tpetra::convertToCrsMatrix(tpA);
1062 RCP<const CRS> Bcrs = Tpetra::convertToCrsMatrix(tpB);
1065 RCP<ParameterList> new_params;
1066 if (!params.is_null()) {
1067 new_params = rcp(
new Teuchos::ParameterList(*params));
1068 new_params->set(
"compute global constants",
true);
1072 RCP<CRS> tempAc = Teuchos::rcp(
new CRS(Acrs->getRowMap(), 0));
1073 Tpetra::MatrixMatrix::Multiply(*Acrs, transposeA, *Bcrs, transposeB, *tempAc, haveMultiplyDoFillComplete, label, new_params);
1076 RCP<Tpetra::BlockCrsMatrix<SC, LO, GO, NO> > Ac_t = Tpetra::convertToBlockCrsMatrix(*tempAc, A.
GetStorageBlockSize());
1078 RCP<Xpetra::CrsMatrix<SC, LO, GO, NO> > Ac_p = Ac_x;
1085 TEUCHOS_TEST_FOR_EXCEPTION(1,
Exceptions::RuntimeError,
"Mix-and-match Crs/BlockCrs Multiply not currently supported");
1094 if (call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
1095 RCP<Teuchos::ParameterList> fillParams = rcp(
new Teuchos::ParameterList());
1096 fillParams->set(
"Optimize Storage", doOptimizeStorage);
1103 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(A));
1104 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(B));
1105 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
1131 const Matrix& B,
bool transposeB,
1133 Teuchos::FancyOStream& fos,
1134 bool doFillComplete =
true,
1135 bool doOptimizeStorage =
true,
1136 const std::string& label = std::string(),
1137 const RCP<ParameterList>& params = null) {
1142 RCP<Matrix> C = C_in;
1144 if (C == Teuchos::null) {
1145 double nnzPerRow = Teuchos::as<double>(0);
1154 nnzPerRow *= nnzPerRow;
1157 if (totalNnz < minNnz)
1161 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
1171 fos <<
"Reuse C pattern" << std::endl;
1174 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
1190 const Matrix& B,
bool transposeB,
1191 Teuchos::FancyOStream& fos,
1192 bool callFillCompleteOnResult =
true,
1193 bool doOptimizeStorage =
true,
1194 const std::string& label = std::string(),
1195 const RCP<ParameterList>& params = null) {
1196 return Multiply(A, transposeA, B, transposeB, Teuchos::null, fos, callFillCompleteOnResult, doOptimizeStorage, label, params);
1199 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
1202 const Epetra_CrsMatrix& ,
1203 Teuchos::FancyOStream& ) {
1205 "No ML multiplication available. This feature is currently not supported by Xpetra.");
1206 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1208 #endif // ifdef HAVE_XPETRA_EPETRAEXT
1222 Teuchos::FancyOStream& fos,
1223 bool doFillComplete =
true,
1224 bool doOptimizeStorage =
true) {
1226 "TwoMatrixMultiply for BlockedCrsMatrix not implemented for transposeA==true or transposeB==true");
1235 RCP<BlockedCrsMatrix> C = rcp(
new BlockedCrsMatrix(rgmapextractor, domapextractor, 33 ));
1237 for (
size_t i = 0; i < A.
Rows(); ++i) {
1238 for (
size_t j = 0; j < B.
Cols(); ++j) {
1241 for (
size_t l = 0; l < B.
Rows(); ++l) {
1245 if (crmat1.is_null() || crmat2.is_null())
1253 if (unwrap1.is_null() != unwrap2.is_null()) {
1254 if (unwrap1 != Teuchos::null && unwrap1->Rows() == 1 && unwrap1->Cols() == 1)
1256 if (unwrap2 != Teuchos::null && unwrap2->Rows() == 1 && unwrap2->Cols() == 1)
1257 crmat2 = unwrap2->getCrsMatrix();
1261 RCP<CrsMatrixWrap> crop1 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat1);
1262 RCP<CrsMatrixWrap> crop2 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat2);
1264 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
1267 if (!crop1.is_null())
1268 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
1269 if (!crop2.is_null())
1270 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
1273 "crmat1 does not have global constants");
1275 "crmat2 does not have global constants");
1277 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
1281 RCP<Matrix> temp = Teuchos::null;
1283 if (crop1 != Teuchos::null && crop2 != Teuchos::null)
1284 temp =
Multiply(*crop1,
false, *crop2,
false, fos);
1286 RCP<BlockedCrsMatrix> bop1 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat1);
1287 RCP<BlockedCrsMatrix> bop2 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat2);
1288 TEUCHOS_TEST_FOR_EXCEPTION(bop1.is_null() ==
true,
Xpetra::Exceptions::BadCast,
"A is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
1289 TEUCHOS_TEST_FOR_EXCEPTION(bop2.is_null() ==
true,
Xpetra::Exceptions::BadCast,
"B is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
1290 TEUCHOS_TEST_FOR_EXCEPTION(bop1->Cols() != bop2->Rows(),
Xpetra::Exceptions::RuntimeError,
"A has " << bop1->Cols() <<
" columns and B has " << bop2->Rows() <<
" rows. Matrices are not compatible! (TwoMatrixMultiplyBlock)");
1291 TEUCHOS_TEST_FOR_EXCEPTION(bop1->getDomainMap()->isSameAs(*(bop2->getRangeMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Domain map of A is not the same as range map of B. Matrices are not compatible! (TwoMatrixMultiplyBlock)");
1294 temp =
TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
1296 RCP<BlockedCrsMatrix> btemp = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(temp);
1297 TEUCHOS_TEST_FOR_EXCEPTION(btemp->Rows() != bop1->Rows(),
Xpetra::Exceptions::RuntimeError,
"Number of block rows of local blocked operator is " << btemp->Rows() <<
" but should be " << bop1->Rows() <<
". (TwoMatrixMultiplyBlock)");
1298 TEUCHOS_TEST_FOR_EXCEPTION(btemp->Cols() != bop2->Cols(),
Xpetra::Exceptions::RuntimeError,
"Number of block cols of local blocked operator is " << btemp->Cols() <<
" but should be " << bop2->Cols() <<
". (TwoMatrixMultiplyBlock)");
1299 TEUCHOS_TEST_FOR_EXCEPTION(btemp->getRangeMapExtractor()->getFullMap()->isSameAs(*(bop1->getRangeMapExtractor()->getFullMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Range map of local blocked operator should be same as first operator. (TwoMatrixMultiplyBlock)");
1300 TEUCHOS_TEST_FOR_EXCEPTION(btemp->getDomainMapExtractor()->getFullMap()->isSameAs(*(bop2->getDomainMapExtractor()->getFullMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Domain map of local blocked operator should be same as second operator. (TwoMatrixMultiplyBlock)");
1301 TEUCHOS_TEST_FOR_EXCEPTION(btemp->getRangeMapExtractor()->getThyraMode() != bop1->getRangeMapExtractor()->getThyraMode(),
Xpetra::Exceptions::RuntimeError,
"Thyra mode of local range map extractor incompatible with range map extractor of A (TwoMatrixMultiplyBlock)");
1302 TEUCHOS_TEST_FOR_EXCEPTION(btemp->getDomainMapExtractor()->getThyraMode() != bop2->getDomainMapExtractor()->getThyraMode(),
Xpetra::Exceptions::RuntimeError,
"Thyra mode of local domain map extractor incompatible with domain map extractor of B (TwoMatrixMultiplyBlock)");
1307 RCP<Matrix> addRes = null;
1316 if (!Cij.is_null()) {
1317 if (Cij->isFillComplete())
1320 C->setMatrix(i, j, Cij);
1322 C->setMatrix(i, j, Teuchos::null);
1347 "TwoMatrixAdd: matrix row maps are not the same.");
1350 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
1355 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, beta);
1359 std::ostringstream buf;
1364 #ifdef HAVE_XPETRA_TPETRA
1365 #if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \
1366 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))))
1372 Tpetra::MatrixMatrix::Add(tpA, transposeA, alpha, tpB, beta);
1395 const Matrix& B,
bool transposeB,
const SC& beta,
1396 RCP<Matrix>& C, Teuchos::FancyOStream& fos,
bool AHasFixedNnzPerRow =
false) {
1397 RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
1398 RCP<const Matrix> rcpB = Teuchos::rcpFromRef(B);
1399 RCP<const BlockedCrsMatrix> rcpBopA = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpA);
1400 RCP<const BlockedCrsMatrix> rcpBopB = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpB);
1402 if (rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
1404 "TwoMatrixAdd: matrix row maps are not the same.");
1407 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
1411 size_t maxNzInA = 0;
1412 size_t maxNzInB = 0;
1413 size_t numLocalRows = 0;
1420 if (maxNzInA == 1 || maxNzInB == 1 || AHasFixedNnzPerRow) {
1423 Teuchos::ArrayRCP<size_t> exactNnzPerRow(numLocalRows);
1425 if ((maxNzInA == 1 && maxNzInB > 1) || AHasFixedNnzPerRow) {
1426 for (
size_t i = 0; i < numLocalRows; ++i)
1430 for (
size_t i = 0; i < numLocalRows; ++i)
1434 fos <<
"MatrixMatrix::TwoMatrixAdd : special case detected (one matrix has a fixed nnz per row)"
1435 <<
", using static profiling" << std::endl;
1444 fos <<
"MatrixMatrix::TwoMatrixAdd : ** WARNING ** estimate could be badly wrong because second summand is transposed" << std::endl;
1447 Epetra_CrsMatrix* ref2epC = &*epC;
1450 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, transposeB, beta, ref2epC);
1458 #ifdef HAVE_XPETRA_TPETRA
1459 #if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \
1460 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))))
1464 using tcrs_matrix_type = Tpetra::CrsMatrix<SC, LO, GO, NO>;
1467 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
1475 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
1476 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
1480 else if (rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
1481 RCP<const MapExtractor> rgmapextractor = rcpBopB->getRangeMapExtractor();
1482 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
1488 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
1489 RCP<Matrix> Cij = Teuchos::null;
1490 if (rcpA != Teuchos::null &&
1491 rcpBopB->getMatrix(i, j) != Teuchos::null) {
1494 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
1495 Cij, fos, AHasFixedNnzPerRow);
1496 }
else if (rcpA == Teuchos::null &&
1497 rcpBopB->getMatrix(i, j) != Teuchos::null) {
1498 Cij = rcpBopB->getMatrix(i, j);
1499 }
else if (rcpA != Teuchos::null &&
1500 rcpBopB->getMatrix(i, j) == Teuchos::null) {
1501 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpA);
1503 Cij = Teuchos::null;
1506 if (!Cij.is_null()) {
1507 if (Cij->isFillComplete())
1509 Cij->fillComplete();
1510 bC->setMatrix(i, j, Cij);
1512 bC->setMatrix(i, j, Teuchos::null);
1517 else if (rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
1518 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
1519 RCP<const MapExtractor> domapextractor = rcpBopA->getDomainMapExtractor();
1525 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
1526 RCP<Matrix> Cij = Teuchos::null;
1527 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
1528 rcpB != Teuchos::null) {
1530 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
1531 *rcpB, transposeB, beta,
1532 Cij, fos, AHasFixedNnzPerRow);
1533 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
1534 rcpB != Teuchos::null) {
1535 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpB);
1536 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
1537 rcpB == Teuchos::null) {
1538 Cij = rcpBopA->getMatrix(i, j);
1540 Cij = Teuchos::null;
1543 if (!Cij.is_null()) {
1544 if (Cij->isFillComplete())
1546 Cij->fillComplete();
1547 bC->setMatrix(i, j, Cij);
1549 bC->setMatrix(i, j, Teuchos::null);
1556 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA.is_null() ==
true,
Xpetra::Exceptions::BadCast,
"A is not a BlockedCrsMatrix. (TwoMatrixAdd)");
1557 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopB.is_null() ==
true,
Xpetra::Exceptions::BadCast,
"B is not a BlockedCrsMatrix. (TwoMatrixAdd)");
1558 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->Rows() != rcpBopB->Rows(),
Xpetra::Exceptions::RuntimeError,
"A has " << rcpBopA->Rows() <<
" rows and B has " << rcpBopA->Rows() <<
" rows. Matrices are not compatible! (TwoMatrixAdd)");
1559 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->Rows() != rcpBopB->Rows(),
Xpetra::Exceptions::RuntimeError,
"A has " << rcpBopA->Cols() <<
" cols and B has " << rcpBopA->Cols() <<
" cols. Matrices are not compatible! (TwoMatrixAdd)");
1560 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->getRangeMap()->isSameAs(*(rcpBopB->getRangeMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Range map of A is not the same as range map of B. Matrices are not compatible! (TwoMatrixAdd)");
1561 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->getDomainMap()->isSameAs(*(rcpBopB->getDomainMap())) ==
false,
Xpetra::Exceptions::RuntimeError,
"Domain map of A is not the same as domain map of B. Matrices are not compatible! (TwoMatrixAdd)");
1562 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->getRangeMapExtractor()->getThyraMode() != rcpBopB->getRangeMapExtractor()->getThyraMode(),
Xpetra::Exceptions::RuntimeError,
"Different Thyra/Xpetra style gids in RangeMapExtractor of A and B. Matrices are not compatible! (TwoMatrixAdd)");
1563 TEUCHOS_TEST_FOR_EXCEPTION(rcpBopA->getDomainMapExtractor()->getThyraMode() != rcpBopB->getDomainMapExtractor()->getThyraMode(),
Xpetra::Exceptions::RuntimeError,
"Different Thyra/Xpetra style gids in DomainMapExtractor of A and B. Matrices are not compatible! (TwoMatrixAdd)");
1565 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
1566 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
1571 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
1572 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
1574 RCP<Matrix> Cij = Teuchos::null;
1575 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
1576 rcpBopB->getMatrix(i, j) != Teuchos::null) {
1579 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
1580 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
1581 Cij, fos, AHasFixedNnzPerRow);
1582 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
1583 rcpBopB->getMatrix(i, j) != Teuchos::null) {
1584 Cij = rcpBopB->getMatrix(i, j);
1585 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
1586 rcpBopB->getMatrix(i, j) == Teuchos::null) {
1587 Cij = rcpBopA->getMatrix(i, j);
1589 Cij = Teuchos::null;
1592 if (!Cij.is_null()) {
1593 if (Cij->isFillComplete())
1596 Cij->fillComplete();
1597 bC->setMatrix(i, j, Cij);
1599 bC->setMatrix(i, j, Teuchos::null);
1608 #endif // HAVE_XPETRA_EPETRA
1612 #define XPETRA_MATRIXMATRIX_SHORT
std::string toString(Xpetra::UnderlyingLib lib)
Convert a Xpetra::UnderlyingLib to a std::string.
static void TwoMatrixAdd(const Matrix &A, bool transposeA, const SC &alpha, const Matrix &B, bool transposeB, const SC &beta, RCP< Matrix > &C, Teuchos::FancyOStream &fos, bool AHasFixedNnzPerRow=false)
Helper function to calculate C = alpha*A + beta*B.
static RCP< BlockedCrsMatrix > TwoMatrixMultiplyBlock(const BlockedCrsMatrix &A, bool transposeA, const BlockedCrsMatrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool doFillComplete=true, bool doOptimizeStorage=true)
Helper function to do matrix-matrix multiply "in-place".
virtual global_size_t getGlobalNumRows() const =0
Returns the number of global rows in this matrix.
RCP< const MapExtractor > getDomainMapExtractor() const
Returns map extractor for domain map.
static RCP< Matrix > Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, RCP< Matrix > C_in, Teuchos::FancyOStream &fos, bool doFillComplete=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
Helper function to do matrix-matrix multiply.
bool isFillComplete() const
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
Xpetra utility class containing transformation routines between Xpetra::Matrix and Epetra/Tpetra obje...
virtual const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
virtual void resumeFill(const RCP< ParameterList > ¶ms=null)=0
virtual LocalOrdinal GetStorageBlockSize() const =0
Returns the block size of the storage mechanism, which is usually 1, except for Tpetra::BlockCrsMatri...
Exception throws to report errors in the internal logical of the program.
static RCP< BlockedCrsMatrix > TwoMatrixMultiplyBlock(const BlockedCrsMatrix &A, bool transposeA, const BlockedCrsMatrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool doFillComplete=true, bool doOptimizeStorage=true)
Helper function to do matrix-matrix multiply "in-place".
virtual size_t Cols() const
number of column blocks
static RCP< const Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2TpetraCrs(RCP< Matrix > Op)
const RCP< const Map > getDomainMap() const
Returns the Map associated with the domain of this operator.
Exception indicating invalid cast attempted.
virtual void fillComplete(const RCP< const Map > &domainMap, const RCP< const Map > &rangeMap, const RCP< ParameterList > ¶ms=null)=0
Signal that data entry is complete, specifying domain and range maps.
static void TwoMatrixAdd(const Matrix &A, bool transposeA, const SC &alpha, const Matrix &B, bool transposeB, const SC &beta, RCP< Matrix > &C, Teuchos::FancyOStream &fos, bool AHasFixedNnzPerRow=false)
Helper function to calculate C = alpha*A + beta*B.
static RCP< Epetra_CrsMatrix > MLTwoMatrixMultiply(const Epetra_CrsMatrix &, const Epetra_CrsMatrix &, Teuchos::FancyOStream &)
bool IsView(const viewLabel_t viewLabel) const
virtual bool isFillComplete() const =0
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
void CreateView(viewLabel_t viewLabel, const RCP< const Map > &rowMap, const RCP< const Map > &colMap)
static void Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Matrix &C, bool call_FillComplete_on_result=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
static RCP< Epetra_CrsMatrix > MLTwoMatrixMultiply(const Epetra_CrsMatrix &epA, const Epetra_CrsMatrix &epB, Teuchos::FancyOStream &fos)
static RCP< Matrix > Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, RCP< Matrix > C_in, Teuchos::FancyOStream &fos, bool doFillComplete=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
Helper function to do matrix-matrix multiply.
virtual size_t Rows() const
number of row blocks
const RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
virtual const Teuchos::RCP< const map_type > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y...
static RCP< Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2NonConstTpetraCrs(RCP< Matrix > Op)
virtual size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const =0
Returns the current number of entries on this node in the specified local row.
static void Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Matrix &C, bool call_FillComplete_on_result=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
virtual size_t getLocalNumRows() const =0
Returns the number of matrix rows owned on the calling node.
RCP< const MapExtractor > getRangeMapExtractor() const
Returns map extractor class for range map.
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
Tpetra::KokkosCompat::KokkosSerialWrapperNode EpetraNode
void replaceCrsMatrix(RCP< CrsMatrix > &M)
Expert only.
static RCP< Matrix > Build(const RCP< const Map > &rowMap)
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
static RCP< const Epetra_CrsMatrix > Op2EpetraCrs(RCP< Matrix > Op)
Exception throws to report incompatible objects (like maps).
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
virtual global_size_t getGlobalNumEntries() const =0
Returns the global number of entries in this matrix.
Concrete implementation of Xpetra::Matrix.
virtual const Teuchos::RCP< const map_type > getDomainMap() const =0
The Map associated with the domain of this operator, which must be compatible with X...
virtual size_t getLocalMaxNumRowEntries() const =0
Returns the maximum number of entries across all rows/columns on this node.
static RCP< const Tpetra::BlockCrsMatrix< SC, LO, GO, NO > > Op2TpetraBlockCrs(RCP< Matrix > Op)
static RCP< Epetra_CrsMatrix > MLTwoMatrixMultiply(const Epetra_CrsMatrix &epA, const Epetra_CrsMatrix &epB, Teuchos::FancyOStream &fos)
static void Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Matrix &C, bool call_FillComplete_on_result=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
static RCP< BlockedCrsMatrix > TwoMatrixMultiplyBlock(const BlockedCrsMatrix &A, bool transposeA, const BlockedCrsMatrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool doFillComplete=true, bool doOptimizeStorage=true)
Helper function to do matrix-matrix multiply "in-place".
static RCP< Epetra_CrsMatrix > Op2NonConstEpetraCrs(RCP< Matrix > Op)
Teuchos::RCP< Matrix > getCrsMatrix() const
return unwrap 1x1 blocked operators
static RCP< Matrix > Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool callFillCompleteOnResult=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
Helper function to do matrix-matrix multiply.
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
Xpetra-specific matrix class.
static RCP< Matrix > Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool callFillCompleteOnResult=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
Helper function to do matrix-matrix multiply.