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" 62 #ifdef HAVE_XPETRA_EPETRA 66 #ifdef HAVE_XPETRA_EPETRAEXT 67 #include <EpetraExt_MatrixMatrix.h> 68 #include <EpetraExt_RowMatrixOut.h> 69 #include <Epetra_RowMatrixTransposer.h> 70 #endif // HAVE_XPETRA_EPETRAEXT 72 #ifdef HAVE_XPETRA_TPETRA 73 #include <TpetraExt_MatrixMatrix.hpp> 74 #include <Tpetra_RowMatrixTransposer.hpp> 75 #include <MatrixMarket_Tpetra.hpp> 76 #include <Xpetra_TpetraCrsMatrix.hpp> 77 #include <Xpetra_TpetraMultiVector.hpp> 78 #include <Xpetra_TpetraVector.hpp> 79 #endif // HAVE_XPETRA_TPETRA 89 template <
class Scalar,
90 class LocalOrdinal = int,
91 class GlobalOrdinal = LocalOrdinal,
98 #ifdef HAVE_XPETRA_EPETRA 101 RCP<const CrsMatrixWrap> crsOp = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(Op);
103 "Cast from Xpetra::Matrix to Xpetra::CrsMatrixWrap failed");
105 RCP<const CrsMatrix> tmp_CrsMtx = crsOp->getCrsMatrix();
106 const RCP<const EpetraCrsMatrixT<GO,NO> > &tmp_ECrsMtx = Teuchos::rcp_dynamic_cast<
const EpetraCrsMatrixT<GO,NO> >(tmp_CrsMtx);
108 "Cast from Xpetra::CrsMatrix to Xpetra::EpetraCrsMatrix failed");
110 return tmp_ECrsMtx->getEpetra_CrsMatrix();
114 RCP<Epetra_CrsMatrix> A;
116 RCP<const CrsMatrixWrap> crsOp = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(Op);
118 "Cast from Xpetra::Matrix to Xpetra::CrsMatrixWrap failed");
120 RCP<const CrsMatrix> tmp_CrsMtx = crsOp->getCrsMatrix();
121 const RCP<const EpetraCrsMatrixT<GO,NO> > &tmp_ECrsMtx = Teuchos::rcp_dynamic_cast<
const EpetraCrsMatrixT<GO,NO> >(tmp_CrsMtx);
122 TEUCHOS_TEST_FOR_EXCEPTION(tmp_ECrsMtx == Teuchos::null,
Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::EpetraCrsMatrix failed");
124 return tmp_ECrsMtx->getEpetra_CrsMatrixNonConst();
132 const RCP<const EpetraCrsMatrixT<GO,NO> > &tmp_ECrsMtx = Teuchos::rcp_dynamic_cast<
const EpetraCrsMatrixT<GO,NO> >(tmp_CrsMtx);
134 "Cast from Xpetra::CrsMatrix to Xpetra::EpetraCrsMatrix failed");
136 return *tmp_ECrsMtx->getEpetra_CrsMatrix();
144 RCP<Epetra_CrsMatrix> A;
149 const RCP<const EpetraCrsMatrixT<GO,NO> > &tmp_ECrsMtx = Teuchos::rcp_dynamic_cast<
const EpetraCrsMatrixT<GO,NO> >(tmp_CrsMtx);
150 TEUCHOS_TEST_FOR_EXCEPTION(tmp_ECrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::EpetraCrsMatrix failed");
152 return *Teuchos::rcp_const_cast<Epetra_CrsMatrix>(tmp_ECrsMtx->getEpetra_CrsMatrix());
158 #endif // HAVE_XPETRA_EPETRA 160 #ifdef HAVE_XPETRA_TPETRA 161 static RCP<const Tpetra::CrsMatrix<SC,LO,GO,NO> >
Op2TpetraCrs(RCP<Matrix> Op) {
163 RCP<const CrsMatrixWrap> crsOp = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(Op);
164 TEUCHOS_TEST_FOR_EXCEPTION(crsOp == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::Matrix to Xpetra::CrsMatrixWrap failed");
166 RCP<const CrsMatrix> tmp_CrsMtx = crsOp->getCrsMatrix();
168 TEUCHOS_TEST_FOR_EXCEPTION(tmp_ECrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::TpetraCrsMatrix failed");
170 return tmp_ECrsMtx->getTpetra_CrsMatrix();
175 RCP<const CrsMatrixWrap> crsOp = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(Op);
176 TEUCHOS_TEST_FOR_EXCEPTION(crsOp == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::Matrix to Xpetra::CrsMatrixWrap failed");
177 RCP<const CrsMatrix> tmp_CrsMtx = crsOp->getCrsMatrix();
179 TEUCHOS_TEST_FOR_EXCEPTION(tmp_ECrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::TpetraCrsMatrix failed");
181 return tmp_ECrsMtx->getTpetra_CrsMatrixNonConst();
190 TEUCHOS_TEST_FOR_EXCEPTION(tmp_TCrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::TpetraCrsMatrix failed");
192 return *tmp_TCrsMtx->getTpetra_CrsMatrix();
205 TEUCHOS_TEST_FOR_EXCEPTION(tmp_TCrsMtx == Teuchos::null,
Xpetra::Exceptions::BadCast,
"Cast from Xpetra::CrsMatrix to Xpetra::TpetraCrsMatrix failed");
207 return *Teuchos::rcp_const_cast<Tpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(tmp_TCrsMtx->getTpetra_CrsMatrix());
213 #endif // HAVE_XPETRA_TPETRA 215 #ifdef HAVE_XPETRA_TPETRA 218 const tcrs_matrix_type& A,
bool transposeA,
const typename tcrs_matrix_type::scalar_type alpha,
219 const tcrs_matrix_type& B,
bool transposeB,
const typename tcrs_matrix_type::scalar_type beta)
221 using Teuchos::Array;
224 using Teuchos::rcp_implicit_cast;
225 using Teuchos::rcpFromRef;
226 using Teuchos::ParameterList;
230 using transposer_type = Tpetra::RowMatrixTransposer<SC,LO,GO,NO>;
231 using import_type = Tpetra::Import<LO,GO,NO>;
232 RCP<const tcrs_matrix_type> Aprime = rcpFromRef(A);
234 Aprime = transposer_type(Aprime).createTranspose();
236 if(A.isFillComplete() && B.isFillComplete())
238 RCP<tcrs_matrix_type> C = rcp(
new tcrs_matrix_type(Aprime->getRowMap(), 0));
239 RCP<ParameterList> addParams = rcp(
new ParameterList);
240 addParams->set(
"Call fillComplete",
false);
242 Tpetra::MatrixMatrix::add<SC,LO,GO,NO>(beta, transposeB, B, alpha,
false, *Aprime, *C, Teuchos::null, Teuchos::null, addParams);
243 return rcp_implicit_cast<
Matrix>(rcp(
new CrsWrap(rcp_implicit_cast<CrsType>(rcp(
new XTCrsType(C))))));
251 RCP<const tcrs_matrix_type> Bprime = rcpFromRef(B);
253 Bprime = transposer_type(Bprime).createTranspose();
255 if(!(Aprime->getRowMap()->isSameAs(*(Bprime->getRowMap()))))
257 auto import = rcp(
new import_type(Bprime->getRowMap(), Aprime->getRowMap()));
258 Bprime = Tpetra::importAndFillCompleteCrsMatrix<tcrs_matrix_type>(Bprime, *
import, Aprime->getDomainMap(), Aprime->getRangeMap());
261 LO numLocalRows = Aprime->getNodeNumRows();
262 Array<size_t> allocPerRow(numLocalRows);
264 for(
LO i = 0; i < numLocalRows; i++)
266 allocPerRow[i] = Aprime->getNumEntriesInLocalRow(i) + Bprime->getNumEntriesInLocalRow(i);
269 RCP<tcrs_matrix_type> C = rcp(
new tcrs_matrix_type(Aprime->getRowMap(), allocPerRow(), Tpetra::StaticProfile));
271 Tpetra::MatrixMatrix::Add<SC,LO,GO,NO>(
272 *Aprime,
false, alpha,
273 *Bprime,
false, beta,
275 return rcp(
new CrsWrap(rcp_implicit_cast<CrsType>(rcp(
new XTCrsType(C)))));
280 #ifdef HAVE_XPETRA_EPETRAEXT 288 const Epetra_Map& Crowmap = epC.RowMap();
290 Epetra_CrsMatrix Ctemp(::Copy, Crowmap, 0,
false);
291 if(fillCompleteResult) {
292 errCode = EpetraExt::MatrixMatrix::Multiply(epA, transposeA, epB, transposeB, Ctemp,
true);
299 errCode = EpetraExt::MatrixMatrix::Multiply(epA, transposeA, epB, transposeB, Ctemp,
false);
301 int numLocalRows = Crowmap.NumMyElements();
302 long long* globalElementList =
nullptr;
303 Crowmap.MyGlobalElementsPtr(globalElementList);
304 Teuchos::Array<int> entriesPerRow(numLocalRows, 0);
305 for(
int i = 0; i < numLocalRows; i++)
307 entriesPerRow[i] = Ctemp.NumGlobalEntries(globalElementList[i]);
310 epC = Epetra_CrsMatrix(::Copy, Crowmap, entriesPerRow.data(),
true);
311 for(
int i = 0; i < numLocalRows; i++)
313 int gid = globalElementList[i];
317 Ctemp.ExtractGlobalRowView(gid, numEntries, values, inds);
318 epC.InsertGlobalValues(gid, numEntries, values, inds);
323 std::ostringstream buf;
325 std::string msg =
"EpetraExt::MatrixMatrix::Multiply returned nonzero error code " + buf.str();
332 template <
class Scalar,
334 class GlobalOrdinal ,
337 #undef XPETRA_MATRIXMATRIX_SHORT 367 const Matrix& B,
bool transposeB,
369 bool call_FillComplete_on_result =
true,
370 bool doOptimizeStorage =
true,
371 const std::string & label = std::string(),
372 const RCP<ParameterList>& params = null) {
374 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
false && C.
getRowMap()->isSameAs(*A.
getRowMap()) ==
false,
376 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
true && C.
getRowMap()->isSameAs(*A.
getDomainMap()) ==
false,
382 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
385 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 386 throw(
Xpetra::Exceptions::RuntimeError(
"Xpetra::MatrixMatrix::Multiply only available for GO=int or GO=long long with EpetraNode (Serial or OpenMP depending on configuration)"));
392 #ifdef HAVE_XPETRA_TPETRA 399 Tpetra::MatrixMatrix::Multiply(tpA, transposeA, tpB, transposeB, tpC, haveMultiplyDoFillComplete, label, params);
405 if (call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
406 RCP<Teuchos::ParameterList> fillParams = rcp(
new Teuchos::ParameterList());
407 fillParams->set(
"Optimize Storage", doOptimizeStorage);
414 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(A));
415 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(B));
416 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
441 static RCP<Matrix>
Multiply(
const Matrix& A,
bool transposeA,
const Matrix& B,
bool transposeB, RCP<Matrix> C_in,
442 Teuchos::FancyOStream& fos,
443 bool doFillComplete =
true,
444 bool doOptimizeStorage =
true,
445 const std::string & label = std::string(),
446 const RCP<ParameterList>& params = null) {
452 RCP<Matrix> C = C_in;
454 if (C == Teuchos::null) {
455 double nnzPerRow = Teuchos::as<double>(0);
464 nnzPerRow *= nnzPerRow;
467 if (totalNnz < minNnz)
471 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
479 fos <<
"Reuse C pattern" << std::endl;
482 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
497 static RCP<Matrix>
Multiply(
const Matrix& A,
bool transposeA,
const Matrix& B,
bool transposeB, Teuchos::FancyOStream &fos,
498 bool callFillCompleteOnResult =
true,
bool doOptimizeStorage =
true,
const std::string& label = std::string(),
499 const RCP<ParameterList>& params = null) {
500 return Multiply(A, transposeA, B, transposeB, Teuchos::null, fos, callFillCompleteOnResult, doOptimizeStorage, label, params);
503 #ifdef HAVE_XPETRA_EPETRAEXT 506 const Epetra_CrsMatrix& epB,
507 Teuchos::FancyOStream& fos) {
508 throw(
Xpetra::Exceptions::RuntimeError(
"MLTwoMatrixMultiply only available for GO=int or GO=long long with EpetraNode (Serial or OpenMP depending on configuration)"));
509 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
511 #endif //ifdef HAVE_XPETRA_EPETRAEXT 525 Teuchos::FancyOStream& fos,
526 bool doFillComplete =
true,
527 bool doOptimizeStorage =
true) {
529 "TwoMatrixMultiply for BlockedCrsMatrix not implemented for transposeA==true or transposeB==true");
538 RCP<BlockedCrsMatrix> C = rcp(
new BlockedCrsMatrix(rgmapextractor, domapextractor, 33 ));
540 for (
size_t i = 0; i < A.
Rows(); ++i) {
541 for (
size_t j = 0; j < B.
Cols(); ++j) {
544 for (
size_t l = 0; l < B.
Rows(); ++l) {
548 if (crmat1.is_null() || crmat2.is_null())
551 RCP<CrsMatrixWrap> crop1 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat1);
552 RCP<CrsMatrixWrap> crop2 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat2);
554 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
557 if (!crop1.is_null())
558 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
559 if (!crop2.is_null())
560 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
563 "crmat1 does not have global constants");
565 "crmat2 does not have global constants");
567 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
571 RCP<Matrix> temp = Teuchos::null;
573 if(crop1 != Teuchos::null && crop2 != Teuchos::null)
574 temp =
Multiply (*crop1,
false, *crop2,
false, fos);
576 RCP<BlockedCrsMatrix> bop1 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat1);
577 RCP<BlockedCrsMatrix> bop2 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat2);
578 TEUCHOS_TEST_FOR_EXCEPTION(bop1.is_null()==
true,
Xpetra::Exceptions::BadCast,
"A is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
579 TEUCHOS_TEST_FOR_EXCEPTION(bop2.is_null()==
true,
Xpetra::Exceptions::BadCast,
"B is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
580 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)");
581 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)");
584 temp =
TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
586 RCP<BlockedCrsMatrix> btemp = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(temp);
587 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)");
588 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)");
589 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)");
590 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)");
591 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)");
592 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)");
597 RCP<Matrix> addRes = null;
606 if (!Cij.is_null()) {
607 if (Cij->isFillComplete())
610 C->setMatrix(i, j, Cij);
612 C->setMatrix(i, j, Teuchos::null);
640 throw Exceptions::RuntimeError(
"TwoMatrixAdd for Epetra matrices needs <double,int,int> for Scalar, LocalOrdinal and GlobalOrdinal.");
642 #ifdef HAVE_XPETRA_TPETRA 646 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);
1356 const Matrix& B,
bool transposeB,
const SC& beta,
1357 RCP<Matrix>& C, Teuchos::FancyOStream &fos,
bool AHasFixedNnzPerRow =
false) {
1359 RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
1360 RCP<const Matrix> rcpB = Teuchos::rcpFromRef(B);
1361 RCP<const BlockedCrsMatrix> rcpBopA = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpA);
1362 RCP<const BlockedCrsMatrix> rcpBopB = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpB);
1365 if(rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
1373 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1374 const Epetra_CrsMatrix& epA = helpers::Op2EpetraCrs(A);
1375 const Epetra_CrsMatrix& epB = helpers::Op2EpetraCrs(B);
1378 size_t maxNzInA = 0;
1379 size_t maxNzInB = 0;
1380 size_t numLocalRows = 0;
1388 if (maxNzInA == 1 || maxNzInB == 1 || AHasFixedNnzPerRow) {
1391 Teuchos::ArrayRCP<size_t> exactNnzPerRow(numLocalRows);
1393 if ((maxNzInA == 1 && maxNzInB > 1) || AHasFixedNnzPerRow) {
1394 for (
size_t i = 0; i < numLocalRows; ++i)
1398 for (
size_t i = 0; i < numLocalRows; ++i)
1402 fos <<
"MatrixMatrix::TwoMatrixAdd : special case detected (one matrix has a fixed nnz per row)" 1403 <<
", using static profiling" << std::endl;
1412 fos <<
"MatrixMatrix::TwoMatrixAdd : ** WARNING ** estimate could be badly wrong because second summand is transposed" << std::endl;
1414 RCP<Epetra_CrsMatrix> epC = helpers::Op2NonConstEpetraCrs(C);
1415 Epetra_CrsMatrix* ref2epC = &*epC;
1418 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, transposeB, beta, ref2epC);
1426 #ifdef HAVE_XPETRA_TPETRA 1427 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \ 1428 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT)))) 1431 using tcrs_matrix_type = Tpetra::CrsMatrix<SC,LO,GO,NO>;
1432 const tcrs_matrix_type& tpA = helpers::Op2TpetraCrs(A);
1433 const tcrs_matrix_type& tpB = helpers::Op2TpetraCrs(B);
1434 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
1442 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
1443 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
1447 else if(rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
1448 RCP<const MapExtractor> rgmapextractor = rcpBopB->getRangeMapExtractor();
1449 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
1455 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
1456 RCP<Matrix> Cij = Teuchos::null;
1457 if(rcpA != Teuchos::null &&
1458 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
1461 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
1462 Cij, fos, AHasFixedNnzPerRow);
1463 }
else if (rcpA == Teuchos::null &&
1464 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
1465 Cij = rcpBopB->getMatrix(i,j);
1466 }
else if (rcpA != Teuchos::null &&
1467 rcpBopB->getMatrix(i,j)==Teuchos::null) {
1468 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpA);
1470 Cij = Teuchos::null;
1473 if (!Cij.is_null()) {
1474 if (Cij->isFillComplete())
1476 Cij->fillComplete();
1477 bC->setMatrix(i, j, Cij);
1479 bC->setMatrix(i, j, Teuchos::null);
1484 else if(rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
1485 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
1486 RCP<const MapExtractor> domapextractor = rcpBopA->getDomainMapExtractor();
1492 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
1493 RCP<Matrix> Cij = Teuchos::null;
1494 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
1495 rcpB!=Teuchos::null) {
1497 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
1498 *rcpB, transposeB, beta,
1499 Cij, fos, AHasFixedNnzPerRow);
1500 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
1501 rcpB!=Teuchos::null) {
1502 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpB);
1503 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
1504 rcpB==Teuchos::null) {
1505 Cij = rcpBopA->getMatrix(i,j);
1507 Cij = Teuchos::null;
1510 if (!Cij.is_null()) {
1511 if (Cij->isFillComplete())
1513 Cij->fillComplete();
1514 bC->setMatrix(i, j, Cij);
1516 bC->setMatrix(i, j, Teuchos::null);
1526 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)");
1527 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)");
1528 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)");
1529 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)");
1530 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)");
1531 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)");
1533 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
1534 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
1539 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
1540 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
1542 RCP<Matrix> Cij = Teuchos::null;
1543 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
1544 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
1547 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
1548 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
1549 Cij, fos, AHasFixedNnzPerRow);
1550 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
1551 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
1552 Cij = rcpBopB->getMatrix(i,j);
1553 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
1554 rcpBopB->getMatrix(i,j)==Teuchos::null) {
1555 Cij = rcpBopA->getMatrix(i,j);
1557 Cij = Teuchos::null;
1560 if (!Cij.is_null()) {
1561 if (Cij->isFillComplete())
1564 Cij->fillComplete();
1565 bC->setMatrix(i, j, Cij);
1567 bC->setMatrix(i, j, Teuchos::null);
1612 const Matrix& B,
bool transposeB,
1614 bool call_FillComplete_on_result =
true,
1615 bool doOptimizeStorage =
true,
1616 const std::string & label = std::string(),
1617 const RCP<ParameterList>& params = null) {
1619 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
false && C.
getRowMap()->isSameAs(*A.
getRowMap()) ==
false,
1621 TEUCHOS_TEST_FOR_EXCEPTION(transposeA ==
true && C.
getRowMap()->isSameAs(*A.
getDomainMap()) ==
false,
1627 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
1630 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1631 helpers::epetraExtMult(A, transposeA, B, transposeB, C, haveMultiplyDoFillComplete);
1636 #ifdef HAVE_XPETRA_TPETRA 1637 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \ 1638 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG)))) 1641 const Tpetra::CrsMatrix<SC,LO,GO,NO> & tpA = helpers::Op2TpetraCrs(A);
1642 const Tpetra::CrsMatrix<SC,LO,GO,NO> & tpB = helpers::Op2TpetraCrs(B);
1643 Tpetra::CrsMatrix<SC,LO,GO,NO> & tpC = helpers::Op2NonConstTpetraCrs(C);
1647 Tpetra::MatrixMatrix::Multiply(tpA, transposeA, tpB, transposeB, tpC, haveMultiplyDoFillComplete, label, params);
1654 if(call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
1655 RCP<Teuchos::ParameterList> fillParams = rcp(
new Teuchos::ParameterList());
1656 fillParams->set(
"Optimize Storage",doOptimizeStorage);
1663 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(A));
1664 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<
Matrix>(Teuchos::rcpFromRef(B));
1665 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
1691 const Matrix& B,
bool transposeB,
1693 Teuchos::FancyOStream& fos,
1694 bool doFillComplete =
true,
1695 bool doOptimizeStorage =
true,
1696 const std::string & label = std::string(),
1697 const RCP<ParameterList>& params = null) {
1703 RCP<Matrix> C = C_in;
1705 if (C == Teuchos::null) {
1706 double nnzPerRow = Teuchos::as<double>(0);
1715 nnzPerRow *= nnzPerRow;
1718 if (totalNnz < minNnz)
1722 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
1730 fos <<
"Reuse C pattern" << std::endl;
1733 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
1749 const Matrix& B,
bool transposeB,
1750 Teuchos::FancyOStream &fos,
1751 bool callFillCompleteOnResult =
true,
1752 bool doOptimizeStorage =
true,
1753 const std::string & label = std::string(),
1754 const RCP<ParameterList>& params = null) {
1755 return Multiply(A, transposeA, B, transposeB, Teuchos::null, fos, callFillCompleteOnResult, doOptimizeStorage, label, params);
1758 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1761 const Epetra_CrsMatrix& ,
1762 Teuchos::FancyOStream& ) {
1764 "No ML multiplication available. This feature is currently not supported by Xpetra.");
1765 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1767 #endif //ifdef HAVE_XPETRA_EPETRAEXT 1781 Teuchos::FancyOStream& fos,
1782 bool doFillComplete =
true,
1783 bool doOptimizeStorage =
true) {
1785 "TwoMatrixMultiply for BlockedCrsMatrix not implemented for transposeA==true or transposeB==true");
1794 RCP<BlockedCrsMatrix> C = rcp(
new BlockedCrsMatrix(rgmapextractor, domapextractor, 33 ));
1796 for (
size_t i = 0; i < A.
Rows(); ++i) {
1797 for (
size_t j = 0; j < B.
Cols(); ++j) {
1800 for (
size_t l = 0; l < B.
Rows(); ++l) {
1804 if (crmat1.is_null() || crmat2.is_null())
1807 RCP<CrsMatrixWrap> crop1 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat1);
1808 RCP<CrsMatrixWrap> crop2 = Teuchos::rcp_dynamic_cast<
CrsMatrixWrap>(crmat2);
1810 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
1813 if (!crop1.is_null())
1814 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
1815 if (!crop2.is_null())
1816 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
1819 "crmat1 does not have global constants");
1821 "crmat2 does not have global constants");
1823 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
1827 RCP<Matrix> temp = Teuchos::null;
1829 if(crop1 != Teuchos::null && crop2 != Teuchos::null)
1830 temp =
Multiply (*crop1,
false, *crop2,
false, fos);
1832 RCP<BlockedCrsMatrix> bop1 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat1);
1833 RCP<BlockedCrsMatrix> bop2 = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(crmat2);
1834 TEUCHOS_TEST_FOR_EXCEPTION(bop1.is_null()==
true,
Xpetra::Exceptions::BadCast,
"A is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
1835 TEUCHOS_TEST_FOR_EXCEPTION(bop2.is_null()==
true,
Xpetra::Exceptions::BadCast,
"B is not a BlockedCrsMatrix. (TwoMatrixMultiplyBlock)");
1836 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)");
1837 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)");
1840 temp =
TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
1842 RCP<BlockedCrsMatrix> btemp = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(temp);
1843 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)");
1844 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)");
1845 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)");
1846 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)");
1847 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)");
1848 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)");
1853 RCP<Matrix> addRes = null;
1862 if (!Cij.is_null()) {
1863 if (Cij->isFillComplete())
1866 C->setMatrix(i, j, Cij);
1868 C->setMatrix(i, j, Teuchos::null);
1893 "TwoMatrixAdd: matrix row maps are not the same.");
1896 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1901 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, beta);
1905 std::ostringstream buf;
1910 #ifdef HAVE_XPETRA_TPETRA 1911 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \ 1912 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG)))) 1918 Tpetra::MatrixMatrix::Add(tpA, transposeA, alpha, tpB, beta);
1942 const Matrix& B,
bool transposeB,
const SC& beta,
1943 RCP<Matrix>& C, Teuchos::FancyOStream &fos,
bool AHasFixedNnzPerRow =
false) {
1944 RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
1945 RCP<const Matrix> rcpB = Teuchos::rcpFromRef(B);
1946 RCP<const BlockedCrsMatrix> rcpBopA = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpA);
1947 RCP<const BlockedCrsMatrix> rcpBopB = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(rcpB);
1949 if(rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
1951 "TwoMatrixAdd: matrix row maps are not the same.");
1954 #if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) 1959 size_t maxNzInA = 0;
1960 size_t maxNzInB = 0;
1961 size_t numLocalRows = 0;
1969 if (maxNzInA == 1 || maxNzInB == 1 || AHasFixedNnzPerRow) {
1972 Teuchos::ArrayRCP<size_t> exactNnzPerRow(numLocalRows);
1974 if ((maxNzInA == 1 && maxNzInB > 1) || AHasFixedNnzPerRow) {
1975 for (
size_t i = 0; i < numLocalRows; ++i)
1979 for (
size_t i = 0; i < numLocalRows; ++i)
1983 fos <<
"MatrixMatrix::TwoMatrixAdd : special case detected (one matrix has a fixed nnz per row)" 1984 <<
", using static profiling" << std::endl;
1993 fos <<
"MatrixMatrix::TwoMatrixAdd : ** WARNING ** estimate could be badly wrong because second summand is transposed" << std::endl;
1996 Epetra_CrsMatrix* ref2epC = &*epC;
1999 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, transposeB, beta, ref2epC);
2007 #ifdef HAVE_XPETRA_TPETRA 2008 # if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \ 2009 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG)))) 2013 using tcrs_matrix_type = Tpetra::CrsMatrix<SC,LO,GO,NO>;
2016 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
2024 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
2025 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
2029 else if(rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
2030 RCP<const MapExtractor> rgmapextractor = rcpBopB->getRangeMapExtractor();
2031 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
2037 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
2038 RCP<Matrix> Cij = Teuchos::null;
2039 if(rcpA != Teuchos::null &&
2040 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
2043 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
2044 Cij, fos, AHasFixedNnzPerRow);
2045 }
else if (rcpA == Teuchos::null &&
2046 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
2047 Cij = rcpBopB->getMatrix(i,j);
2048 }
else if (rcpA != Teuchos::null &&
2049 rcpBopB->getMatrix(i,j)==Teuchos::null) {
2050 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpA);
2052 Cij = Teuchos::null;
2055 if (!Cij.is_null()) {
2056 if (Cij->isFillComplete())
2058 Cij->fillComplete();
2059 bC->setMatrix(i, j, Cij);
2061 bC->setMatrix(i, j, Teuchos::null);
2066 else if(rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
2067 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
2068 RCP<const MapExtractor> domapextractor = rcpBopA->getDomainMapExtractor();
2074 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
2075 RCP<Matrix> Cij = Teuchos::null;
2076 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
2077 rcpB!=Teuchos::null) {
2079 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
2080 *rcpB, transposeB, beta,
2081 Cij, fos, AHasFixedNnzPerRow);
2082 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
2083 rcpB!=Teuchos::null) {
2084 Cij = Teuchos::rcp_const_cast<
Matrix>(rcpB);
2085 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
2086 rcpB==Teuchos::null) {
2087 Cij = rcpBopA->getMatrix(i,j);
2089 Cij = Teuchos::null;
2092 if (!Cij.is_null()) {
2093 if (Cij->isFillComplete())
2095 Cij->fillComplete();
2096 bC->setMatrix(i, j, Cij);
2098 bC->setMatrix(i, j, Teuchos::null);
2108 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)");
2109 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)");
2110 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)");
2111 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)");
2112 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)");
2113 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)");
2115 RCP<const MapExtractor> rgmapextractor = rcpBopA->getRangeMapExtractor();
2116 RCP<const MapExtractor> domapextractor = rcpBopB->getDomainMapExtractor();
2121 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
2122 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
2124 RCP<Matrix> Cij = Teuchos::null;
2125 if(rcpBopA->getMatrix(i,j)!=Teuchos::null &&
2126 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
2129 TwoMatrixAdd(*(rcpBopA->getMatrix(i,j)), transposeA, alpha,
2130 *(rcpBopB->getMatrix(i,j)), transposeB, beta,
2131 Cij, fos, AHasFixedNnzPerRow);
2132 }
else if (rcpBopA->getMatrix(i,j) == Teuchos::null &&
2133 rcpBopB->getMatrix(i,j)!=Teuchos::null) {
2134 Cij = rcpBopB->getMatrix(i,j);
2135 }
else if (rcpBopA->getMatrix(i,j) != Teuchos::null &&
2136 rcpBopB->getMatrix(i,j)==Teuchos::null) {
2137 Cij = rcpBopA->getMatrix(i,j);
2139 Cij = Teuchos::null;
2142 if (!Cij.is_null()) {
2143 if (Cij->isFillComplete())
2146 Cij->fillComplete();
2147 bC->setMatrix(i, j, Cij);
2149 bC->setMatrix(i, j, Teuchos::null);
2158 #endif // HAVE_XPETRA_EPETRA 2162 #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.