48 #ifndef PACKAGES_XPETRA_SUP_UTILS_XPETRA_MATRIXMATRIX_HPP_ 49 #define PACKAGES_XPETRA_SUP_UTILS_XPETRA_MATRIXMATRIX_HPP_ 54 #include "Xpetra_CrsMatrixWrap.hpp" 55 #include "Xpetra_MapExtractor.hpp" 56 #include "Xpetra_Map.hpp" 59 #include "Xpetra_StridedMapFactory.hpp" 60 #include "Xpetra_StridedMap.hpp" 64 #ifdef HAVE_XPETRA_EPETRA 68 #ifdef HAVE_XPETRA_EPETRAEXT 69 #include <EpetraExt_MatrixMatrix.h> 70 #include <EpetraExt_RowMatrixOut.h> 71 #include <Epetra_RowMatrixTransposer.h> 72 #endif // HAVE_XPETRA_EPETRAEXT 74 #ifdef HAVE_XPETRA_TPETRA 75 #include <TpetraExt_MatrixMatrix.hpp> 76 #include <Tpetra_RowMatrixTransposer.hpp> 77 #include <MatrixMarket_Tpetra.hpp> 78 #include <Xpetra_TpetraCrsMatrix.hpp> 79 #include <Xpetra_TpetraMultiVector.hpp> 80 #include <Xpetra_TpetraVector.hpp> 81 #endif // HAVE_XPETRA_TPETRA 91 template <
class Scalar,
92 class LocalOrdinal = int,
93 class GlobalOrdinal = LocalOrdinal,
100 #ifdef HAVE_XPETRA_EPETRA 103 RCP<const CrsMatrixWrap> crsOp = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(Op);
105 "Cast from Xpetra::Matrix to Xpetra::CrsMatrixWrap failed");
107 RCP<const CrsMatrix> tmp_CrsMtx = crsOp->getCrsMatrix();
108 const RCP<const EpetraCrsMatrixT<GO,NO> > &tmp_ECrsMtx = Teuchos::rcp_dynamic_cast<
const EpetraCrsMatrixT<GO,NO> >(tmp_CrsMtx);
110 "Cast from Xpetra::CrsMatrix to Xpetra::EpetraCrsMatrix failed");
112 return tmp_ECrsMtx->getEpetra_CrsMatrix();
116 RCP<Epetra_CrsMatrix> A;
118 RCP<const CrsMatrixWrap> crsOp = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(Op);
120 "Cast from Xpetra::Matrix to Xpetra::CrsMatrixWrap failed");
122 RCP<const CrsMatrix> tmp_CrsMtx = crsOp->getCrsMatrix();
123 const RCP<const EpetraCrsMatrixT<GO,NO> > &tmp_ECrsMtx = Teuchos::rcp_dynamic_cast<
const EpetraCrsMatrixT<GO,NO> >(tmp_CrsMtx);
124 TEUCHOS_TEST_FOR_EXCEPTION(tmp_ECrsMtx == Teuchos::null,
Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::EpetraCrsMatrix failed");
126 return tmp_ECrsMtx->getEpetra_CrsMatrixNonConst();
134 const RCP<const EpetraCrsMatrixT<GO,NO> > &tmp_ECrsMtx = Teuchos::rcp_dynamic_cast<
const EpetraCrsMatrixT<GO,NO> >(tmp_CrsMtx);
136 "Cast from Xpetra::CrsMatrix to Xpetra::EpetraCrsMatrix failed");
138 return *tmp_ECrsMtx->getEpetra_CrsMatrix();
146 RCP<Epetra_CrsMatrix> A;
151 const RCP<const EpetraCrsMatrixT<GO,NO> > &tmp_ECrsMtx = Teuchos::rcp_dynamic_cast<
const EpetraCrsMatrixT<GO,NO> >(tmp_CrsMtx);
152 TEUCHOS_TEST_FOR_EXCEPTION(tmp_ECrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::EpetraCrsMatrix failed");
154 return *Teuchos::rcp_const_cast<Epetra_CrsMatrix>(tmp_ECrsMtx->getEpetra_CrsMatrix());
160 #endif // HAVE_XPETRA_EPETRA 162 #ifdef HAVE_XPETRA_TPETRA 163 static RCP<const Tpetra::CrsMatrix<SC,LO,GO,NO> >
Op2TpetraCrs(RCP<Matrix> Op) {
165 RCP<const CrsMatrixWrap> crsOp = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(Op);
166 TEUCHOS_TEST_FOR_EXCEPTION(crsOp == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::Matrix to Xpetra::CrsMatrixWrap failed");
168 RCP<const CrsMatrix> tmp_CrsMtx = crsOp->getCrsMatrix();
170 TEUCHOS_TEST_FOR_EXCEPTION(tmp_ECrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::TpetraCrsMatrix failed");
172 return tmp_ECrsMtx->getTpetra_CrsMatrix();
177 RCP<const CrsMatrixWrap> crsOp = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(Op);
178 TEUCHOS_TEST_FOR_EXCEPTION(crsOp == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::Matrix to Xpetra::CrsMatrixWrap failed");
179 RCP<const CrsMatrix> tmp_CrsMtx = crsOp->getCrsMatrix();
181 TEUCHOS_TEST_FOR_EXCEPTION(tmp_ECrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::TpetraCrsMatrix failed");
183 return tmp_ECrsMtx->getTpetra_CrsMatrixNonConst();
192 TEUCHOS_TEST_FOR_EXCEPTION(tmp_TCrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::TpetraCrsMatrix failed");
194 return *tmp_TCrsMtx->getTpetra_CrsMatrix();
207 TEUCHOS_TEST_FOR_EXCEPTION(tmp_TCrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::TpetraCrsMatrix failed");
209 return *Teuchos::rcp_const_cast<Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tmp_TCrsMtx->getTpetra_CrsMatrix());
215 #endif // HAVE_XPETRA_TPETRA 217 #ifdef HAVE_XPETRA_TPETRA 220 const tcrs_matrix_type& A,
bool transposeA,
const typename tcrs_matrix_type::scalar_type alpha,
221 const tcrs_matrix_type& B,
bool transposeB,
const typename tcrs_matrix_type::scalar_type beta)
223 using Teuchos::Array;
226 using Teuchos::rcp_implicit_cast;
227 using Teuchos::rcpFromRef;
228 using Teuchos::ParameterList;
232 using transposer_type = Tpetra::RowMatrixTransposer<SC,LO,GO,NO>;
233 using import_type = Tpetra::Import<LO,GO,NO>;
234 RCP<const tcrs_matrix_type> Aprime = rcpFromRef(A);
236 Aprime = transposer_type(Aprime).createTranspose();
238 if(A.isFillComplete() && B.isFillComplete())
240 RCP<tcrs_matrix_type> C = rcp(
new tcrs_matrix_type(Aprime->getRowMap(), 0));
241 RCP<ParameterList> addParams = rcp(
new ParameterList);
242 addParams->set(
"Call fillComplete",
false);
244 Tpetra::MatrixMatrix::add<SC,LO,GO,NO>(beta, transposeB, B, alpha,
false, *Aprime, *C, Teuchos::null, Teuchos::null, addParams);
245 return rcp_implicit_cast<
Matrix>(rcp(
new CrsWrap(rcp_implicit_cast<CrsType>(rcp(
new XTCrsType(C))))));
253 RCP<const tcrs_matrix_type> Bprime = rcpFromRef(B);
255 Bprime = transposer_type(Bprime).createTranspose();
257 if(!(Aprime->getRowMap()->isSameAs(*(Bprime->getRowMap()))))
259 auto import = rcp(
new import_type(Bprime->getRowMap(), Aprime->getRowMap()));
260 Bprime = Tpetra::importAndFillCompleteCrsMatrix<tcrs_matrix_type>(Bprime, *
import, Aprime->getDomainMap(), Aprime->getRangeMap());
263 LO numLocalRows = Aprime->getNodeNumRows();
264 Array<size_t> allocPerRow(numLocalRows);
266 for(
LO i = 0; i < numLocalRows; i++)
268 allocPerRow[i] = Aprime->getNumEntriesInLocalRow(i) + Bprime->getNumEntriesInLocalRow(i);
271 RCP<tcrs_matrix_type> C = rcp(
new tcrs_matrix_type(Aprime->getRowMap(), allocPerRow(), Tpetra::StaticProfile));
273 Tpetra::MatrixMatrix::Add<SC,LO,GO,NO>(
274 *Aprime,
false, alpha,
275 *Bprime,
false, beta,
277 return rcp(
new CrsWrap(rcp_implicit_cast<CrsType>(rcp(
new XTCrsType(C)))));
282 #ifdef HAVE_XPETRA_EPETRAEXT 290 const Epetra_Map& Crowmap = epC.RowMap();
292 Epetra_CrsMatrix Ctemp(::Copy, Crowmap, 0,
false);
293 if(fillCompleteResult) {
294 errCode = EpetraExt::MatrixMatrix::Multiply(epA, transposeA, epB, transposeB, Ctemp,
true);
301 errCode = EpetraExt::MatrixMatrix::Multiply(epA, transposeA, epB, transposeB, Ctemp,
false);
303 int numLocalRows = Crowmap.NumMyElements();
304 long long* globalElementList =
nullptr;
305 Crowmap.MyGlobalElementsPtr(globalElementList);
306 Teuchos::Array<int> entriesPerRow(numLocalRows, 0);
307 for(
int i = 0; i < numLocalRows; i++)
309 entriesPerRow[i] = Ctemp.NumGlobalEntries(globalElementList[i]);
312 epC = Epetra_CrsMatrix(::Copy, Crowmap, entriesPerRow.data(),
true);
313 for(
int i = 0; i < numLocalRows; i++)
315 int gid = globalElementList[i];
319 Ctemp.ExtractGlobalRowView(gid, numEntries, values, inds);
320 epC.InsertGlobalValues(gid, numEntries, values, inds);
325 std::ostringstream buf;
327 std::string msg =
"EpetraExt::MatrixMatrix::Multiply returned nonzero error code " + buf.str();
334 template <
class Scalar,
336 class GlobalOrdinal ,
339 #undef XPETRA_MATRIXMATRIX_SHORT 369 const Matrix& B,
bool transposeB,
371 bool call_FillComplete_on_result =
true,
372 bool doOptimizeStorage =
true,
373 const std::string & label = std::string(),
374 const RCP<ParameterList>& params = null) {
376 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
false && C.
getRowMap()->isSameAs(*A.
getRowMap()) ==
false,
378 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
true && C.
getRowMap()->isSameAs(*A.
getDomainMap()) ==
false,
384 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
387 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 388 throw(
Xpetra::Exceptions::RuntimeError(
"Xpetra::MatrixMatrix::Multiply only available for GO=int or GO=long long with EpetraNode (Serial or OpenMP depending on configuration)"));
394 #ifdef HAVE_XPETRA_TPETRA 401 Tpetra::MatrixMatrix::Multiply(tpA, transposeA, tpB, transposeB, tpC, haveMultiplyDoFillComplete, label, params);
407 if (call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
408 RCP<Teuchos::ParameterList> fillParams = rcp(
new Teuchos::ParameterList());
409 fillParams->set(
"Optimize Storage", doOptimizeStorage);
416 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(A));
417 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(B));
418 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
443 static RCP<Matrix>
Multiply(
const Matrix& A,
bool transposeA,
const Matrix& B,
bool transposeB, RCP<Matrix> C_in,
444 Teuchos::FancyOStream& fos,
445 bool doFillComplete =
true,
446 bool doOptimizeStorage =
true,
447 const std::string & label = std::string(),
448 const RCP<ParameterList>& params = null) {
454 RCP<Matrix> C = C_in;
456 if (C == Teuchos::null) {
457 double nnzPerRow = Teuchos::as<double>(0);
466 nnzPerRow *= nnzPerRow;
469 if (totalNnz < minNnz)
473 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
481 fos <<
"Reuse C pattern" << std::endl;
484 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
499 static RCP<Matrix>
Multiply(
const Matrix& A,
bool transposeA,
const Matrix& B,
bool transposeB, Teuchos::FancyOStream &fos,
500 bool callFillCompleteOnResult =
true,
bool doOptimizeStorage =
true,
const std::string& label = std::string(),
501 const RCP<ParameterList>& params = null) {
502 return Multiply(A, transposeA, B, transposeB, Teuchos::null, fos, callFillCompleteOnResult, doOptimizeStorage, label, params);
505 #ifdef HAVE_XPETRA_EPETRAEXT 508 const Epetra_CrsMatrix& epB,
509 Teuchos::FancyOStream& fos) {
510 throw(
Xpetra::Exceptions::RuntimeError(
"MLTwoMatrixMultiply only available for GO=int or GO=long long with EpetraNode (Serial or OpenMP depending on configuration)"));
511 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
513 #endif //ifdef HAVE_XPETRA_EPETRAEXT 527 Teuchos::FancyOStream& fos,
528 bool doFillComplete =
true,
529 bool doOptimizeStorage =
true) {
531 "TwoMatrixMultiply for BlockedCrsMatrix not implemented for transposeA==true or transposeB==true");
540 RCP<BlockedCrsMatrix> C = rcp(
new BlockedCrsMatrix(rgmapextractor, domapextractor, 33 ));
542 for (
size_t i = 0; i < A.
Rows(); ++i) {
543 for (
size_t j = 0; j < B.
Cols(); ++j) {
546 for (
size_t l = 0; l < B.
Rows(); ++l) {
550 if (crmat1.is_null() || crmat2.is_null())
553 RCP<CrsMatrixWrap> crop1 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat1);
554 RCP<CrsMatrixWrap> crop2 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat2);
556 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
559 if (!crop1.is_null())
560 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
561 if (!crop2.is_null())
562 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
565 "crmat1 does not have global constants");
567 "crmat2 does not have global constants");
569 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
573 RCP<Matrix> temp = Teuchos::null;
575 if(crop1 != Teuchos::null && crop2 != Teuchos::null)
576 temp =
Multiply (*crop1,
false, *crop2,
false, fos);
578 RCP<BlockedCrsMatrix> bop1 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat1);
579 RCP<BlockedCrsMatrix> bop2 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat2);
580 TEUCHOS_TEST_FOR_EXCEPTION(bop1.is_null()==
true,
Xpetra::Exceptions::BadCast,
"A is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
581 TEUCHOS_TEST_FOR_EXCEPTION(bop2.is_null()==
true,
Xpetra::Exceptions::BadCast,
"B is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
582 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)");
583 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)");
586 temp =
TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
588 RCP<BlockedCrsMatrix> btemp = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(temp);
589 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)");
590 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)");
591 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)");
592 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)");
593 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)");
594 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)");
599 RCP<Matrix> addRes = null;
608 if (!Cij.is_null()) {
609 if (Cij->isFillComplete())
612 C->setMatrix(i, j, Cij);
614 C->setMatrix(i, j, Teuchos::null);
642 throw Exceptions::RuntimeError(
"TwoMatrixAdd for Epetra matrices needs <double,int,int> for Scalar, LocalOrdinal and GlobalOrdinal.");
644 #ifdef HAVE_XPETRA_TPETRA 648 Tpetra::MatrixMatrix::Add(tpA, transposeA, alpha, tpB, beta);
669 const Matrix& B,
bool transposeB,
const SC& beta,
670 RCP<Matrix>& C, Teuchos::FancyOStream &fos,
bool AHasFixedNnzPerRow =
false) {
672 RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
673 RCP<const Matrix> rcpB = Teuchos::rcpFromRef(B);
674 RCP<const BlockedCrsMatrix> rcpBopA = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpA);
675 RCP<const BlockedCrsMatrix> rcpBopB = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpB);
683 if(rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
689 #ifdef HAVE_XPETRA_TPETRA 690 using tcrs_matrix_type = Tpetra::CrsMatrix<SC,LO,GO,NO>;
692 const tcrs_matrix_type& tpA = helpers::Op2TpetraCrs(A);
693 const tcrs_matrix_type& tpB = helpers::Op2TpetraCrs(B);
694 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
700 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
701 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
705 else if(rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
706 RCP<const MapExtractor> rgmapextractor = rcpBopB->getRangeMapExtractor();
707 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
713 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
714 RCP<Matrix> Cij = Teuchos::null;
715 if(rcpA != Teuchos::null &&
716 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
719 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
720 Cij, fos, AHasFixedNnzPerRow);
721 }
else if (rcpA == Teuchos::null &&
722 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
723 Cij = rcpBopB->getMatrix(i,j);
724 }
else if (rcpA != Teuchos::null &&
725 rcpBopB->getMatrix(i,j)==Teuchos::null) {
726 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpA);
731 if (!Cij.is_null()) {
732 if (Cij->isFillComplete())
735 bC->setMatrix(i, j, Cij);
737 bC->setMatrix(i, j, Teuchos::null);
742 else if(rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
743 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
744 RCP<const MapExtractor> domapextractor = rcpBopA->getDomainMapExtractor();
749 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
750 RCP<Matrix> Cij = Teuchos::null;
751 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
752 rcpB!=Teuchos::null) {
754 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
755 *rcpB, transposeB, beta,
756 Cij, fos, AHasFixedNnzPerRow);
757 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
758 rcpB!=Teuchos::null) {
759 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpB);
760 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
761 rcpB==Teuchos::null) {
762 Cij = rcpBopA->getMatrix(i,j);
767 if (!Cij.is_null()) {
768 if (Cij->isFillComplete())
771 bC->setMatrix(i, j, Cij);
773 bC->setMatrix(i, j, Teuchos::null);
783 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)");
784 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)");
785 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)");
786 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)");
787 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)");
788 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)");
790 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
791 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
795 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
796 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
798 RCP<Matrix> Cij = Teuchos::null;
799 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
800 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
802 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
803 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
804 Cij, fos, AHasFixedNnzPerRow);
805 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
806 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
807 Cij = rcpBopB->getMatrix(i,j);
808 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
809 rcpBopB->getMatrix(i,j)==Teuchos::null) {
810 Cij = rcpBopA->getMatrix(i,j);
815 if (!Cij.is_null()) {
816 if (Cij->isFillComplete())
819 bC->setMatrix(i, j, Cij);
821 bC->setMatrix(i, j, Teuchos::null);
833 #ifdef HAVE_XPETRA_EPETRA 870 const Matrix& B,
bool transposeB,
872 bool call_FillComplete_on_result =
true,
873 bool doOptimizeStorage =
true,
874 const std::string & label = std::string(),
875 const RCP<ParameterList>& params = null) {
876 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
false && C.
getRowMap()->isSameAs(*A.
getRowMap()) ==
false,
878 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
true && C.
getRowMap()->isSameAs(*A.
getDomainMap()) ==
false,
884 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
889 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 890 helpers::epetraExtMult(A, transposeA, B, transposeB, C, haveMultiplyDoFillComplete);
895 #ifdef HAVE_XPETRA_TPETRA 896 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \ 897 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT)))) 900 const Tpetra::CrsMatrix<SC,LO,GO,NO> & tpA = helpers::Op2TpetraCrs(A);
901 const Tpetra::CrsMatrix<SC,LO,GO,NO> & tpB = helpers::Op2TpetraCrs(B);
902 Tpetra::CrsMatrix<SC,LO,GO,NO> & tpC = helpers::Op2NonConstTpetraCrs(C);
906 Tpetra::MatrixMatrix::Multiply(tpA, transposeA, tpB, transposeB, tpC, haveMultiplyDoFillComplete, label, params);
913 if (call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
914 RCP<Teuchos::ParameterList> fillParams = rcp(
new Teuchos::ParameterList());
915 fillParams->set(
"Optimize Storage",doOptimizeStorage);
922 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(A));
923 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(B));
924 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
950 const Matrix& B,
bool transposeB,
952 Teuchos::FancyOStream& fos,
953 bool doFillComplete =
true,
954 bool doOptimizeStorage =
true,
955 const std::string & label = std::string(),
956 const RCP<ParameterList>& params = null) {
963 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) && defined(HAVE_XPETRA_ML_MMM) 969 RCP<Matrix> C = Convert_Epetra_CrsMatrix_ToXpetra_CrsMatrixWrap<SC,LO,GO,NO> (epC);
970 if (doFillComplete) {
971 RCP<Teuchos::ParameterList> fillParams = rcp(
new Teuchos::ParameterList());
972 fillParams->set(
"Optimize Storage", doOptimizeStorage);
979 C->CreateView(
"stridedMaps", rcpFromRef(A), transposeA, rcpFromRef(B), transposeB);
983 #endif // EPETRA + EPETRAEXT + ML 986 RCP<Matrix> C = C_in;
988 if (C == Teuchos::null) {
989 double nnzPerRow = Teuchos::as<double>(0);
998 nnzPerRow *= nnzPerRow;
1001 if (totalNnz < minNnz)
1005 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
1014 fos <<
"Reuse C pattern" << std::endl;
1017 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
1033 const Matrix& B,
bool transposeB,
1034 Teuchos::FancyOStream &fos,
1035 bool callFillCompleteOnResult =
true,
1036 bool doOptimizeStorage =
true,
1037 const std::string & label = std::string(),
1038 const RCP<ParameterList>& params = null) {
1039 return Multiply(A, transposeA, B, transposeB, Teuchos::null, fos, callFillCompleteOnResult, doOptimizeStorage, label, params);
1042 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1045 const Epetra_CrsMatrix& epB,
1046 Teuchos::FancyOStream& fos) {
1047 #if defined(HAVE_XPETRA_ML_MMM) // Note: this is currently not supported 1049 ML_Comm_Create(&comm);
1050 fos <<
"****** USING ML's MATRIX MATRIX MULTIPLY ******" << std::endl;
1053 const Epetra_MpiComm * Mcomm =
dynamic_cast<const Epetra_MpiComm*
>(&(epA.Comm()));
1055 ML_Comm_Set_UsrComm(comm,Mcomm->GetMpiComm());
1058 EpetraExt::CrsMatrix_SolverMap Atransform;
1059 EpetraExt::CrsMatrix_SolverMap Btransform;
1060 const Epetra_CrsMatrix& A = Atransform(const_cast<Epetra_CrsMatrix&>(epA));
1061 const Epetra_CrsMatrix& B = Btransform(const_cast<Epetra_CrsMatrix&>(epB));
1067 ML_Operator* ml_As = ML_Operator_Create(comm);
1068 ML_Operator* ml_Bs = ML_Operator_Create(comm);
1069 ML_Operator_WrapEpetraCrsMatrix(const_cast<Epetra_CrsMatrix*>(&A),ml_As);
1070 ML_Operator_WrapEpetraCrsMatrix(const_cast<Epetra_CrsMatrix*>(&B),ml_Bs);
1071 ML_Operator* ml_AtimesB = ML_Operator_Create(comm);
1073 Teuchos::TimeMonitor tm(*Teuchos::TimeMonitor::getNewTimer(
"ML_2matmult kernel"));
1074 ML_2matmult(ml_As,ml_Bs,ml_AtimesB,ML_CSR_MATRIX);
1076 ML_Operator_Destroy(&ml_As);
1077 ML_Operator_Destroy(&ml_Bs);
1082 int N_local = ml_AtimesB->invec_leng;
1083 ML_CommInfoOP* getrow_comm = ml_AtimesB->getrow->pre_comm;
1085 ML_Comm* comm_AB = ml_AtimesB->comm;
1086 if (N_local != B.DomainMap().NumMyElements())
1091 for (
int i = 0; i < getrow_comm->N_neighbors; i++) {
1092 N_rcvd += (getrow_comm->neighbors)[i].N_rcv;
1093 N_send += (getrow_comm->neighbors)[i].N_send;
1094 if ( ((getrow_comm->neighbors)[i].N_rcv != 0) &&
1095 ((getrow_comm->neighbors)[i].rcv_list != NULL) ) flag = 1;
1099 std::vector<double> dtemp(N_local + N_rcvd + 1);
1100 std::vector<int> cmap (N_local + N_rcvd + 1);
1101 for (
int i = 0; i < N_local; ++i) {
1102 cmap[i] = B.DomainMap().GID(i);
1103 dtemp[i] = (double) cmap[i];
1105 ML_cheap_exchange_bdry(&dtemp[0],getrow_comm,N_local,N_send,comm_AB);
1107 int count = N_local;
1108 const int neighbors = getrow_comm->N_neighbors;
1109 for (
int i = 0; i < neighbors; i++) {
1110 const int nrcv = getrow_comm->neighbors[i].N_rcv;
1111 for (
int j = 0; j < nrcv; j++)
1112 cmap[getrow_comm->neighbors[i].rcv_list[j]] = (
int) dtemp[count++];
1115 for (
int i = 0; i < N_local+N_rcvd; ++i)
1116 cmap[i] = (
int)dtemp[i];
1121 Epetra_Map gcmap(-1, N_local+N_rcvd, &cmap[0], B.ColMap().IndexBase(), A.Comm());
1128 const int myrowlength = A.RowMap().NumMyElements();
1129 const Epetra_Map& rowmap = A.RowMap();
1134 int educatedguess = 0;
1135 for (
int i = 0; i < myrowlength; ++i) {
1137 ML_get_matrix_row(ml_AtimesB, 1, &i, &allocated, &bindx, &val, &rowlength, 0);
1138 if (rowlength>educatedguess)
1139 educatedguess = rowlength;
1143 RCP<Epetra_CrsMatrix> result = rcp(
new Epetra_CrsMatrix(::Copy, A.RangeMap(), gcmap, educatedguess,
false));
1145 std::vector<int> gcid(educatedguess);
1146 for (
int i = 0; i < myrowlength; ++i) {
1147 const int grid = rowmap.GID(i);
1149 ML_get_matrix_row(ml_AtimesB, 1, &i, &allocated, &bindx, &val, &rowlength, 0);
1150 if (!rowlength)
continue;
1151 if ((
int)gcid.size() < rowlength) gcid.resize(rowlength);
1152 for (
int j = 0; j < rowlength; ++j) {
1153 gcid[j] = gcmap.GID(bindx[j]);
1157 int err = result->InsertGlobalValues(grid, rowlength, val, &gcid[0]);
1158 if (err != 0 && err != 1) {
1159 std::ostringstream errStr;
1160 errStr <<
"Epetra_CrsMatrix::InsertGlobalValues returned err=" << err;
1165 if (bindx) ML_free(bindx);
1166 if (val) ML_free(val);
1167 ML_Operator_Destroy(&ml_AtimesB);
1168 ML_Comm_Destroy(&comm);
1171 #else // no MUELU_ML 1176 "No ML multiplication available. This feature is currently not supported by Xpetra.");
1177 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1180 #endif //ifdef HAVE_XPETRA_EPETRAEXT 1194 Teuchos::FancyOStream& fos,
1195 bool doFillComplete =
true,
1196 bool doOptimizeStorage =
true) {
1198 "TwoMatrixMultiply for BlockedCrsMatrix not implemented for transposeA==true or transposeB==true");
1207 RCP<BlockedCrsMatrix> C = rcp(
new BlockedCrsMatrix(rgmapextractor, domapextractor, 33 ));
1209 for (
size_t i = 0; i < A.
Rows(); ++i) {
1210 for (
size_t j = 0; j < B.
Cols(); ++j) {
1213 for (
size_t l = 0; l < B.
Rows(); ++l) {
1217 if (crmat1.is_null() || crmat2.is_null())
1220 RCP<CrsMatrixWrap> crop1 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat1);
1221 RCP<CrsMatrixWrap> crop2 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat2);
1223 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
1226 if (!crop1.is_null())
1227 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
1228 if (!crop2.is_null())
1229 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
1232 "crmat1 does not have global constants");
1234 "crmat2 does not have global constants");
1236 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
1241 RCP<Matrix> temp = Teuchos::null;
1243 if(crop1 != Teuchos::null && crop2 != Teuchos::null)
1244 temp =
Multiply (*crop1,
false, *crop2,
false, fos);
1246 RCP<BlockedCrsMatrix> bop1 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat1);
1247 RCP<BlockedCrsMatrix> bop2 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat2);
1248 TEUCHOS_TEST_FOR_EXCEPTION(bop1.is_null()==
true,
Xpetra::Exceptions::BadCast,
"A is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
1249 TEUCHOS_TEST_FOR_EXCEPTION(bop2.is_null()==
true,
Xpetra::Exceptions::BadCast,
"B is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
1250 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)");
1251 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)");
1254 temp =
TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
1256 RCP<BlockedCrsMatrix> btemp = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(temp);
1257 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)");
1258 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)");
1259 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)");
1260 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)");
1261 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)");
1262 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)");
1267 RCP<Matrix> addRes = null;
1276 if (!Cij.is_null()) {
1277 if (Cij->isFillComplete())
1280 C->setMatrix(i, j, Cij);
1282 C->setMatrix(i, j, Teuchos::null);
1307 "TwoMatrixAdd: matrix row maps are not the same.");
1310 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1315 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, beta);
1319 std::ostringstream buf;
1324 #ifdef HAVE_XPETRA_TPETRA 1325 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \ 1326 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT)))) 1332 Tpetra::MatrixMatrix::Add(tpA, transposeA, alpha, tpB, beta);
1354 const Matrix& B,
bool transposeB,
const SC& beta,
1355 RCP<Matrix>& C, Teuchos::FancyOStream &fos,
bool AHasFixedNnzPerRow =
false) {
1357 RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
1358 RCP<const Matrix> rcpB = Teuchos::rcpFromRef(B);
1359 RCP<const BlockedCrsMatrix> rcpBopA = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpA);
1360 RCP<const BlockedCrsMatrix> rcpBopB = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpB);
1363 if(rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
1371 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1372 const Epetra_CrsMatrix& epA = helpers::Op2EpetraCrs(A);
1373 const Epetra_CrsMatrix& epB = helpers::Op2EpetraCrs(B);
1376 size_t maxNzInA = 0;
1377 size_t maxNzInB = 0;
1378 size_t numLocalRows = 0;
1386 if (maxNzInA == 1 || maxNzInB == 1 || AHasFixedNnzPerRow) {
1389 Teuchos::ArrayRCP<size_t> exactNnzPerRow(numLocalRows);
1391 if ((maxNzInA == 1 && maxNzInB > 1) || AHasFixedNnzPerRow) {
1392 for (
size_t i = 0; i < numLocalRows; ++i)
1396 for (
size_t i = 0; i < numLocalRows; ++i)
1400 fos <<
"MatrixMatrix::TwoMatrixAdd : special case detected (one matrix has a fixed nnz per row)" 1401 <<
", using static profiling" << std::endl;
1410 fos <<
"MatrixMatrix::TwoMatrixAdd : ** WARNING ** estimate could be badly wrong because second summand is transposed" << std::endl;
1412 RCP<Epetra_CrsMatrix> epC = helpers::Op2NonConstEpetraCrs(C);
1413 Epetra_CrsMatrix* ref2epC = &*epC;
1416 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, transposeB, beta, ref2epC);
1424 #ifdef HAVE_XPETRA_TPETRA 1425 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \ 1426 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT)))) 1429 using tcrs_matrix_type = Tpetra::CrsMatrix<SC,LO,GO,NO>;
1430 const tcrs_matrix_type& tpA = helpers::Op2TpetraCrs(A);
1431 const tcrs_matrix_type& tpB = helpers::Op2TpetraCrs(B);
1432 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
1440 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
1441 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
1445 else if(rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
1446 RCP<const MapExtractor> rgmapextractor = rcpBopB->getRangeMapExtractor();
1447 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
1453 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
1454 RCP<Matrix> Cij = Teuchos::null;
1455 if(rcpA != Teuchos::null &&
1456 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
1459 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
1460 Cij, fos, AHasFixedNnzPerRow);
1461 }
else if (rcpA == Teuchos::null &&
1462 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
1463 Cij = rcpBopB->getMatrix(i,j);
1464 }
else if (rcpA != Teuchos::null &&
1465 rcpBopB->getMatrix(i,j)==Teuchos::null) {
1466 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpA);
1468 Cij = Teuchos::null;
1471 if (!Cij.is_null()) {
1472 if (Cij->isFillComplete())
1474 Cij->fillComplete();
1475 bC->setMatrix(i, j, Cij);
1477 bC->setMatrix(i, j, Teuchos::null);
1482 else if(rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
1483 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
1484 RCP<const MapExtractor> domapextractor = rcpBopA->getDomainMapExtractor();
1490 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
1491 RCP<Matrix> Cij = Teuchos::null;
1492 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
1493 rcpB!=Teuchos::null) {
1495 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
1496 *rcpB, transposeB, beta,
1497 Cij, fos, AHasFixedNnzPerRow);
1498 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
1499 rcpB!=Teuchos::null) {
1500 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpB);
1501 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
1502 rcpB==Teuchos::null) {
1503 Cij = rcpBopA->getMatrix(i,j);
1505 Cij = Teuchos::null;
1508 if (!Cij.is_null()) {
1509 if (Cij->isFillComplete())
1511 Cij->fillComplete();
1512 bC->setMatrix(i, j, Cij);
1514 bC->setMatrix(i, j, Teuchos::null);
1524 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)");
1525 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)");
1526 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)");
1527 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)");
1528 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)");
1529 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)");
1531 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
1532 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
1537 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
1538 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
1540 RCP<Matrix> Cij = Teuchos::null;
1541 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
1542 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
1545 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
1546 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
1547 Cij, fos, AHasFixedNnzPerRow);
1548 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
1549 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
1550 Cij = rcpBopB->getMatrix(i,j);
1551 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
1552 rcpBopB->getMatrix(i,j)==Teuchos::null) {
1553 Cij = rcpBopA->getMatrix(i,j);
1555 Cij = Teuchos::null;
1558 if (!Cij.is_null()) {
1559 if (Cij->isFillComplete())
1562 Cij->fillComplete();
1563 bC->setMatrix(i, j, Cij);
1565 bC->setMatrix(i, j, Teuchos::null);
1610 const Matrix& B,
bool transposeB,
1612 bool call_FillComplete_on_result =
true,
1613 bool doOptimizeStorage =
true,
1614 const std::string & label = std::string(),
1615 const RCP<ParameterList>& params = null) {
1617 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
false && C.
getRowMap()->isSameAs(*A.
getRowMap()) ==
false,
1619 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
true && C.
getRowMap()->isSameAs(*A.
getDomainMap()) ==
false,
1625 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
1628 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1629 helpers::epetraExtMult(A, transposeA, B, transposeB, C, haveMultiplyDoFillComplete);
1634 #ifdef HAVE_XPETRA_TPETRA 1635 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \ 1636 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG)))) 1639 const Tpetra::CrsMatrix<SC,LO,GO,NO> & tpA = helpers::Op2TpetraCrs(A);
1640 const Tpetra::CrsMatrix<SC,LO,GO,NO> & tpB = helpers::Op2TpetraCrs(B);
1641 Tpetra::CrsMatrix<SC,LO,GO,NO> & tpC = helpers::Op2NonConstTpetraCrs(C);
1645 Tpetra::MatrixMatrix::Multiply(tpA, transposeA, tpB, transposeB, tpC, haveMultiplyDoFillComplete, label, params);
1652 if(call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
1653 RCP<Teuchos::ParameterList> fillParams = rcp(
new Teuchos::ParameterList());
1654 fillParams->set(
"Optimize Storage",doOptimizeStorage);
1661 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(A));
1662 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(B));
1663 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
1689 const Matrix& B,
bool transposeB,
1691 Teuchos::FancyOStream& fos,
1692 bool doFillComplete =
true,
1693 bool doOptimizeStorage =
true,
1694 const std::string & label = std::string(),
1695 const RCP<ParameterList>& params = null) {
1701 RCP<Matrix> C = C_in;
1703 if (C == Teuchos::null) {
1704 double nnzPerRow = Teuchos::as<double>(0);
1713 nnzPerRow *= nnzPerRow;
1716 if (totalNnz < minNnz)
1720 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
1728 fos <<
"Reuse C pattern" << std::endl;
1731 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
1747 const Matrix& B,
bool transposeB,
1748 Teuchos::FancyOStream &fos,
1749 bool callFillCompleteOnResult =
true,
1750 bool doOptimizeStorage =
true,
1751 const std::string & label = std::string(),
1752 const RCP<ParameterList>& params = null) {
1753 return Multiply(A, transposeA, B, transposeB, Teuchos::null, fos, callFillCompleteOnResult, doOptimizeStorage, label, params);
1756 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1759 const Epetra_CrsMatrix& ,
1760 Teuchos::FancyOStream& ) {
1762 "No ML multiplication available. This feature is currently not supported by Xpetra.");
1763 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1765 #endif //ifdef HAVE_XPETRA_EPETRAEXT 1779 Teuchos::FancyOStream& fos,
1780 bool doFillComplete =
true,
1781 bool doOptimizeStorage =
true) {
1783 "TwoMatrixMultiply for BlockedCrsMatrix not implemented for transposeA==true or transposeB==true");
1792 RCP<BlockedCrsMatrix> C = rcp(
new BlockedCrsMatrix(rgmapextractor, domapextractor, 33 ));
1794 for (
size_t i = 0; i < A.
Rows(); ++i) {
1795 for (
size_t j = 0; j < B.
Cols(); ++j) {
1798 for (
size_t l = 0; l < B.
Rows(); ++l) {
1802 if (crmat1.is_null() || crmat2.is_null())
1805 RCP<CrsMatrixWrap> crop1 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat1);
1806 RCP<CrsMatrixWrap> crop2 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat2);
1808 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
1811 if (!crop1.is_null())
1812 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
1813 if (!crop2.is_null())
1814 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
1817 "crmat1 does not have global constants");
1819 "crmat2 does not have global constants");
1821 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
1825 RCP<Matrix> temp = Teuchos::null;
1827 if(crop1 != Teuchos::null && crop2 != Teuchos::null)
1828 temp =
Multiply (*crop1,
false, *crop2,
false, fos);
1830 RCP<BlockedCrsMatrix> bop1 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat1);
1831 RCP<BlockedCrsMatrix> bop2 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat2);
1832 TEUCHOS_TEST_FOR_EXCEPTION(bop1.is_null()==
true,
Xpetra::Exceptions::BadCast,
"A is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
1833 TEUCHOS_TEST_FOR_EXCEPTION(bop2.is_null()==
true,
Xpetra::Exceptions::BadCast,
"B is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
1834 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)");
1835 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)");
1838 temp =
TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
1840 RCP<BlockedCrsMatrix> btemp = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(temp);
1841 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)");
1842 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)");
1843 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)");
1844 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)");
1845 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)");
1846 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)");
1851 RCP<Matrix> addRes = null;
1860 if (!Cij.is_null()) {
1861 if (Cij->isFillComplete())
1864 C->setMatrix(i, j, Cij);
1866 C->setMatrix(i, j, Teuchos::null);
1891 "TwoMatrixAdd: matrix row maps are not the same.");
1894 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1899 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, beta);
1903 std::ostringstream buf;
1908 #ifdef HAVE_XPETRA_TPETRA 1909 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \ 1910 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG)))) 1916 Tpetra::MatrixMatrix::Add(tpA, transposeA, alpha, tpB, beta);
1938 const Matrix& B,
bool transposeB,
const SC& beta,
1939 RCP<Matrix>& C, Teuchos::FancyOStream &fos,
bool AHasFixedNnzPerRow =
false) {
1940 RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
1941 RCP<const Matrix> rcpB = Teuchos::rcpFromRef(B);
1942 RCP<const BlockedCrsMatrix> rcpBopA = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpA);
1943 RCP<const BlockedCrsMatrix> rcpBopB = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpB);
1945 if(rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
1947 "TwoMatrixAdd: matrix row maps are not the same.");
1950 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1955 size_t maxNzInA = 0;
1956 size_t maxNzInB = 0;
1957 size_t numLocalRows = 0;
1965 if (maxNzInA == 1 || maxNzInB == 1 || AHasFixedNnzPerRow) {
1968 Teuchos::ArrayRCP<size_t> exactNnzPerRow(numLocalRows);
1970 if ((maxNzInA == 1 && maxNzInB > 1) || AHasFixedNnzPerRow) {
1971 for (
size_t i = 0; i < numLocalRows; ++i)
1975 for (
size_t i = 0; i < numLocalRows; ++i)
1979 fos <<
"MatrixMatrix::TwoMatrixAdd : special case detected (one matrix has a fixed nnz per row)" 1980 <<
", using static profiling" << std::endl;
1989 fos <<
"MatrixMatrix::TwoMatrixAdd : ** WARNING ** estimate could be badly wrong because second summand is transposed" << std::endl;
1992 Epetra_CrsMatrix* ref2epC = &*epC;
1995 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, transposeB, beta, ref2epC);
2003 #ifdef HAVE_XPETRA_TPETRA 2004 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \ 2005 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG)))) 2009 using tcrs_matrix_type = Tpetra::CrsMatrix<SC,LO,GO,NO>;
2012 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
2020 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
2021 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
2025 else if(rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
2026 RCP<const MapExtractor> rgmapextractor = rcpBopB->getRangeMapExtractor();
2027 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
2033 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
2034 RCP<Matrix> Cij = Teuchos::null;
2035 if(rcpA != Teuchos::null &&
2036 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
2039 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
2040 Cij, fos, AHasFixedNnzPerRow);
2041 }
else if (rcpA == Teuchos::null &&
2042 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
2043 Cij = rcpBopB->getMatrix(i,j);
2044 }
else if (rcpA != Teuchos::null &&
2045 rcpBopB->getMatrix(i,j)==Teuchos::null) {
2046 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpA);
2048 Cij = Teuchos::null;
2051 if (!Cij.is_null()) {
2052 if (Cij->isFillComplete())
2054 Cij->fillComplete();
2055 bC->setMatrix(i, j, Cij);
2057 bC->setMatrix(i, j, Teuchos::null);
2062 else if(rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
2063 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
2064 RCP<const MapExtractor> domapextractor = rcpBopA->getDomainMapExtractor();
2070 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
2071 RCP<Matrix> Cij = Teuchos::null;
2072 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
2073 rcpB!=Teuchos::null) {
2075 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
2076 *rcpB, transposeB, beta,
2077 Cij, fos, AHasFixedNnzPerRow);
2078 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
2079 rcpB!=Teuchos::null) {
2080 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpB);
2081 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
2082 rcpB==Teuchos::null) {
2083 Cij = rcpBopA->getMatrix(i,j);
2085 Cij = Teuchos::null;
2088 if (!Cij.is_null()) {
2089 if (Cij->isFillComplete())
2091 Cij->fillComplete();
2092 bC->setMatrix(i, j, Cij);
2094 bC->setMatrix(i, j, Teuchos::null);
2104 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)");
2105 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)");
2106 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)");
2107 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)");
2108 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)");
2109 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)");
2111 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
2112 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
2117 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
2118 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
2120 RCP<Matrix> Cij = Teuchos::null;
2121 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
2122 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
2125 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
2126 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
2127 Cij, fos, AHasFixedNnzPerRow);
2128 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
2129 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
2130 Cij = rcpBopB->getMatrix(i,j);
2131 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
2132 rcpBopB->getMatrix(i,j)==Teuchos::null) {
2133 Cij = rcpBopA->getMatrix(i,j);
2135 Cij = Teuchos::null;
2138 if (!Cij.is_null()) {
2139 if (Cij->isFillComplete())
2142 Cij->fillComplete();
2143 bC->setMatrix(i, j, Cij);
2145 bC->setMatrix(i, j, Teuchos::null);
2154 #endif // HAVE_XPETRA_EPETRA 2158 #define XPETRA_MATRIXMATRIX_SHORT Tpetra::CrsMatrix< SC, LO, GO, NO > tcrs_matrix_type
virtual size_t getNodeMaxNumRowEntries() const =0
Returns the maximum number of entries across all rows/columns on this node.
virtual size_t getNodeNumRows() const =0
Returns the number of matrix rows owned on the calling node.
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 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.
virtual global_size_t getGlobalNumRows() const =0
Returns the number of global rows in this matrix.
static Teuchos::RCP< Matrix > tpetraAdd(const tcrs_matrix_type &A, bool transposeA, const typename tcrs_matrix_type::scalar_type alpha, const tcrs_matrix_type &B, bool transposeB, const typename tcrs_matrix_type::scalar_type beta)
virtual const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
bool isFillComplete() const
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
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.
static Epetra_CrsMatrix & Op2NonConstEpetraCrs(const Matrix &Op)
Xpetra utility class containing transformation routines between Xpetra::Matrix and Epetra/Tpetra obje...
static RCP< Matrix > Build(const RCP< const Map > &rowMap)
virtual void resumeFill(const RCP< ParameterList > ¶ms=null)=0
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".
static const Epetra_CrsMatrix & Op2EpetraCrs(const Matrix &Op)
RCP< const MapExtractor > getRangeMapExtractor() const
Returns map extractor class for range map.
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 &)
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.
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< 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.
static Tpetra::CrsMatrix< SC, LO, GO, NO > & Op2NonConstTpetraCrs(const Matrix &Op)
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 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)
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 void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
static void epetraExtMult(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Matrix &C, bool fillCompleteResult)
static RCP< const Epetra_CrsMatrix > Op2EpetraCrs(RCP< Matrix > Op)
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 > Op2NonConstEpetraCrs(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.
RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
virtual global_size_t getGlobalNumEntries() const =0
Returns the global number of entries in this matrix.
Concrete implementation of Xpetra::Matrix.
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
virtual Teuchos::RCP< const Map > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y...
bool IsView(const viewLabel_t viewLabel) const
static RCP< Epetra_CrsMatrix > MLTwoMatrixMultiply(const Epetra_CrsMatrix &epA, const Epetra_CrsMatrix &epB, Teuchos::FancyOStream &fos)
RCP< const MapExtractor > getDomainMapExtractor() const
Returns map extractor for domain map.
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 Rows() const
number of row blocks
static RCP< Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2NonConstTpetraCrs(RCP< Matrix > Op)
virtual size_t Cols() const
number of column blocks
RCP< CrsMatrix > getCrsMatrix() const
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.
RCP< const Map > getDomainMap() const
Returns the Map associated with the domain of this operator.
static RCP< Epetra_CrsMatrix > MLTwoMatrixMultiply(const Epetra_CrsMatrix &epA, const Epetra_CrsMatrix &epB, Teuchos::FancyOStream &fos)
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
static const Tpetra::CrsMatrix< SC, LO, GO, NO > & Op2TpetraCrs(const Matrix &Op)
virtual Teuchos::RCP< const Map > getDomainMap() const =0
The Map associated with the domain of this operator, which must be compatible with X...
Xpetra-specific matrix class.
static RCP< const Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2TpetraCrs(RCP< Matrix > Op)
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.