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
RCP< CrsMatrix > getCrsMatrix() const
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)
static RCP< Matrix > Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, RCP< Matrix > C_in, Teuchos::FancyOStream &fos, bool doFillComplete=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
Helper function to do matrix-matrix multiply.
bool isFillComplete() const
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
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)
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.
bool IsView(const viewLabel_t viewLabel) const
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
virtual bool isFillComplete() const =0
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
virtual size_t Cols() const
number of column blocks
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)
RCP< const MapExtractor > getDomainMapExtractor() const
Returns map extractor for domain map.
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).
RCP< const Map > getDomainMap() const
Returns the Map associated with the domain of this operator.
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
virtual global_size_t getGlobalNumEntries() const =0
Returns the global number of entries in this matrix.
Concrete implementation of Xpetra::Matrix.
virtual Teuchos::RCP< const Map > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y...
virtual size_t Rows() const
number of row blocks
static RCP< Epetra_CrsMatrix > MLTwoMatrixMultiply(const Epetra_CrsMatrix &epA, const Epetra_CrsMatrix &epB, Teuchos::FancyOStream &fos)
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 const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
static RCP< Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2NonConstTpetraCrs(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.
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.
RCP< const MapExtractor > getRangeMapExtractor() const
Returns map extractor class for range map.