46 #ifndef XPETRA_BLOCKEDCRSMATRIX_HPP
47 #define XPETRA_BLOCKEDCRSMATRIX_HPP
57 #include "Xpetra_MapFactory.hpp"
59 #include "Xpetra_BlockedMultiVector.hpp"
60 #include "Xpetra_MultiVectorFactory.hpp"
61 #include "Xpetra_BlockedVector.hpp"
66 #include "Xpetra_MapExtractor.hpp"
70 #include "Xpetra_CrsMatrixWrap.hpp"
72 #ifdef HAVE_XPETRA_THYRA
73 #include <Thyra_ProductVectorSpaceBase.hpp>
74 #include <Thyra_VectorSpaceBase.hpp>
75 #include <Thyra_LinearOpBase.hpp>
76 #include <Thyra_BlockedLinearOpBase.hpp>
77 #include <Thyra_PhysicallyBlockedLinearOpBase.hpp>
92 template <
class Scalar,
97 public Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
105 #undef XPETRA_BLOCKEDCRSMATRIX_SHORT
132 for (
size_t r = 0; r <
Rows(); ++r)
133 for (
size_t c = 0; c <
Cols(); ++c)
160 for (
size_t r = 0; r <
Rows(); ++r)
161 for (
size_t c = 0; c <
Cols(); ++c)
168 #ifdef HAVE_XPETRA_THYRA
183 int numRangeBlocks = productRangeSpace->numBlocks();
184 int numDomainBlocks = productDomainSpace->numBlocks();
187 std::vector<Teuchos::RCP<const Map> > subRangeMaps(numRangeBlocks);
188 for (
size_t r=0; r<Teuchos::as<size_t>(numRangeBlocks); ++r) {
189 for (
size_t c=0; c<Teuchos::as<size_t>(numDomainBlocks); ++c) {
190 if (thyraOp->blockExists(r,c)) {
195 subRangeMaps[r] = xop->getRangeMap();
205 bool bRangeUseThyraStyleNumbering =
false;
206 size_t numAllElements = 0;
207 for(
size_t v = 0; v < subRangeMaps.size(); ++v) {
208 numAllElements += subRangeMaps[v]->getGlobalNumElements();
210 if ( fullRangeMap->getGlobalNumElements() != numAllElements) bRangeUseThyraStyleNumbering =
true;
214 std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > > subDomainMaps(numDomainBlocks);
215 for (
size_t c=0; c<Teuchos::as<size_t>(numDomainBlocks); ++c) {
216 for (
size_t r=0; r<Teuchos::as<size_t>(numRangeBlocks); ++r) {
217 if (thyraOp->blockExists(r,c)) {
222 subDomainMaps[c] = xop->getDomainMap();
229 bool bDomainUseThyraStyleNumbering =
false;
231 for(
size_t v = 0; v < subDomainMaps.size(); ++v) {
232 numAllElements += subDomainMaps[v]->getGlobalNumElements();
234 if (fullDomainMap->getGlobalNumElements() != numAllElements) bDomainUseThyraStyleNumbering =
true;
243 for (
size_t r = 0; r <
Rows(); ++r) {
244 for (
size_t c = 0; c <
Cols(); ++c) {
245 if(thyraOp->blockExists(r,c)) {
277 std::vector<GlobalOrdinal> gids;
278 for(
size_t tt = 0; tt<subMaps.size(); ++tt) {
282 gids.insert(gids.end(), subMapGids.
begin(), subMapGids.
end());
284 size_t myNumElements = subMap->getNodeNumElements();
285 for(LocalOrdinal l = 0; l < Teuchos::as<LocalOrdinal>(myNumElements); ++l) {
286 GlobalOrdinal gid = subMap->getGlobalElement(l);
297 std::sort(gids.begin(), gids.end());
298 gids.erase(std::unique(gids.begin(), gids.end()), gids.end());
345 getMatrix(0,0)->insertGlobalValues(globalRow, cols, vals);
365 getMatrix(0,0)->insertLocalValues(localRow, cols, vals);
372 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::removeEmptyProcessesInPlace");
374 getMatrix(0,0)->removeEmptyProcessesInPlace(newMap);
394 getMatrix(0,0)->replaceGlobalValues(globalRow,cols,vals);
410 getMatrix(0,0)->replaceLocalValues(localRow,cols,vals);
419 for (
size_t row = 0; row <
Rows(); row++) {
420 for (
size_t col = 0; col <
Cols(); col++) {
422 getMatrix(row,col)->setAllToScalar(alpha);
431 for (
size_t row = 0; row <
Rows(); row++) {
432 for (
size_t col = 0; col <
Cols(); col++) {
454 for (
size_t row = 0; row <
Rows(); row++) {
455 for (
size_t col = 0; col <
Cols(); col++) {
471 getMatrix(0,0)->fillComplete(domainMap, rangeMap, params);
495 for (
size_t r = 0; r <
Rows(); ++r)
496 for (
size_t c = 0; c <
Cols(); ++c) {
500 if (Ablock != Teuchos::null && !Ablock->isFillComplete())
508 fullrowmap_ =
MapFactory::Build(rangeMap()->lib(), rangeMap()->getGlobalNumElements(), rangeMap()->getNodeElementList(), rangeMap()->getIndexBase(), rangeMap()->getComm());
511 fullcolmap_ = Teuchos::null;
513 std::vector<GO> colmapentries;
514 for (
size_t c = 0; c <
Cols(); ++c) {
517 for (
size_t r = 0; r <
Rows(); ++r) {
520 if (Ablock != Teuchos::null) {
523 copy(colElements.
getRawPtr(), colElements.
getRawPtr() + colElements.
size(), inserter(colset, colset.begin()));
528 colmapentries.reserve(colmapentries.size() + colset.size());
529 copy(colset.begin(), colset.end(), back_inserter(colmapentries));
530 sort(colmapentries.begin(), colmapentries.end());
531 typename std::vector<GO>::iterator gendLocation;
532 gendLocation = std::unique(colmapentries.begin(), colmapentries.end());
533 colmapentries.erase(gendLocation,colmapentries.end());
537 size_t numGlobalElements = 0;
538 Teuchos::reduceAll(*(rangeMap->getComm()), Teuchos::REDUCE_SUM, colmapentries.size(), Teuchos::outArg(numGlobalElements));
542 fullcolmap_ =
MapFactory::Build(rangeMap->lib(), numGlobalElements, aView, 0, rangeMap->getComm());
555 for (
size_t row = 0; row <
Rows(); row++)
556 for (
size_t col = 0; col <
Cols(); col++)
558 globalNumRows +=
getMatrix(row,col)->getGlobalNumRows();
562 return globalNumRows;
572 for (
size_t col = 0; col <
Cols(); col++)
573 for (
size_t row = 0; row <
Rows(); row++)
575 globalNumCols +=
getMatrix(row,col)->getGlobalNumCols();
579 return globalNumCols;
587 for (
size_t row = 0; row <
Rows(); ++row)
588 for (
size_t col = 0; col <
Cols(); col++)
590 nodeNumRows +=
getMatrix(row,col)->getNodeNumRows();
602 for (
size_t row = 0; row <
Rows(); ++row)
603 for (
size_t col = 0; col <
Cols(); ++col)
605 globalNumEntries +=
getMatrix(row,col)->getGlobalNumEntries();
607 return globalNumEntries;
615 for (
size_t row = 0; row <
Rows(); ++row)
616 for (
size_t col = 0; col <
Cols(); ++col)
618 nodeNumEntries +=
getMatrix(row,col)->getNodeNumEntries();
620 return nodeNumEntries;
626 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNumEntriesInLocalRow");
628 return getMatrix(0,0)->getNumEntriesInLocalRow(localRow);
631 GlobalOrdinal gid = this->
getRowMap()->getGlobalElement(localRow);
641 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNumEntriesInGlobalRow");
643 return getMatrix(0,0)->getNumEntriesInGlobalRow(globalRow);
652 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getGlobalMaxNumRowEntries");
655 for (
size_t row = 0; row <
Rows(); row++) {
657 for (
size_t col = 0; col <
Cols(); col++) {
659 globalMaxEntriesBlockRows +=
getMatrix(row,col)->getGlobalMaxNumRowEntries();
662 if(globalMaxEntriesBlockRows > globalMaxEntries)
663 globalMaxEntries = globalMaxEntriesBlockRows;
665 return globalMaxEntries;
672 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNodeMaxNumRowEntries");
673 size_t localMaxEntries = 0;
675 for (
size_t row = 0; row <
Rows(); row++) {
676 size_t localMaxEntriesBlockRows = 0;
677 for (
size_t col = 0; col <
Cols(); col++) {
679 localMaxEntriesBlockRows +=
getMatrix(row,col)->getNodeMaxNumRowEntries();
682 if(localMaxEntriesBlockRows > localMaxEntries)
683 localMaxEntries = localMaxEntriesBlockRows;
685 return localMaxEntries;
694 for (
size_t i = 0; i <
blocks_.size(); ++i)
706 for (
size_t i = 0; i <
blocks_.size(); i++)
715 for (
size_t i = 0; i <
blocks_.size(); i++)
739 size_t &NumEntries)
const {
742 getMatrix(0,0)->getLocalRowCopy(LocalRow, Indices, Values, NumEntries);
761 getMatrix(0,0)->getGlobalRowView(GlobalRow, indices, values);
780 getMatrix(0,0)->getLocalRowView(LocalRow, indices, values);
785 GlobalOrdinal gid = this->
getRowMap()->getGlobalElement(LocalRow);
810 rm->getLocalDiagCopy(diag);
817 "BlockedCrsMatrix::getLocalDiagCopy(): the number of blocks in diag differ from the number of blocks in this operator." );
821 for (
size_t row = 0; row <
Rows(); row++) {
825 rm->getLocalDiagCopy(*rv);
826 bdiag->setMultiVector(row,rv,bdiag->getBlockedMap()->getThyraMode());
844 for (
size_t col = 0; col <
Cols(); ++col) {
854 "BlockedCrsMatrix::leftScale(): the number of blocks in diag differ from the number of blocks in this operator." );
856 for (
size_t row = 0; row <
Rows(); row++) {
860 for (
size_t col = 0; col <
Cols(); ++col) {
863 rm->leftScale(*rscale);
882 for (
size_t row = 0; row <
Rows(); ++row) {
892 "BlockedCrsMatrix::rightScale(): the number of blocks in diag differ from the number of blocks in this operator." );
894 for (
size_t col = 0; col <
Cols(); ++col) {
898 for (
size_t row = 0; row <
Rows(); row++) {
901 rm->rightScale(*rscale);
912 for (
size_t col = 0; col <
Cols(); ++col) {
913 for (
size_t row = 0; row <
Rows(); ++row) {
971 "apply() only supports the following modes: NO_TRANS and TRANS." );
980 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
992 for (
size_t row = 0; row <
Rows(); row++) {
994 for (
size_t col = 0; col <
Cols(); col++) {
1004 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false :
true;
1016 Ablock->apply(*Xblock, *tmpYblock);
1018 Yblock->update(one, *tmpYblock, one);
1025 for (
size_t col = 0; col <
Cols(); col++) {
1028 for (
size_t row = 0; row<
Rows(); row++) {
1036 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false :
true;
1046 Yblock->update(one, *tmpYblock, one);
1051 Y.
update(alpha, *tmpY, beta);
1116 "apply() only supports the following modes: NO_TRANS and TRANS." );
1124 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
1134 for (
size_t col = 0; col <
Cols(); col++) {
1144 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false :
true;
1156 Ablock->apply(*Xblock, *tmpYblock);
1158 Yblock->update(one, *tmpYblock, one);
1164 Y.
update(alpha, *tmpY, beta);
1187 getMatrix(0,0)->doImport(source, importer, CM);
1197 getMatrix(0,0)->doExport(dest, importer, CM);
1207 getMatrix(0,0)->doImport(source, exporter, CM);
1217 getMatrix(0,0)->doExport(dest, exporter, CM);
1229 std::string
description()
const {
return "Xpetra_BlockedCrsMatrix.description()"; }
1233 out <<
"Xpetra::BlockedCrsMatrix: " <<
Rows() <<
" x " <<
Cols() << std::endl;
1236 out <<
"BlockMatrix is fillComplete" << std::endl;
1249 out <<
"BlockMatrix is NOT fillComplete" << std::endl;
1252 for (
size_t r = 0; r <
Rows(); ++r)
1253 for (
size_t c = 0; c <
Cols(); ++c) {
1255 out <<
"Block(" << r <<
"," << c <<
")" << std::endl;
1256 getMatrix(r,c)->describe(out,verbLevel);
1257 }
else out <<
"Block(" << r <<
"," << c <<
") = null" << std::endl;
1265 for (
size_t r = 0; r <
Rows(); ++r)
1266 for (
size_t c = 0; c <
Cols(); ++c) {
1268 std::ostringstream oss; oss<< objectLabel <<
"(" << r <<
"," << c <<
")";
1269 getMatrix(r,c)->setObjectLabel(oss.str());
1278 if (
Rows() == 1 &&
Cols () == 1)
return true;
1312 if (bmat == Teuchos::null)
return mat;
1313 return bmat->getCrsMatrix();
1319 size_t row =
Rows()+1, col =
Cols()+1;
1320 for (
size_t r = 0; r <
Rows(); ++r)
1321 for(
size_t c = 0; c <
Cols(); ++c)
1330 if (bmat == Teuchos::null)
return mm;
1331 return bmat->getInnermostCrsMatrix();
1366 using Teuchos::rcp_dynamic_cast;
1370 "BlockedCrsMatrix::Merge: only implemented for Xpetra-style or Thyra-style numbering. No mixup allowed!" );
1373 "BlockedCrsMatrix::Merge: BlockMatrix must be fill-completed." );
1379 for (
size_t i = 0; i <
Rows(); i++) {
1380 for (
size_t j = 0; j <
Cols(); j++) {
1386 if (bMat != Teuchos::null) mat = bMat->Merge();
1388 bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1390 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!" );
1393 if(mat->getNodeNumEntries() == 0)
continue;
1395 this->
Add(*mat, one, *sparse, one);
1401 for (
size_t i = 0; i <
Rows(); i++) {
1402 for (
size_t j = 0; j <
Cols(); j++) {
1407 if (bMat != Teuchos::null) mat = bMat->Merge();
1409 bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1411 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!" );
1435 if(mat->getNodeNumEntries() == 0)
continue;
1437 size_t maxNumEntries = mat->getNodeMaxNumRowEntries();
1445 for (
size_t k = 0; k < mat->getNodeNumRows(); k++) {
1446 GlobalOrdinal rowTGID = trowMap->getGlobalElement(k);
1447 crsMat->getCrsMatrix()->getGlobalRowCopy(rowTGID, inds(), vals(), numEntries);
1450 for (
size_t l = 0; l < numEntries; ++l) {
1451 LocalOrdinal lid = tcolMap->getLocalElement(inds[l]);
1452 inds2[l] = xcolMap->getGlobalElement(lid);
1455 GlobalOrdinal rowXGID = xrowMap->getGlobalElement(k);
1456 sparse->insertGlobalValues(
1457 rowXGID, inds2(0, numEntries),
1458 vals(0, numEntries));
1468 "BlockedCrsMatrix::Merge: Local number of entries of merged matrix does not coincide with local number of entries of blocked operator." );
1471 "BlockedCrsMatrix::Merge: Global number of entries of merged matrix does not coincide with global number of entries of blocked operator." );
1477 #ifdef HAVE_XPETRA_KOKKOS_REFACTOR
1478 typedef typename CrsMatrix::local_matrix_type local_matrix_type;
1481 local_matrix_type getLocalMatrix ()
const {
1483 return getMatrix(0,0)->getLocalMatrix();
1489 #ifdef HAVE_XPETRA_THYRA
1492 Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(Teuchos::rcpFromRef(*
this));
1496 Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<Scalar> >(thOp);
1521 "Matrix A is not completed");
1530 if (scalarA == zero)
1536 "BlockedCrsMatrix::Add: matrix A must be of type CrsMatrixWrap.");
1539 size_t maxNumEntries = crsA->getNodeMaxNumRowEntries();
1549 for (
size_t i = 0; i < crsA->getNodeNumRows(); i++) {
1550 GO row = rowGIDs[i];
1551 crsA->getGlobalRowCopy(row, inds(), vals(), numEntries);
1554 for (
size_t j = 0; j < numEntries; ++j)
1583 #ifdef HAVE_XPETRA_THYRA
1593 #define XPETRA_BLOCKEDCRSMATRIX_SHORT