10#ifndef PACKAGES_XPETRA_SUP_UTILS_XPETRA_MATRIXMATRIX_DECL_HPP_
11#define PACKAGES_XPETRA_SUP_UTILS_XPETRA_MATRIXMATRIX_DECL_HPP_
15#include "Xpetra_BlockedCrsMatrix.hpp"
16#include "Xpetra_CrsMatrixWrap.hpp"
17#include "Xpetra_MapExtractor.hpp"
18#include "Xpetra_Map.hpp"
19#include "Xpetra_MatrixFactory.hpp"
20#include "Xpetra_Matrix.hpp"
21#include "Xpetra_StridedMapFactory.hpp"
22#include "Xpetra_StridedMap.hpp"
24#include "Xpetra_Helpers.hpp"
26#ifdef HAVE_XPETRA_EPETRA
30#ifdef HAVE_XPETRA_EPETRAEXT
31#include <EpetraExt_MatrixMatrix.h>
32#include <EpetraExt_RowMatrixOut.h>
33#include <Epetra_RowMatrixTransposer.h>
36#ifdef HAVE_XPETRA_TPETRA
37#include <TpetraExt_MatrixMatrix.hpp>
38#include <Tpetra_RowMatrixTransposer.hpp>
39#include <MatrixMarket_Tpetra.hpp>
40#include <Xpetra_TpetraCrsMatrix.hpp>
41#include <Xpetra_TpetraBlockCrsMatrix.hpp>
42#include <Tpetra_BlockCrsMatrix_Helpers.hpp>
43#include <Xpetra_TpetraMultiVector.hpp>
44#include <Xpetra_TpetraVector.hpp>
49template <
class Scalar,
54#undef XPETRA_MATRIXMATRIX_SHORT
83 const Matrix& B,
bool transposeB,
85 bool call_FillComplete_on_result =
true,
86 bool doOptimizeStorage =
true,
87 const std::string& label = std::string(),
114 bool doFillComplete =
true,
115 bool doOptimizeStorage =
true,
116 const std::string& label = std::string(),
130 bool callFillCompleteOnResult =
true,
bool doOptimizeStorage =
true,
const std::string& label = std::string(),
133#ifdef HAVE_XPETRA_EPETRAEXT
153 bool doFillComplete =
true,
154 bool doOptimizeStorage =
true);
185 const Matrix& B,
bool transposeB,
const SC& beta,
190#ifdef HAVE_XPETRA_EPETRA
226 const Matrix& B,
bool transposeB,
228 bool call_FillComplete_on_result =
true,
229 bool doOptimizeStorage =
true,
230 const std::string& label = std::string(),
240 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
245#if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
246 helpers::epetraExtMult(A, transposeA, B, transposeB, C, haveMultiplyDoFillComplete);
251#ifdef HAVE_XPETRA_TPETRA
252#if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \
253 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT))))
256 if (helpers::isTpetraCrs(A) && helpers::isTpetraCrs(B) && helpers::isTpetraCrs(C)) {
258 const Tpetra::CrsMatrix<SC, LO, GO, NO>& tpA = helpers::Op2TpetraCrs(A);
259 const Tpetra::CrsMatrix<SC, LO, GO, NO>& tpB = helpers::Op2TpetraCrs(B);
260 Tpetra::CrsMatrix<SC, LO, GO, NO>& tpC = helpers::Op2NonConstTpetraCrs(C);
264 Tpetra::MatrixMatrix::Multiply(tpA, transposeA, tpB, transposeB, tpC, haveMultiplyDoFillComplete, label, params);
265 }
else if (helpers::isTpetraBlockCrs(A) && helpers::isTpetraBlockCrs(B)) {
270 if (!A.
getRowMap()->getComm()->getRank())
271 std::cout <<
"WARNING: Using inefficient BlockCrs Multiply Placeholder" << std::endl;
275 using CRS = Tpetra::CrsMatrix<SC, LO, GO, NO>;
281 if (!params.is_null()) {
283 new_params->set(
"compute global constants",
true);
288 Tpetra::MatrixMatrix::Multiply(*Acrs, transposeA, *Bcrs, transposeB, *tempAc, haveMultiplyDoFillComplete, label, new_params);
297 Ac_w->replaceCrsMatrix(Ac_p);
308 if (call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
310 fillParams->set(
"Optimize Storage", doOptimizeStorage);
317 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<Matrix>(Teuchos::rcpFromRef(A));
318 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<Matrix>(Teuchos::rcpFromRef(B));
319 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
345 const Matrix& B,
bool transposeB,
348 bool doFillComplete =
true,
349 bool doOptimizeStorage =
true,
350 const std::string& label = std::string(),
357#if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT) && defined(HAVE_XPETRA_ML_MMM)
363 RCP<Matrix> C = Convert_Epetra_CrsMatrix_ToXpetra_CrsMatrixWrap<SC, LO, GO, NO>(epC);
364 if (doFillComplete) {
366 fillParams->set(
"Optimize Storage", doOptimizeStorage);
373 C->CreateView(
"stridedMaps", rcpFromRef(A), transposeA, rcpFromRef(B), transposeB);
382 if (C == Teuchos::null) {
383 double nnzPerRow = Teuchos::as<double>(0);
392 nnzPerRow *= nnzPerRow;
395 if (totalNnz < minNnz)
399 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
410 fos <<
"Reuse C pattern" << std::endl;
413 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
429 const Matrix& B,
bool transposeB,
431 bool callFillCompleteOnResult =
true,
432 bool doOptimizeStorage =
true,
433 const std::string& label = std::string(),
435 return Multiply(A, transposeA, B, transposeB, Teuchos::null, fos, callFillCompleteOnResult, doOptimizeStorage, label, params);
438#if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
443#if defined(HAVE_XPETRA_ML_MMM)
445 ML_Comm_Create(&comm);
446 fos <<
"****** USING ML's MATRIX MATRIX MULTIPLY ******" << std::endl;
451 ML_Comm_Set_UsrComm(comm, Mcomm->
GetMpiComm());
454 EpetraExt::CrsMatrix_SolverMap Atransform;
455 EpetraExt::CrsMatrix_SolverMap Btransform;
463 ML_Operator* ml_As = ML_Operator_Create(comm);
464 ML_Operator* ml_Bs = ML_Operator_Create(comm);
467 ML_Operator* ml_AtimesB = ML_Operator_Create(comm);
470 ML_2matmult(ml_As, ml_Bs, ml_AtimesB, ML_CSR_MATRIX);
472 ML_Operator_Destroy(&ml_As);
473 ML_Operator_Destroy(&ml_Bs);
478 int N_local = ml_AtimesB->invec_leng;
479 ML_CommInfoOP* getrow_comm = ml_AtimesB->getrow->pre_comm;
481 ML_Comm* comm_AB = ml_AtimesB->comm;
487 for (
int i = 0; i < getrow_comm->N_neighbors; i++) {
488 N_rcvd += (getrow_comm->neighbors)[i].N_rcv;
489 N_send += (getrow_comm->neighbors)[i].N_send;
490 if (((getrow_comm->neighbors)[i].N_rcv != 0) &&
491 ((getrow_comm->neighbors)[i].rcv_list != NULL)) flag = 1;
495 std::vector<double> dtemp(N_local + N_rcvd + 1);
496 std::vector<int> cmap(N_local + N_rcvd + 1);
497 for (
int i = 0; i < N_local; ++i) {
499 dtemp[i] = (double)cmap[i];
501 ML_cheap_exchange_bdry(&dtemp[0], getrow_comm, N_local, N_send, comm_AB);
504 const int neighbors = getrow_comm->N_neighbors;
505 for (
int i = 0; i < neighbors; i++) {
506 const int nrcv = getrow_comm->neighbors[i].N_rcv;
507 for (
int j = 0; j < nrcv; j++)
508 cmap[getrow_comm->neighbors[i].rcv_list[j]] = (
int)dtemp[count++];
511 for (
int i = 0; i < N_local + N_rcvd; ++i)
512 cmap[i] = (
int)dtemp[i];
530 int educatedguess = 0;
531 for (
int i = 0; i < myrowlength; ++i) {
533 ML_get_matrix_row(ml_AtimesB, 1, &i, &allocated, &bindx, &val, &rowlength, 0);
534 if (rowlength > educatedguess)
535 educatedguess = rowlength;
541 std::vector<int> gcid(educatedguess);
542 for (
int i = 0; i < myrowlength; ++i) {
543 const int grid = rowmap.
GID(i);
545 ML_get_matrix_row(ml_AtimesB, 1, &i, &allocated, &bindx, &val, &rowlength, 0);
546 if (!rowlength)
continue;
547 if ((
int)gcid.size() < rowlength) gcid.resize(rowlength);
548 for (
int j = 0; j < rowlength; ++j) {
549 gcid[j] = gcmap.
GID(bindx[j]);
553 int err = result->InsertGlobalValues(grid, rowlength, val, &gcid[0]);
554 if (err != 0 && err != 1) {
555 std::ostringstream errStr;
556 errStr <<
"Epetra_CrsMatrix::InsertGlobalValues returned err=" << err;
561 if (bindx) ML_free(bindx);
562 if (val) ML_free(val);
563 ML_Operator_Destroy(&ml_AtimesB);
564 ML_Comm_Destroy(&comm);
572 "No ML multiplication available. This feature is currently not supported by Xpetra.");
591 bool doFillComplete =
true,
592 bool doOptimizeStorage =
true) {
594 "TwoMatrixMultiply for BlockedCrsMatrix not implemented for transposeA==true or transposeB==true");
605 for (
size_t i = 0; i < A.
Rows(); ++i) {
606 for (
size_t j = 0; j < B.
Cols(); ++j) {
609 for (
size_t l = 0; l < B.
Rows(); ++l) {
618 auto unwrap1 = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(crmat1);
619 auto unwrap2 = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(crmat2);
621 if (unwrap1.is_null() != unwrap2.is_null()) {
622 if (unwrap1 != Teuchos::null && unwrap1->Rows() == 1 && unwrap1->Cols() == 1)
623 crmat1 = unwrap1->getCrsMatrix();
624 if (unwrap2 != Teuchos::null && unwrap2->Rows() == 1 && unwrap2->Cols() == 1)
625 crmat2 = unwrap2->getCrsMatrix();
632 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
636 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
638 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
641 "crmat1 does not have global constants");
643 "crmat2 does not have global constants");
645 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
651 if (crop1 != Teuchos::null && crop2 != Teuchos::null)
652 temp =
Multiply(*crop1,
false, *crop2,
false, fos);
662 temp =
TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
685 if (Cij->isFillComplete())
688 C->setMatrix(i, j, Cij);
690 C->setMatrix(i, j, Teuchos::null);
715 "TwoMatrixAdd: matrix row maps are not the same.");
718#if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
723 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, beta);
727 std::ostringstream buf;
732#ifdef HAVE_XPETRA_TPETRA
733#if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \
734 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT))))
740 Tpetra::MatrixMatrix::Add(tpA, transposeA, alpha, tpB, beta);
763 const Matrix& B,
bool transposeB,
const SC& beta,
771 if (rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
777#if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
783 size_t numLocalRows = 0;
790 if (maxNzInA == 1 || maxNzInB == 1 || AHasFixedNnzPerRow) {
795 if ((maxNzInA == 1 && maxNzInB > 1) || AHasFixedNnzPerRow) {
796 for (
size_t i = 0; i < numLocalRows; ++i)
800 for (
size_t i = 0; i < numLocalRows; ++i)
804 fos <<
"MatrixMatrix::TwoMatrixAdd : special case detected (one matrix has a fixed nnz per row)"
805 <<
", using static profiling" << std::endl;
814 fos <<
"MatrixMatrix::TwoMatrixAdd : ** WARNING ** estimate could be badly wrong because second summand is transposed" << std::endl;
820 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, transposeB, beta, ref2epC);
828#ifdef HAVE_XPETRA_TPETRA
829#if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_INT))) || \
830 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_INT))))
833 using tcrs_matrix_type = Tpetra::CrsMatrix<SC, LO, GO, NO>;
834 const tcrs_matrix_type& tpA = helpers::Op2TpetraCrs(A);
835 const tcrs_matrix_type& tpB = helpers::Op2TpetraCrs(B);
836 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
844 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
845 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
849 else if (rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
857 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
859 if (rcpA != Teuchos::null &&
860 rcpBopB->getMatrix(i, j) != Teuchos::null) {
863 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
864 Cij, fos, AHasFixedNnzPerRow);
865 }
else if (rcpA == Teuchos::null &&
866 rcpBopB->getMatrix(i, j) != Teuchos::null) {
867 Cij = rcpBopB->getMatrix(i, j);
868 }
else if (rcpA != Teuchos::null &&
869 rcpBopB->getMatrix(i, j) == Teuchos::null) {
870 Cij = Teuchos::rcp_const_cast<Matrix>(rcpA);
876 if (Cij->isFillComplete())
879 bC->setMatrix(i, j, Cij);
881 bC->setMatrix(i, j, Teuchos::null);
886 else if (rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
894 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
896 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
897 rcpB != Teuchos::null) {
899 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
900 *rcpB, transposeB, beta,
901 Cij, fos, AHasFixedNnzPerRow);
902 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
903 rcpB != Teuchos::null) {
904 Cij = Teuchos::rcp_const_cast<Matrix>(rcpB);
905 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
906 rcpB == Teuchos::null) {
907 Cij = rcpBopA->getMatrix(i, j);
913 if (Cij->isFillComplete())
916 bC->setMatrix(i, j, Cij);
918 bC->setMatrix(i, j, Teuchos::null);
940 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
941 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
944 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
945 rcpBopB->getMatrix(i, j) != Teuchos::null) {
948 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
949 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
950 Cij, fos, AHasFixedNnzPerRow);
951 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
952 rcpBopB->getMatrix(i, j) != Teuchos::null) {
953 Cij = rcpBopB->getMatrix(i, j);
954 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
955 rcpBopB->getMatrix(i, j) == Teuchos::null) {
956 Cij = rcpBopA->getMatrix(i, j);
962 if (Cij->isFillComplete())
966 bC->setMatrix(i, j, Cij);
968 bC->setMatrix(i, j, Teuchos::null);
1012 const Matrix& B,
bool transposeB,
1014 bool call_FillComplete_on_result =
true,
1015 bool doOptimizeStorage =
true,
1016 const std::string& label = std::string(),
1027 bool haveMultiplyDoFillComplete = call_FillComplete_on_result && doOptimizeStorage;
1030#if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
1031 helpers::epetraExtMult(A, transposeA, B, transposeB, C, haveMultiplyDoFillComplete);
1036#ifdef HAVE_XPETRA_TPETRA
1037#if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \
1038 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))))
1041 if (helpers::isTpetraCrs(A) && helpers::isTpetraCrs(B) && helpers::isTpetraCrs(C)) {
1043 const Tpetra::CrsMatrix<SC, LO, GO, NO>& tpA = helpers::Op2TpetraCrs(A);
1044 const Tpetra::CrsMatrix<SC, LO, GO, NO>& tpB = helpers::Op2TpetraCrs(B);
1045 Tpetra::CrsMatrix<SC, LO, GO, NO>& tpC = helpers::Op2NonConstTpetraCrs(C);
1049 Tpetra::MatrixMatrix::Multiply(tpA, transposeA, tpB, transposeB, tpC, haveMultiplyDoFillComplete, label, params);
1050 }
else if (helpers::isTpetraBlockCrs(A) && helpers::isTpetraBlockCrs(B)) {
1055 if (!A.
getRowMap()->getComm()->getRank())
1056 std::cout <<
"WARNING: Using inefficient BlockCrs Multiply Placeholder" << std::endl;
1060 using CRS = Tpetra::CrsMatrix<SC, LO, GO, NO>;
1066 if (!params.is_null()) {
1068 new_params->set(
"compute global constants",
true);
1073 Tpetra::MatrixMatrix::Multiply(*Acrs, transposeA, *Bcrs, transposeB, *tempAc, haveMultiplyDoFillComplete, label, new_params);
1082 Ac_w->replaceCrsMatrix(Ac_p);
1094 if (call_FillComplete_on_result && !haveMultiplyDoFillComplete) {
1096 fillParams->set(
"Optimize Storage", doOptimizeStorage);
1103 RCP<Matrix> rcpA = Teuchos::rcp_const_cast<Matrix>(Teuchos::rcpFromRef(A));
1104 RCP<Matrix> rcpB = Teuchos::rcp_const_cast<Matrix>(Teuchos::rcpFromRef(B));
1105 C.
CreateView(
"stridedMaps", rcpA, transposeA, rcpB, transposeB);
1131 const Matrix& B,
bool transposeB,
1134 bool doFillComplete =
true,
1135 bool doOptimizeStorage =
true,
1136 const std::string& label = std::string(),
1144 if (C == Teuchos::null) {
1145 double nnzPerRow = Teuchos::as<double>(0);
1154 nnzPerRow *= nnzPerRow;
1157 if (totalNnz < minNnz)
1161 fos <<
"Matrix product nnz per row estimate = " << Teuchos::as<LO>(nnzPerRow) << std::endl;
1171 fos <<
"Reuse C pattern" << std::endl;
1174 Multiply(A, transposeA, B, transposeB, *C, doFillComplete, doOptimizeStorage, label, params);
1190 const Matrix& B,
bool transposeB,
1192 bool callFillCompleteOnResult =
true,
1193 bool doOptimizeStorage =
true,
1194 const std::string& label = std::string(),
1196 return Multiply(A, transposeA, B, transposeB, Teuchos::null, fos, callFillCompleteOnResult, doOptimizeStorage, label, params);
1199#if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
1205 "No ML multiplication available. This feature is currently not supported by Xpetra.");
1223 bool doFillComplete =
true,
1224 bool doOptimizeStorage =
true) {
1226 "TwoMatrixMultiply for BlockedCrsMatrix not implemented for transposeA==true or transposeB==true");
1237 for (
size_t i = 0; i < A.
Rows(); ++i) {
1238 for (
size_t j = 0; j < B.
Cols(); ++j) {
1241 for (
size_t l = 0; l < B.
Rows(); ++l) {
1250 auto unwrap1 = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(crmat1);
1251 auto unwrap2 = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(crmat2);
1253 if (unwrap1.is_null() != unwrap2.is_null()) {
1254 if (unwrap1 != Teuchos::null && unwrap1->Rows() == 1 && unwrap1->Cols() == 1)
1255 crmat1 = unwrap1->getCrsMatrix();
1256 if (unwrap2 != Teuchos::null && unwrap2->Rows() == 1 && unwrap2->Cols() == 1)
1257 crmat2 = unwrap2->getCrsMatrix();
1264 "A and B must be either both (compatible) BlockedCrsMatrix objects or both CrsMatrixWrap objects.");
1268 Teuchos::rcp_const_cast<CrsGraph>(crmat1->getCrsGraph())->computeGlobalConstants();
1270 Teuchos::rcp_const_cast<CrsGraph>(crmat2->getCrsGraph())->computeGlobalConstants();
1273 "crmat1 does not have global constants");
1275 "crmat2 does not have global constants");
1277 if (crmat1->getGlobalNumEntries() == 0 || crmat2->getGlobalNumEntries() == 0)
1283 if (crop1 != Teuchos::null && crop2 != Teuchos::null)
1284 temp =
Multiply(*crop1,
false, *crop2,
false, fos);
1294 temp =
TwoMatrixMultiplyBlock(*bop1, transposeA, *bop2, transposeB, fos, doFillComplete, doOptimizeStorage);
1317 if (Cij->isFillComplete())
1320 C->setMatrix(i, j, Cij);
1322 C->setMatrix(i, j, Teuchos::null);
1347 "TwoMatrixAdd: matrix row maps are not the same.");
1350#if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
1355 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, beta);
1359 std::ostringstream buf;
1364#ifdef HAVE_XPETRA_TPETRA
1365#if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \
1366 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))))
1372 Tpetra::MatrixMatrix::Add(tpA, transposeA, alpha, tpB, beta);
1395 const Matrix& B,
bool transposeB,
const SC& beta,
1402 if (rcpBopA == Teuchos::null && rcpBopB == Teuchos::null) {
1404 "TwoMatrixAdd: matrix row maps are not the same.");
1407#if defined(HAVE_XPETRA_EPETRA) && defined(HAVE_XPETRA_EPETRAEXT)
1411 size_t maxNzInA = 0;
1412 size_t maxNzInB = 0;
1413 size_t numLocalRows = 0;
1420 if (maxNzInA == 1 || maxNzInB == 1 || AHasFixedNnzPerRow) {
1425 if ((maxNzInA == 1 && maxNzInB > 1) || AHasFixedNnzPerRow) {
1426 for (
size_t i = 0; i < numLocalRows; ++i)
1430 for (
size_t i = 0; i < numLocalRows; ++i)
1434 fos <<
"MatrixMatrix::TwoMatrixAdd : special case detected (one matrix has a fixed nnz per row)"
1435 <<
", using static profiling" << std::endl;
1444 fos <<
"MatrixMatrix::TwoMatrixAdd : ** WARNING ** estimate could be badly wrong because second summand is transposed" << std::endl;
1450 int rv = EpetraExt::MatrixMatrix::Add(epA, transposeA, alpha, epB, transposeB, beta, ref2epC);
1458#ifdef HAVE_XPETRA_TPETRA
1459#if ((defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_OPENMP) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))) || \
1460 (!defined(EPETRA_HAVE_OMP) && (!defined(HAVE_TPETRA_INST_SERIAL) || !defined(HAVE_TPETRA_INST_INT_LONG_LONG))))
1464 using tcrs_matrix_type = Tpetra::CrsMatrix<SC, LO, GO, NO>;
1467 C = helpers::tpetraAdd(tpA, transposeA, alpha, tpB, transposeB, beta);
1475 if (A.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(A));
1476 if (B.
IsView(
"stridedMaps")) C->CreateView(
"stridedMaps", rcpFromRef(B));
1480 else if (rcpBopA == Teuchos::null && rcpBopB != Teuchos::null) {
1488 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
1490 if (rcpA != Teuchos::null &&
1491 rcpBopB->getMatrix(i, j) != Teuchos::null) {
1494 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
1495 Cij, fos, AHasFixedNnzPerRow);
1496 }
else if (rcpA == Teuchos::null &&
1497 rcpBopB->getMatrix(i, j) != Teuchos::null) {
1498 Cij = rcpBopB->getMatrix(i, j);
1499 }
else if (rcpA != Teuchos::null &&
1500 rcpBopB->getMatrix(i, j) == Teuchos::null) {
1501 Cij = Teuchos::rcp_const_cast<Matrix>(rcpA);
1503 Cij = Teuchos::null;
1507 if (Cij->isFillComplete())
1509 Cij->fillComplete();
1510 bC->setMatrix(i, j, Cij);
1512 bC->setMatrix(i, j, Teuchos::null);
1517 else if (rcpBopA != Teuchos::null && rcpBopB == Teuchos::null) {
1525 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
1527 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
1528 rcpB != Teuchos::null) {
1530 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
1531 *rcpB, transposeB, beta,
1532 Cij, fos, AHasFixedNnzPerRow);
1533 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
1534 rcpB != Teuchos::null) {
1535 Cij = Teuchos::rcp_const_cast<Matrix>(rcpB);
1536 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
1537 rcpB == Teuchos::null) {
1538 Cij = rcpBopA->getMatrix(i, j);
1540 Cij = Teuchos::null;
1544 if (Cij->isFillComplete())
1546 Cij->fillComplete();
1547 bC->setMatrix(i, j, Cij);
1549 bC->setMatrix(i, j, Teuchos::null);
1571 for (
size_t i = 0; i < rcpBopA->Rows(); ++i) {
1572 for (
size_t j = 0; j < rcpBopB->Cols(); ++j) {
1575 if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
1576 rcpBopB->getMatrix(i, j) != Teuchos::null) {
1579 TwoMatrixAdd(*(rcpBopA->getMatrix(i, j)), transposeA, alpha,
1580 *(rcpBopB->getMatrix(i, j)), transposeB, beta,
1581 Cij, fos, AHasFixedNnzPerRow);
1582 }
else if (rcpBopA->getMatrix(i, j) == Teuchos::null &&
1583 rcpBopB->getMatrix(i, j) != Teuchos::null) {
1584 Cij = rcpBopB->getMatrix(i, j);
1585 }
else if (rcpBopA->getMatrix(i, j) != Teuchos::null &&
1586 rcpBopB->getMatrix(i, j) == Teuchos::null) {
1587 Cij = rcpBopA->getMatrix(i, j);
1589 Cij = Teuchos::null;
1593 if (Cij->isFillComplete())
1596 Cij->fillComplete();
1597 bC->setMatrix(i, j, Cij);
1599 bC->setMatrix(i, j, Teuchos::null);
1612#define XPETRA_MATRIXMATRIX_SHORT
int NumMyElements() const
const Epetra_Map & RowMap() const
const Epetra_Comm & Comm() const
const Epetra_Map & RangeMap() const
const Epetra_Map & ColMap() const
const Epetra_Map & DomainMap() const
MPI_Comm GetMpiComm() const
static RCP< Time > getNewTimer(const std::string &name)
virtual size_t Cols() const
number of column blocks
const RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
bool isFillComplete() const
Returns true if fillComplete() has been called and the matrix is in compute mode.
const RCP< const Map > getDomainMap() const
Returns the Map associated with the domain of this operator.
virtual size_t Rows() const
number of row blocks
RCP< const MapExtractor > getRangeMapExtractor() const
Returns map extractor class for range map.
RCP< const MapExtractor > getDomainMapExtractor() const
Returns map extractor for domain map.
Concrete implementation of Xpetra::Matrix.
Exception indicating invalid cast attempted.
Exception throws to report incompatible objects (like maps).
Exception throws to report errors in the internal logical of the program.
static RCP< const Epetra_CrsMatrix > Op2EpetraCrs(RCP< Matrix > Op)
static RCP< Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2NonConstTpetraCrs(RCP< Matrix > Op)
static RCP< const Tpetra::BlockCrsMatrix< SC, LO, GO, NO > > Op2TpetraBlockCrs(RCP< Matrix > Op)
static RCP< Epetra_CrsMatrix > Op2NonConstEpetraCrs(RCP< Matrix > Op)
static RCP< const Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2TpetraCrs(RCP< Matrix > Op)
static RCP< Matrix > Build(const RCP< const Map > &rowMap)
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, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
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 RCP< BlockedCrsMatrix > TwoMatrixMultiplyBlock(const BlockedCrsMatrix &A, bool transposeA, const BlockedCrsMatrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool doFillComplete=true, bool doOptimizeStorage=true)
Helper function to do matrix-matrix multiply "in-place".
static RCP< Matrix > Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool callFillCompleteOnResult=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
Helper function to do matrix-matrix multiply.
static void Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Matrix &C, bool call_FillComplete_on_result=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
static RCP< Epetra_CrsMatrix > MLTwoMatrixMultiply(const Epetra_CrsMatrix &epA, const Epetra_CrsMatrix &epB, Teuchos::FancyOStream &fos)
static RCP< Matrix > Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool callFillCompleteOnResult=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
Helper function to do matrix-matrix multiply.
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
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 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 void Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Matrix &C, bool call_FillComplete_on_result=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
static RCP< BlockedCrsMatrix > TwoMatrixMultiplyBlock(const BlockedCrsMatrix &A, bool transposeA, const BlockedCrsMatrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool doFillComplete=true, bool doOptimizeStorage=true)
Helper function to do matrix-matrix multiply "in-place".
static RCP< BlockedCrsMatrix > TwoMatrixMultiplyBlock(const BlockedCrsMatrix &A, bool transposeA, const BlockedCrsMatrix &B, bool transposeB, Teuchos::FancyOStream &fos, bool doFillComplete=true, bool doOptimizeStorage=true)
Helper function to do matrix-matrix multiply "in-place".
static RCP< Epetra_CrsMatrix > MLTwoMatrixMultiply(const Epetra_CrsMatrix &epA, const Epetra_CrsMatrix &epB, Teuchos::FancyOStream &fos)
static void Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Matrix &C, bool call_FillComplete_on_result=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > ¶ms=null)
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
Xpetra-specific matrix class.
virtual global_size_t getGlobalNumEntries() const =0
Returns the global number of entries in this matrix.
void CreateView(viewLabel_t viewLabel, const RCP< const Map > &rowMap, const RCP< const Map > &colMap)
virtual global_size_t getGlobalNumRows() const =0
Returns the number of global rows in this matrix.
virtual const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
virtual bool isFillComplete() const =0
Returns true if fillComplete() has been called and the matrix is in compute mode.
virtual size_t getLocalNumRows() const =0
Returns the number of matrix rows owned on the calling node.
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.
virtual size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const =0
Returns the current number of entries on this node in the specified local row.
bool IsView(const viewLabel_t viewLabel) const
virtual size_t getLocalMaxNumRowEntries() const =0
Returns the maximum number of entries across all rows/columns on this node.
virtual LocalOrdinal GetStorageBlockSize() const =0
Returns the block size of the storage mechanism, which is usually 1, except for Tpetra::BlockCrsMatri...
virtual const Teuchos::RCP< const map_type > getDomainMap() const =0
The Map associated with the domain of this operator, which must be compatible with X....
virtual const Teuchos::RCP< const map_type > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y....
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
#define TEUCHOS_UNREACHABLE_RETURN(dummyReturnVal)
std::string toString(const T &t)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Tpetra::KokkosCompat::KokkosSerialWrapperNode EpetraNode