39 const Matrix& B,
bool transposeB,
41 bool call_FillComplete_on_result,
42 bool doOptimizeStorage,
43 const std::string& label,
53 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
57 if (helpers::isTpetraCrs(A) && helpers::isTpetraCrs(B) && helpers::isTpetraCrs(C)) {
66 }
else if (helpers::isTpetraBlockCrs(A) && helpers::isTpetraBlockCrs(B)) {
71 std::cout <<
"WARNING: Using inefficient BlockCrs Multiply Placeholder" << std::endl;
83 new_params->set(
"compute global constants",
true);
97 Ac_w->replaceCrsMatrix(Ac_p);
104 if (call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
106 fillParams->set(
"Optimize Storage", doOptimizeStorage);
113 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<Matrix>(Teuchos::rcpFromRef(A));
114 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<Matrix>(Teuchos::rcpFromRef(B));
116 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
120RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(
const Matrix& A,
bool transposeA,
const Matrix& B,
bool transposeB,
RCP<Matrix> C_in,
123 bool doOptimizeStorage,
124 const std::string& label,
126 auto A_blk = rcp_dynamic_cast<const BlockedCrsMatrix>(rcpFromRef(A));
127 auto B_blk = rcp_dynamic_cast<const BlockedCrsMatrix>(rcpFromRef(B));
128 if (A_blk != Teuchos::null && B_blk != Teuchos::null) {
129 return TwoMatrixMultiplyBlock(*A_blk, transposeA, *B_blk, transposeB, fos);
138 if (C == Teuchos::null) {
139 double nnzPerRow = Teuchos::as<double>(0);
148 nnzPerRow *= nnzPerRow;
151 if (totalNnz < minNnz)
155 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
165 fos <<
"Reuse C pattern" << std::endl;
168 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
185 bool doOptimizeStorage) {
189 const size_t A_inner = transposeA ? A.
Rows() : A.
Cols();
190 const size_t B_inner = transposeB ? B.
Cols() : B.
Rows();
192 "TwoMatrixMultiplyBlock: Block dimensions are not compatible for multiplication. "
194 << A_inner <<
" block columns and B has " << B_inner <<
" block rows.");
201 for (
size_t i = 0; i < A.
Rows(); ++i) {
202 for (
size_t j = 0; j < B.
Cols(); ++j) {
205 const size_t innerDim = transposeB ? B.
Cols() : B.
Rows();
206 for (
size_t l = 0; l < innerDim; ++l) {
215 auto unwrap1 = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(crmat1);
216 auto unwrap2 = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(crmat2);
218 if (unwrap1.is_null() != unwrap2.is_null()) {
219 if (unwrap1 != Teuchos::null && unwrap1->Rows() == 1 && unwrap1->Cols() == 1)
220 crmat1 = unwrap1->getCrsMatrix();
221 if (unwrap2 != Teuchos::null && unwrap2->Rows() == 1 && unwrap2->Cols() == 1)
222 crmat2 = unwrap2->getCrsMatrix();
229 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
233 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
235 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
238 "crmat1 does not have global constants");
240 "crmat2 does not have global constants");
242 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
248 if (crop1 != Teuchos::null && crop2 != Teuchos::null)
249 temp = Multiply(*crop1, transposeA, *crop2, transposeB, fos);
256 const auto op1Cols = transposeA ? bop1->Rows() : bop1->Cols();
257 const auto op2Rows = transposeB ? bop2->Cols() : bop2->Rows();
260 const auto op1DomainMap = transposeA ? bop1->getRangeMap() : bop1->getDomainMap();
261 const auto op2RangeMap = transposeB ? bop2->getDomainMap() : bop2->getRangeMap();
265 temp = TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
267 const auto op1Rows = transposeA ? bop1->Cols() : bop1->Rows();
268 const auto op2Cols = transposeB ? bop2->Rows() : bop2->Cols();
270 const auto bop1RangeMap = transposeA ? bop1->getDomainMapExtractor() : bop1->getRangeMapExtractor();
271 const auto bop2DomainMap = transposeB ? bop2->getRangeMapExtractor() : bop2->getDomainMapExtractor();
294 if (Cij->isFillComplete())
299 Cij->fillComplete(BjDomainMap, AiDomainMap);
301 C->setMatrix(i, j, Cij);
303 C->setMatrix(i, j, Teuchos::null);
329 const Matrix& B,
bool transposeB,
const SC& beta,
342 if (rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
348 const tcrs_matrix_type& tpA = helpers::Op2TpetraCrs(A);
349 const tcrs_matrix_type& tpB = helpers::Op2TpetraCrs(B);
350 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
353 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
354 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
358 else if (rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
366 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
368 if (rcpA != Teuchos::null &&
369 rcpBopB->getMatrix(i, j) != Teuchos::null) {
371 TwoMatrixAdd(*rcpA, transposeA, alpha,
372 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
373 Cij, fos, AHasFixedNnzPerRow);
374 }
else if (rcpA == Teuchos::null &&
375 rcpBopB->getMatrix(i, j) != Teuchos::null) {
376 Cij = rcpBopB->getMatrix(i, j);
377 }
else if (rcpA != Teuchos::null &&
378 rcpBopB->getMatrix(i, j) == Teuchos::null) {
379 Cij = Teuchos::rcp_const_cast<Matrix>(rcpA);
385 if (Cij->isFillComplete())
388 bC->setMatrix(i, j, Cij);
390 bC->setMatrix(i, j, Teuchos::null);
395 else if (rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
402 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
404 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
405 rcpB != Teuchos::null) {
407 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
408 *rcpB, transposeB, beta,
409 Cij, fos, AHasFixedNnzPerRow);
410 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
411 rcpB != Teuchos::null) {
412 Cij = Teuchos::rcp_const_cast<Matrix>(rcpB);
413 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
414 rcpB == Teuchos::null) {
415 Cij = rcpBopA->getMatrix(i, j);
421 if (Cij->isFillComplete())
424 bC->setMatrix(i, j, Cij);
426 bC->setMatrix(i, j, Teuchos::null);
447 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
448 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
451 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
452 rcpBopB->getMatrix(i, j) != Teuchos::null) {
454 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
455 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
456 Cij, fos, AHasFixedNnzPerRow);
457 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
458 rcpBopB->getMatrix(i, j) != Teuchos::null) {
459 Cij = rcpBopB->getMatrix(i, j);
460 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
461 rcpBopB->getMatrix(i, j) == Teuchos::null) {
462 Cij = rcpBopA->getMatrix(i, j);
468 if (Cij->isFillComplete())
471 bC->setMatrix(i, j, Cij);
473 bC->setMatrix(i, j, Teuchos::null);
void Multiply(const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, bool transposeA, const CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B, bool transposeB, CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &C, bool call_FillComplete_on_result=true, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)