46 #ifndef XPETRA_BLOCKEDCRSMATRIX_HPP
47 #define XPETRA_BLOCKEDCRSMATRIX_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>
90 template <
class Scalar,
95 public Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
103 #undef XPETRA_BLOCKEDCRSMATRIX_SHORT
130 for (
size_t r = 0; r <
Rows(); ++r)
131 for (
size_t c = 0; c <
Cols(); ++c)
158 for (
size_t r = 0; r <
Rows(); ++r)
159 for (
size_t c = 0; c <
Cols(); ++c)
166 #ifdef HAVE_XPETRA_THYRA
181 int numRangeBlocks = productRangeSpace->numBlocks();
182 int numDomainBlocks = productDomainSpace->numBlocks();
185 std::vector<Teuchos::RCP<const Map> > subRangeMaps(numRangeBlocks);
186 for (
size_t r=0; r<Teuchos::as<size_t>(numRangeBlocks); ++r) {
187 for (
size_t c=0; c<Teuchos::as<size_t>(numDomainBlocks); ++c) {
188 if (thyraOp->blockExists(r,c)) {
193 subRangeMaps[r] = xop->getRangeMap();
203 bool bRangeUseThyraStyleNumbering =
false;
204 size_t numAllElements = 0;
205 for(
size_t v = 0; v < subRangeMaps.size(); ++v) {
206 numAllElements += subRangeMaps[v]->getGlobalNumElements();
208 if ( fullRangeMap->getGlobalNumElements() != numAllElements) bRangeUseThyraStyleNumbering =
true;
212 std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > > subDomainMaps(numDomainBlocks);
213 for (
size_t c=0; c<Teuchos::as<size_t>(numDomainBlocks); ++c) {
214 for (
size_t r=0; r<Teuchos::as<size_t>(numRangeBlocks); ++r) {
215 if (thyraOp->blockExists(r,c)) {
220 subDomainMaps[c] = xop->getDomainMap();
227 bool bDomainUseThyraStyleNumbering =
false;
229 for(
size_t v = 0; v < subDomainMaps.size(); ++v) {
230 numAllElements += subDomainMaps[v]->getGlobalNumElements();
232 if (fullDomainMap->getGlobalNumElements() != numAllElements) bDomainUseThyraStyleNumbering =
true;
241 for (
size_t r = 0; r <
Rows(); ++r) {
242 for (
size_t c = 0; c <
Cols(); ++c) {
243 if(thyraOp->blockExists(r,c)) {
275 std::vector<GlobalOrdinal> gids;
276 for(
size_t tt = 0; tt<subMaps.size(); ++tt) {
280 gids.insert(gids.end(), subMapGids.
begin(), subMapGids.
end());
282 size_t myNumElements = subMap->getNodeNumElements();
283 for(LocalOrdinal l = 0; l < Teuchos::as<LocalOrdinal>(myNumElements); ++l) {
284 GlobalOrdinal gid = subMap->getGlobalElement(l);
295 std::sort(gids.begin(), gids.end());
296 gids.erase(std::unique(gids.begin(), gids.end()), gids.end());
343 getMatrix(0,0)->insertGlobalValues(globalRow, cols, vals);
363 getMatrix(0,0)->insertLocalValues(localRow, cols, vals);
370 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::removeEmptyProcessesInPlace");
372 getMatrix(0,0)->removeEmptyProcessesInPlace(newMap);
392 getMatrix(0,0)->replaceGlobalValues(globalRow,cols,vals);
408 getMatrix(0,0)->replaceLocalValues(localRow,cols,vals);
417 for (
size_t row = 0; row <
Rows(); row++) {
418 for (
size_t col = 0; col <
Cols(); col++) {
420 getMatrix(row,col)->setAllToScalar(alpha);
429 for (
size_t row = 0; row <
Rows(); row++) {
430 for (
size_t col = 0; col <
Cols(); col++) {
452 for (
size_t row = 0; row <
Rows(); row++) {
453 for (
size_t col = 0; col <
Cols(); col++) {
469 getMatrix(0,0)->fillComplete(domainMap, rangeMap, params);
493 for (
size_t r = 0; r <
Rows(); ++r)
494 for (
size_t c = 0; c <
Cols(); ++c) {
498 if (Ablock != Teuchos::null && !Ablock->isFillComplete())
506 fullrowmap_ =
MapFactory::Build(rangeMap()->lib(), rangeMap()->getGlobalNumElements(), rangeMap()->getNodeElementList(), rangeMap()->getIndexBase(), rangeMap()->getComm());
509 fullcolmap_ = Teuchos::null;
511 std::vector<GO> colmapentries;
512 for (
size_t c = 0; c <
Cols(); ++c) {
515 for (
size_t r = 0; r <
Rows(); ++r) {
518 if (Ablock != Teuchos::null) {
521 copy(colElements.
getRawPtr(), colElements.
getRawPtr() + colElements.
size(), inserter(colset, colset.begin()));
526 colmapentries.reserve(colmapentries.size() + colset.size());
527 copy(colset.begin(), colset.end(), back_inserter(colmapentries));
528 sort(colmapentries.begin(), colmapentries.end());
529 typename std::vector<GO>::iterator gendLocation;
530 gendLocation = std::unique(colmapentries.begin(), colmapentries.end());
531 colmapentries.erase(gendLocation,colmapentries.end());
535 size_t numGlobalElements = 0;
536 Teuchos::reduceAll(*(rangeMap->
getComm()), Teuchos::REDUCE_SUM, colmapentries.size(), Teuchos::outArg(numGlobalElements));
553 for (
size_t row = 0; row <
Rows(); row++)
554 for (
size_t col = 0; col <
Cols(); col++)
556 globalNumRows +=
getMatrix(row,col)->getGlobalNumRows();
560 return globalNumRows;
570 for (
size_t col = 0; col <
Cols(); col++)
571 for (
size_t row = 0; row <
Rows(); row++)
573 globalNumCols +=
getMatrix(row,col)->getGlobalNumCols();
577 return globalNumCols;
585 for (
size_t row = 0; row <
Rows(); ++row)
586 for (
size_t col = 0; col <
Cols(); col++)
588 nodeNumRows +=
getMatrix(row,col)->getNodeNumRows();
600 for (
size_t row = 0; row <
Rows(); ++row)
601 for (
size_t col = 0; col <
Cols(); ++col)
603 globalNumEntries +=
getMatrix(row,col)->getGlobalNumEntries();
605 return globalNumEntries;
613 for (
size_t row = 0; row <
Rows(); ++row)
614 for (
size_t col = 0; col <
Cols(); ++col)
616 nodeNumEntries +=
getMatrix(row,col)->getNodeNumEntries();
618 return nodeNumEntries;
624 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNumEntriesInLocalRow");
626 return getMatrix(0,0)->getNumEntriesInLocalRow(localRow);
629 GlobalOrdinal gid = this->
getRowMap()->getGlobalElement(localRow);
640 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getGlobalMaxNumRowEntries");
643 for (
size_t row = 0; row <
Rows(); row++) {
645 for (
size_t col = 0; col <
Cols(); col++) {
647 globalMaxEntriesBlockRows +=
getMatrix(row,col)->getGlobalMaxNumRowEntries();
650 if(globalMaxEntriesBlockRows > globalMaxEntries)
651 globalMaxEntries = globalMaxEntriesBlockRows;
653 return globalMaxEntries;
660 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNodeMaxNumRowEntries");
661 size_t localMaxEntries = 0;
663 for (
size_t row = 0; row <
Rows(); row++) {
664 size_t localMaxEntriesBlockRows = 0;
665 for (
size_t col = 0; col <
Cols(); col++) {
667 localMaxEntriesBlockRows +=
getMatrix(row,col)->getNodeMaxNumRowEntries();
670 if(localMaxEntriesBlockRows > localMaxEntries)
671 localMaxEntries = localMaxEntriesBlockRows;
673 return localMaxEntries;
682 for (
size_t i = 0; i <
blocks_.size(); ++i)
694 for (
size_t i = 0; i <
blocks_.size(); i++)
703 for (
size_t i = 0; i <
blocks_.size(); i++)
727 size_t &NumEntries)
const {
730 getMatrix(0,0)->getLocalRowCopy(LocalRow, Indices, Values, NumEntries);
749 getMatrix(0,0)->getGlobalRowView(GlobalRow, indices, values);
768 getMatrix(0,0)->getLocalRowView(LocalRow, indices, values);
773 GlobalOrdinal gid = this->
getRowMap()->getGlobalElement(LocalRow);
798 rm->getLocalDiagCopy(diag);
805 "BlockedCrsMatrix::getLocalDiagCopy(): the number of blocks in diag differ from the number of blocks in this operator." );
809 for (
size_t row = 0; row <
Rows(); row++) {
813 rm->getLocalDiagCopy(*rv);
814 bdiag->setMultiVector(row,rv,bdiag->getBlockedMap()->getThyraMode());
832 for (
size_t col = 0; col <
Cols(); ++col) {
842 "BlockedCrsMatrix::leftScale(): the number of blocks in diag differ from the number of blocks in this operator." );
844 for (
size_t row = 0; row <
Rows(); row++) {
848 for (
size_t col = 0; col <
Cols(); ++col) {
851 rm->leftScale(*rscale);
870 for (
size_t row = 0; row <
Rows(); ++row) {
880 "BlockedCrsMatrix::rightScale(): the number of blocks in diag differ from the number of blocks in this operator." );
882 for (
size_t col = 0; col <
Cols(); ++col) {
886 for (
size_t row = 0; row <
Rows(); row++) {
889 rm->rightScale(*rscale);
900 for (
size_t col = 0; col <
Cols(); ++col) {
901 for (
size_t row = 0; row <
Rows(); ++row) {
959 "apply() only supports the following modes: NO_TRANS and TRANS." );
968 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
980 for (
size_t row = 0; row <
Rows(); row++) {
982 for (
size_t col = 0; col <
Cols(); col++) {
992 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false :
true;
1004 Ablock->apply(*Xblock, *tmpYblock);
1006 Yblock->
update(one, *tmpYblock, one);
1013 for (
size_t col = 0; col <
Cols(); col++) {
1016 for (
size_t row = 0; row<
Rows(); row++) {
1024 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false :
true;
1034 Yblock->
update(one, *tmpYblock, one);
1039 Y.
update(alpha, *tmpY, beta);
1104 "apply() only supports the following modes: NO_TRANS and TRANS." );
1112 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
1122 for (
size_t col = 0; col <
Cols(); col++) {
1132 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false :
true;
1144 Ablock->apply(*Xblock, *tmpYblock);
1146 Yblock->
update(one, *tmpYblock, one);
1152 Y.
update(alpha, *tmpY, beta);
1175 getMatrix(0,0)->doImport(source, importer, CM);
1185 getMatrix(0,0)->doExport(dest, importer, CM);
1195 getMatrix(0,0)->doImport(source, exporter, CM);
1205 getMatrix(0,0)->doExport(dest, exporter, CM);
1217 std::string
description()
const {
return "Xpetra_BlockedCrsMatrix.description()"; }
1221 out <<
"Xpetra::BlockedCrsMatrix: " <<
Rows() <<
" x " <<
Cols() << std::endl;
1224 out <<
"BlockMatrix is fillComplete" << std::endl;
1237 out <<
"BlockMatrix is NOT fillComplete" << std::endl;
1240 for (
size_t r = 0; r <
Rows(); ++r)
1241 for (
size_t c = 0; c <
Cols(); ++c) {
1243 out <<
"Block(" << r <<
"," << c <<
")" << std::endl;
1244 getMatrix(r,c)->describe(out,verbLevel);
1245 }
else out <<
"Block(" << r <<
"," << c <<
") = null" << std::endl;
1251 if (
Rows() == 1 &&
Cols () == 1)
return true;
1285 if (bmat == Teuchos::null)
return mat;
1286 return bmat->getCrsMatrix();
1292 size_t row =
Rows()+1, col =
Cols()+1;
1293 for (
size_t r = 0; r <
Rows(); ++r)
1294 for(
size_t c = 0; c <
Cols(); ++c)
1303 if (bmat == Teuchos::null)
return mm;
1304 return bmat->getInnermostCrsMatrix();
1339 using Teuchos::rcp_dynamic_cast;
1343 "BlockedCrsMatrix::Merge: only implemented for Xpetra-style or Thyra-style numbering. No mixup allowed!" );
1346 "BlockedCrsMatrix::Merge: BlockMatrix must be fill-completed." );
1352 for (
size_t i = 0; i <
Rows(); i++) {
1353 for (
size_t j = 0; j <
Cols(); j++) {
1359 if (bMat != Teuchos::null) mat = bMat->Merge();
1361 bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1363 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!" );
1366 if(mat->getNodeNumEntries() == 0)
continue;
1368 this->
Add(*mat, one, *sparse, one);
1374 for (
size_t i = 0; i <
Rows(); i++) {
1375 for (
size_t j = 0; j <
Cols(); j++) {
1380 if (bMat != Teuchos::null) mat = bMat->Merge();
1382 bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1384 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!" );
1408 if(mat->getNodeNumEntries() == 0)
continue;
1410 size_t maxNumEntries = mat->getNodeMaxNumRowEntries();
1418 for (
size_t k = 0; k < mat->getNodeNumRows(); k++) {
1420 crsMat->getCrsMatrix()->getGlobalRowCopy(rowTGID, inds(), vals(), numEntries);
1423 for (
size_t l = 0; l < numEntries; ++l) {
1429 sparse->insertGlobalValues(
1430 rowXGID, inds2(0, numEntries),
1431 vals(0, numEntries));
1441 "BlockedCrsMatrix::Merge: Local number of entries of merged matrix does not coincide with local number of entries of blocked operator." );
1444 "BlockedCrsMatrix::Merge: Global number of entries of merged matrix does not coincide with global number of entries of blocked operator." );
1450 #ifdef HAVE_XPETRA_KOKKOS_REFACTOR
1451 typedef typename CrsMatrix::local_matrix_type local_matrix_type;
1454 local_matrix_type getLocalMatrix ()
const {
1456 return getMatrix(0,0)->getLocalMatrix();
1462 #ifdef HAVE_XPETRA_THYRA
1465 Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(Teuchos::rcpFromRef(*
this));
1469 Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<Scalar> >(thOp);
1494 "Matrix A is not completed");
1503 if (scalarA == zero)
1509 "BlockedCrsMatrix::Add: matrix A must be of type CrsMatrixWrap.");
1523 GO row = rowGIDs[i];
1527 for (
size_t j = 0; j < numEntries; ++j)
1556 #ifdef HAVE_XPETRA_THYRA
1566 #define XPETRA_BLOCKEDCRSMATRIX_SHORT