10#ifndef XPETRA_BLOCKEDCRSMATRIX_DEF_HPP
11#define XPETRA_BLOCKEDCRSMATRIX_DEF_HPP
13#include <Tpetra_KokkosCompat_DefaultNode.hpp>
22#include "Xpetra_MapFactory.hpp"
23#include "Xpetra_MultiVector.hpp"
24#include "Xpetra_BlockedMultiVector.hpp"
25#include "Xpetra_MultiVectorFactory.hpp"
26#include "Xpetra_BlockedVector.hpp"
31#include "Xpetra_MapExtractor.hpp"
34#include "Xpetra_Matrix.hpp"
35#include "Xpetra_MatrixFactory.hpp"
36#include "Xpetra_CrsMatrixWrap.hpp"
38#ifdef HAVE_XPETRA_THYRA
39#include <Thyra_ProductVectorSpaceBase.hpp>
40#include <Thyra_VectorSpaceBase.hpp>
41#include <Thyra_LinearOpBase.hpp>
42#include <Thyra_BlockedLinearOpBase.hpp>
43#include <Thyra_PhysicallyBlockedLinearOpBase.hpp>
44#include "Xpetra_ThyraUtils.hpp"
47#include "Xpetra_VectorFactory.hpp"
55template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
58 size_t numEntriesPerRow)
59 : is_diagonal_(true) {
68 for (
size_t r = 0; r <
Rows(); ++r)
69 for (
size_t c = 0; c <
Cols(); ++c)
76template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
79 size_t numEntriesPerRow)
81 , domainmaps_(domainMapExtractor)
82 , rangemaps_(rangeMapExtractor) {
89 for (
size_t r = 0; r <
Rows(); ++r)
90 for (
size_t c = 0; c <
Cols(); ++c)
97#ifdef HAVE_XPETRA_THYRA
98template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
101 , thyraOp_(thyraOp) {
106 int numRangeBlocks = productRangeSpace->numBlocks();
107 int numDomainBlocks = productDomainSpace->numBlocks();
110 std::vector<Teuchos::RCP<const Map>> subRangeMaps(numRangeBlocks);
111 for (
size_t r = 0; r < Teuchos::as<size_t>(numRangeBlocks); ++r) {
112 for (
size_t c = 0; c < Teuchos::as<size_t>(numDomainBlocks); ++c) {
113 if (thyraOp->blockExists(r, c)) {
117 Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::toXpetra(const_op);
118 subRangeMaps[r] = xop->getRangeMap();
119 if (r != c) is_diagonal_ =
false;
128 bool bRangeUseThyraStyleNumbering =
false;
129 size_t numAllElements = 0;
130 for (
size_t v = 0; v < subRangeMaps.size(); ++v) {
131 numAllElements += subRangeMaps[v]->getGlobalNumElements();
133 if (fullRangeMap->getGlobalNumElements() != numAllElements) bRangeUseThyraStyleNumbering =
true;
137 std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>> subDomainMaps(numDomainBlocks);
138 for (
size_t c = 0; c < Teuchos::as<size_t>(numDomainBlocks); ++c) {
139 for (
size_t r = 0; r < Teuchos::as<size_t>(numRangeBlocks); ++r) {
140 if (thyraOp->blockExists(r, c)) {
144 Xpetra::ThyraUtils<Scalar, LO, GO, Node>::toXpetra(const_op);
145 subDomainMaps[c] = xop->getDomainMap();
152 bool bDomainUseThyraStyleNumbering =
false;
154 for (
size_t v = 0; v < subDomainMaps.size(); ++v) {
155 numAllElements += subDomainMaps[v]->getGlobalNumElements();
157 if (fullDomainMap->getGlobalNumElements() != numAllElements) bDomainUseThyraStyleNumbering =
true;
161 bRangeThyraMode_ = bRangeUseThyraStyleNumbering;
162 bDomainThyraMode_ = bDomainUseThyraStyleNumbering;
165 blocks_.reserve(Rows() * Cols());
166 for (
size_t r = 0; r < Rows(); ++r) {
167 for (
size_t c = 0; c < Cols(); ++c) {
168 if (thyraOp->blockExists(r, c)) {
173 Xpetra::ThyraUtils<Scalar, LO, GO, Node>::toXpetra(op);
175 Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LO, GO, Node>>(xop,
true);
176 blocks_.push_back(xwrap);
179 blocks_.push_back(MatrixFactory::Build(getRangeMap(r, bRangeThyraMode_), 0));
187template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
192 std::vector<GlobalOrdinal> gids;
193 for (
size_t tt = 0; tt < subMaps.size(); ++tt) {
197 gids.insert(gids.end(), subMapGids.
begin(), subMapGids.
end());
199 size_t myNumElements = subMap->getLocalNumElements();
200 for (LocalOrdinal l = 0; l < Teuchos::as<LocalOrdinal>(myNumElements); ++l) {
201 GlobalOrdinal gid = subMap->getGlobalElement(l);
212 std::sort(gids.begin(), gids.end());
213 gids.erase(std::unique(gids.begin(), gids.end()), gids.end());
221template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
224template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
227 if (Rows() == 1 && Cols() == 1) {
228 getMatrix(0, 0)->insertGlobalValues(globalRow, cols, vals);
234template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
237 if (Rows() == 1 && Cols() == 1) {
238 getMatrix(0, 0)->insertLocalValues(localRow, cols, vals);
244template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
247 if (Rows() == 1 && Cols() == 1) {
248 getMatrix(0, 0)->removeEmptyProcessesInPlace(newMap);
254template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
259 if (Rows() == 1 && Cols() == 1) {
260 getMatrix(0, 0)->replaceGlobalValues(globalRow, cols, vals);
266template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
271 if (Rows() == 1 && Cols() == 1) {
272 getMatrix(0, 0)->replaceLocalValues(localRow, cols, vals);
279template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
282 for (
size_t row = 0; row < Rows(); row++) {
283 for (
size_t col = 0; col < Cols(); col++) {
284 if (!getMatrix(row, col).is_null()) {
285 getMatrix(row, col)->setAllToScalar(alpha);
292template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
295 for (
size_t row = 0; row < Rows(); row++) {
296 for (
size_t col = 0; col < Cols(); col++) {
297 if (!getMatrix(row, col).is_null()) {
298 getMatrix(row, col)->scale(alpha);
304template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
307 for (
size_t row = 0; row < Rows(); row++) {
308 for (
size_t col = 0; col < Cols(); col++) {
309 if (!getMatrix(row, col).is_null()) {
310 getMatrix(row, col)->resumeFill(params);
316template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
319 if (Rows() == 1 && Cols() == 1) {
320 getMatrix(0, 0)->fillComplete(domainMap, rangeMap, params);
323 fillComplete(params);
326template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
331 for (
size_t r = 0; r < Rows(); ++r)
332 for (
size_t c = 0; c < Cols(); ++c) {
333 if (getMatrix(r, c) != Teuchos::null) {
335 if (r != c) is_diagonal_ =
false;
336 if (Ablock != Teuchos::null && !Ablock->isFillComplete())
337 Ablock->fillComplete(getDomainMap(c, bDomainThyraMode_), getRangeMap(r, bRangeThyraMode_), params);
344 fullrowmap_ = MapFactory::Build(rangeMap()->lib(), rangeMap()->getGlobalNumElements(), rangeMap()->getLocalElementList(), rangeMap()->getIndexBase(), rangeMap()->getComm());
347 fullcolmap_ = Teuchos::null;
349 std::vector<GO> colmapentries;
350 for (
size_t c = 0; c < Cols(); ++c) {
353 for (
size_t r = 0; r < Rows(); ++r) {
356 if (Ablock != Teuchos::null) {
359 copy(colElements.
getRawPtr(), colElements.
getRawPtr() + colElements.
size(), inserter(colset, colset.begin()));
364 colmapentries.reserve(colmapentries.size() + colset.size());
365 copy(colset.begin(), colset.end(), back_inserter(colmapentries));
366 sort(colmapentries.begin(), colmapentries.end());
367 typename std::vector<GO>::iterator gendLocation;
368 gendLocation = std::unique(colmapentries.begin(), colmapentries.end());
369 colmapentries.erase(gendLocation,colmapentries.end());
373 size_t numGlobalElements = 0;
374 Teuchos::reduceAll(*(rangeMap->getComm()), Teuchos::REDUCE_SUM, colmapentries.size(), Teuchos::outArg(numGlobalElements));
378 fullcolmap_ = MapFactory::Build(rangeMap->lib(), numGlobalElements, aView, 0, rangeMap->getComm());
382template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
387 for (
size_t row = 0; row < Rows(); row++)
388 for (
size_t col = 0; col < Cols(); col++)
389 if (!getMatrix(row, col).is_null()) {
390 globalNumRows += getMatrix(row, col)->getGlobalNumRows();
394 return globalNumRows;
397template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
402 for (
size_t col = 0; col < Cols(); col++)
403 for (
size_t row = 0; row < Rows(); row++)
404 if (!getMatrix(row, col).is_null()) {
405 globalNumCols += getMatrix(row, col)->getGlobalNumCols();
409 return globalNumCols;
412template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
417 for (
size_t row = 0; row < Rows(); ++row)
418 for (
size_t col = 0; col < Cols(); col++)
419 if (!getMatrix(row, col).is_null()) {
420 nodeNumRows += getMatrix(row, col)->getLocalNumRows();
427template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
432 for (
size_t row = 0; row < Rows(); ++row)
433 for (
size_t col = 0; col < Cols(); ++col)
434 if (!getMatrix(row, col).is_null())
435 globalNumEntries += getMatrix(row, col)->getGlobalNumEntries();
437 return globalNumEntries;
440template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
445 for (
size_t row = 0; row < Rows(); ++row)
446 for (
size_t col = 0; col < Cols(); ++col)
447 if (!getMatrix(row, col).is_null())
448 nodeNumEntries += getMatrix(row, col)->getLocalNumEntries();
450 return nodeNumEntries;
453template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
455 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNumEntriesInLocalRow");
456 GlobalOrdinal gid = this->getRowMap()->getGlobalElement(localRow);
457 size_t row = getBlockedRangeMap()->getMapIndexForGID(gid);
458 LocalOrdinal lid = getBlockedRangeMap()->getMap(row)->getLocalElement(gid);
459 size_t numEntriesInLocalRow = 0;
460 for (
size_t col = 0; col < Cols(); ++col)
461 if (!getMatrix(row, col).is_null())
462 numEntriesInLocalRow += getMatrix(row, col)->getNumEntriesInLocalRow(lid);
463 return numEntriesInLocalRow;
466template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
469 size_t row = getBlockedRangeMap()->getMapIndexForGID(globalRow);
470 size_t numEntriesInGlobalRow = 0;
471 for (
size_t col = 0; col < Cols(); ++col)
472 if (!getMatrix(row, col).is_null())
473 numEntriesInGlobalRow += getMatrix(row, col)->getNumEntriesInGlobalRow(globalRow);
474 return numEntriesInGlobalRow;
477template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
479 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getGlobalMaxNumRowEntries");
482 for (
size_t row = 0; row < Rows(); row++) {
484 for (
size_t col = 0; col < Cols(); col++) {
485 if (!getMatrix(row, col).is_null()) {
486 globalMaxEntriesBlockRows += getMatrix(row, col)->getGlobalMaxNumRowEntries();
489 if (globalMaxEntriesBlockRows > globalMaxEntries)
490 globalMaxEntries = globalMaxEntriesBlockRows;
492 return globalMaxEntries;
495template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
497 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getLocalMaxNumRowEntries");
498 size_t localMaxEntries = 0;
500 for (
size_t row = 0; row < Rows(); row++) {
501 size_t localMaxEntriesBlockRows = 0;
502 for (
size_t col = 0; col < Cols(); col++) {
503 if (!getMatrix(row, col).is_null()) {
504 localMaxEntriesBlockRows += getMatrix(row, col)->getLocalMaxNumRowEntries();
507 if (localMaxEntriesBlockRows > localMaxEntries)
508 localMaxEntries = localMaxEntriesBlockRows;
510 return localMaxEntries;
513template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
516 for (
size_t i = 0; i < blocks_.size(); ++i)
517 if (blocks_[i] != Teuchos::null && !blocks_[i]->isLocallyIndexed())
522template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
525 for (
size_t i = 0; i < blocks_.size(); i++)
526 if (blocks_[i] != Teuchos::null && !blocks_[i]->isGloballyIndexed())
531template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
534 for (
size_t i = 0; i < blocks_.size(); i++)
535 if (blocks_[i] != Teuchos::null && !blocks_[i]->isFillComplete())
540template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
544 size_t& NumEntries)
const {
546 if (Rows() == 1 && Cols() == 1) {
547 getMatrix(0, 0)->getLocalRowCopy(LocalRow, Indices, Values, NumEntries);
553template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
556 if (Rows() == 1 && Cols() == 1) {
557 getMatrix(0, 0)->getGlobalRowView(GlobalRow, indices, values);
563template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
566 if (Rows() == 1 && Cols() == 1) {
567 getMatrix(0, 0)->getLocalRowView(LocalRow, indices, values);
569 }
else if (is_diagonal_) {
570 GlobalOrdinal gid = this->getRowMap()->getGlobalElement(LocalRow);
571 size_t row = getBlockedRangeMap()->getMapIndexForGID(gid);
572 getMatrix(row, row)->getLocalRowView(getMatrix(row, row)->getRowMap()->getLocalElement(gid), indices, values);
578template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
590 if (Rows() == 1 && Cols() == 1 && bdiag.
is_null() ==
true) {
592 rm->getLocalDiagCopy(diag);
599 "BlockedCrsMatrix::getLocalDiagCopy(): the number of blocks in diag differ from the number of blocks in this operator.");
603 for (
size_t row = 0; row < Rows(); row++) {
606 Teuchos::RCP<Vector> rv = VectorFactory::Build(bdiag->getBlockedMap()->getMap(row, bdiag->getBlockedMap()->getThyraMode()));
607 rm->getLocalDiagCopy(*rv);
608 bdiag->setMultiVector(row, rv, bdiag->getBlockedMap()->getThyraMode());
613template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
625 if (Rows() == 1 && bx.
is_null() ==
true) {
626 for (
size_t col = 0; col < Cols(); ++col) {
636 "BlockedCrsMatrix::leftScale(): the number of blocks in diag differ from the number of blocks in this operator.");
638 for (
size_t row = 0; row < Rows(); row++) {
642 for (
size_t col = 0; col < Cols(); ++col) {
645 rm->leftScale(*rscale);
651template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
663 if (Cols() == 1 && bx.
is_null() ==
true) {
664 for (
size_t row = 0; row < Rows(); ++row) {
674 "BlockedCrsMatrix::rightScale(): the number of blocks in diag differ from the number of blocks in this operator.");
676 for (
size_t col = 0; col < Cols(); ++col) {
680 for (
size_t row = 0; row < Rows(); row++) {
683 rm->rightScale(*rscale);
689template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
693 for (
size_t col = 0; col < Cols(); ++col) {
694 for (
size_t row = 0; row < Rows(); ++row) {
695 if (getMatrix(row, col) != Teuchos::null) {
704template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
707template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
712template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
721 "apply() only supports the following modes: NO_TRANS and TRANS.");
730 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
741 for (
size_t row = 0; row < Rows(); row++) {
743 for (
size_t col = 0; col < Cols(); col++) {
752 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false :
true;
761 Xblock = domainmaps_->ExtractVector(refbX, col, bDomainThyraMode_);
763 Xblock = domainmaps_->ExtractVector(refX, col, bBlockedSubMatrix ==
true ?
false : bDomainThyraMode_);
766 Ablock->apply(*Xblock, *tmpYblock);
768 Yblock->update(one, *tmpYblock, one);
770 rangemaps_->InsertVector(Yblock, row, tmpY, bRangeThyraMode_);
775 for (
size_t col = 0; col < Cols(); col++) {
778 for (
size_t row = 0; row < Rows(); row++) {
786 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false :
true;
792 Xblock = rangemaps_->ExtractVector(refbX, row, bRangeThyraMode_);
794 Xblock = rangemaps_->ExtractVector(refX, row, bBlockedSubMatrix ==
true ?
false : bRangeThyraMode_);
798 Yblock->update(one, *tmpYblock, one);
800 domainmaps_->InsertVector(Yblock, col, tmpY, bDomainThyraMode_);
803 Y.
update(alpha, *tmpY, beta);
806template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
809 return domainmaps_->getFullMap();
812template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
815 return domainmaps_->getBlockedMap();
818template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
821 return domainmaps_->getMap();
824template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
827 return domainmaps_->getMap(i, bDomainThyraMode_);
830template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
832 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getDomainMap(size_t,bool)");
833 return domainmaps_->getMap(i, bThyraMode);
836template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
839 return rangemaps_->getFullMap();
842template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
845 return rangemaps_->getBlockedMap();
848template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
851 return rangemaps_->getMap();
854template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
857 return rangemaps_->getMap(i, bRangeThyraMode_);
860template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
862 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getRangeMap(size_t,bool)");
863 return rangemaps_->getMap(i, bThyraMode);
866template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
872template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
874 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getDomainMapExtractor()");
878template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
891 "apply() only supports the following modes: NO_TRANS and TRANS.");
899 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
909 for (
size_t col = 0; col < Cols(); col++) {
918 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false :
true;
927 Xblock = domainmaps_->ExtractVector(refbX, col, bDomainThyraMode_);
929 Xblock = domainmaps_->ExtractVector(refX, col, bBlockedSubMatrix ==
true ?
false : bDomainThyraMode_);
932 Ablock->apply(*Xblock, *tmpYblock);
934 Yblock->update(one, *tmpYblock, one);
936 rangemaps_->InsertVector(Yblock, row, tmpY, bRangeThyraMode_);
940 Y.
update(alpha, *tmpY, beta);
943template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
946 if (Rows() == 1 && Cols() == 1) {
947 return getMatrix(0, 0)->getMap();
952template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
955 if (Rows() == 1 && Cols() == 1) {
956 getMatrix(0, 0)->doImport(source, importer, CM);
962template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
965 if (Rows() == 1 && Cols() == 1) {
966 getMatrix(0, 0)->doExport(dest, importer, CM);
972template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
975 if (Rows() == 1 && Cols() == 1) {
976 getMatrix(0, 0)->doImport(source, exporter, CM);
983template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
986 if (Rows() == 1 && Cols() == 1) {
987 getMatrix(0, 0)->doExport(dest, exporter, CM);
993template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
996template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
998 out <<
"Xpetra::BlockedCrsMatrix: " << Rows() <<
" x " << Cols() << std::endl;
1000 if (isFillComplete()) {
1001 out <<
"BlockMatrix is fillComplete" << std::endl;
1014 out <<
"BlockMatrix is NOT fillComplete" << std::endl;
1017 for (
size_t r = 0; r < Rows(); ++r)
1018 for (
size_t c = 0; c < Cols(); ++c) {
1019 if (getMatrix(r, c) != Teuchos::null) {
1020 out <<
"Block(" << r <<
"," << c <<
")" << std::endl;
1021 getMatrix(r, c)->describe(out, verbLevel);
1023 out <<
"Block(" << r <<
"," << c <<
") = null" << std::endl;
1027template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1030 for (
size_t r = 0; r < Rows(); ++r)
1031 for (
size_t c = 0; c < Cols(); ++c) {
1032 if (getMatrix(r, c) != Teuchos::null) {
1033 std::ostringstream oss;
1034 oss << objectLabel <<
"(" << r <<
"," << c <<
")";
1035 getMatrix(r, c)->setObjectLabel(oss.str());
1040template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1042 if (Rows() == 1 && Cols() == 1)
1048template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1051 if (Rows() == 1 && Cols() == 1) {
1052 return getMatrix(0, 0)->getCrsGraph();
1057template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1060template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1063 return rangemaps_->NumMaps();
1066template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1069 return domainmaps_->NumMaps();
1072template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1075 TEUCHOS_TEST_FOR_EXCEPTION(Rows() != 1, std::out_of_range,
"Can only unwrap a 1x1 blocked matrix. The matrix has " << Rows() <<
" block rows, though.");
1076 TEUCHOS_TEST_FOR_EXCEPTION(Cols() != 1, std::out_of_range,
"Can only unwrap a 1x1 blocked matrix. The matrix has " << Cols() <<
" block columns, though.");
1080 if (bmat == Teuchos::null)
return mat;
1081 return bmat->getCrsMatrix();
1084template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1087 size_t row = Rows() + 1, col = Cols() + 1;
1088 for (
size_t r = 0; r < Rows(); ++r)
1089 for (
size_t c = 0; c < Cols(); ++c)
1090 if (getMatrix(r, c) != Teuchos::null) {
1098 if (bmat == Teuchos::null)
return mm;
1099 return bmat->getInnermostCrsMatrix();
1102template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1112 return blocks_[r * Cols() + c];
1115template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1122 if (!mat.
is_null() && r != c) is_diagonal_ =
false;
1124 blocks_[r * Cols() + c] = mat;
1127template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1131 using Teuchos::rcp_dynamic_cast;
1135 "BlockedCrsMatrix::Merge: only implemented for Xpetra-style or Thyra-style numbering. No mixup allowed!");
1138 "BlockedCrsMatrix::Merge: BlockMatrix must be fill-completed.");
1140 LocalOrdinal lclNumRows = getFullRangeMap()->getLocalNumElements();
1142 for (LocalOrdinal lclRow = 0; lclRow < lclNumRows; ++lclRow)
1143 numEntPerRow[lclRow] = getNumEntriesInLocalRow(lclRow);
1145 RCP<Matrix> sparse = MatrixFactory::Build(getFullRangeMap(), numEntPerRow);
1147 if (bRangeThyraMode_ ==
false) {
1149 for (
size_t i = 0; i < Rows(); i++) {
1150 for (
size_t j = 0; j < Cols(); j++) {
1151 if (getMatrix(i, j) != Teuchos::null) {
1156 if (bMat != Teuchos::null) mat = bMat->Merge();
1158 bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1160 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!");
1163 if (mat->getLocalNumEntries() == 0)
continue;
1165 this->
Add(*mat, one, *sparse, one);
1171 for (
size_t i = 0; i < Rows(); i++) {
1172 for (
size_t j = 0; j < Cols(); j++) {
1173 if (getMatrix(i, j) != Teuchos::null) {
1177 if (bMat != Teuchos::null) mat = bMat->Merge();
1179 bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1181 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!");
1193 RCP<const Map> xrowMap = getRangeMapExtractor()->getMap(i,
false);
1194 RCP<const Map> xdomMap = getDomainMapExtractor()->getMap(j,
false);
1205 if (mat->getLocalNumEntries() == 0)
continue;
1207 size_t maxNumEntries = mat->getLocalMaxNumRowEntries();
1215 for (
size_t k = 0; k < mat->getLocalNumRows(); k++) {
1216 GlobalOrdinal rowTGID = trowMap->getGlobalElement(k);
1217 crsMat->getCrsMatrix()->getGlobalRowCopy(rowTGID, inds(), vals(), numEntries);
1220 for (
size_t l = 0; l < numEntries; ++l) {
1221 LocalOrdinal lid = tcolMap->getLocalElement(inds[l]);
1222 inds2[l] = xcolMap->getGlobalElement(lid);
1225 GlobalOrdinal rowXGID = xrowMap->getGlobalElement(k);
1226 sparse->insertGlobalValues(
1227 rowXGID, inds2(0, numEntries),
1228 vals(0, numEntries));
1235 sparse->fillComplete(getFullDomainMap(), getFullRangeMap());
1238 "BlockedCrsMatrix::Merge: Local number of entries of merged matrix does not coincide with local number of entries of blocked operator.");
1241 "BlockedCrsMatrix::Merge: Global number of entries of merged matrix does not coincide with global number of entries of blocked operator.");
1246template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1248 if (Rows() == 1 && Cols() == 1) {
1254template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1255#if KOKKOS_VERSION >= 40799
1260 if (Rows() == 1 && Cols() == 1) {
1266#ifdef HAVE_XPETRA_THYRA
1267template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1270 Xpetra::ThyraUtils<Scalar, LO, GO, Node>::toThyra(Teuchos::rcpFromRef(*
this));
1274 Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<Scalar>>(thOp);
1280template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1283template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1288 R.
update(STS::one(), B, STS::zero());
1292template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1296 "Matrix A is not completed");
1305 if (scalarA == zero)
1311 "BlockedCrsMatrix::Add: matrix A must be of type CrsMatrixWrap.");
1314 size_t maxNumEntries = crsA->getLocalMaxNumRowEntries();
1324 for (
size_t i = 0; i < crsA->getLocalNumRows(); i++) {
1325 GO row = rowGIDs[i];
1326 crsA->getGlobalRowCopy(row, inds(), vals(), numEntries);
1329 for (
size_t j = 0; j < numEntries; ++j)
1336template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1341 this->defaultViewLabel_ =
"point";
1342 this->CreateView(this->GetDefaultViewLabel(), getRangeMap(), getDomainMap());
1345 this->currentViewLabel_ = this->GetDefaultViewLabel();
1350#define XPETRA_BLOCKEDCRSMATRIX_SHORT
#define XPETRA_MONITOR(funcName)
#define XPETRA_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::RCP< const MapExtractor > domainmaps_
full domain map together with all partial domain maps
virtual size_t Cols() const
number of column blocks
Teuchos::RCP< const MapExtractor > rangemaps_
full range map together with all partial domain maps
const RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
BlockedCrsMatrix(const Teuchos::RCP< const BlockedMap > &rangeMaps, const Teuchos::RCP< const BlockedMap > &domainMaps, size_t numEntriesPerRow)
Constructor.
bool bDomainThyraMode_
boolean flag, which is true, if BlockedCrsMatrix has been created using Thyra-style numbering for sub...
std::vector< Teuchos::RCP< Matrix > > blocks_
row major matrix block storage
local_matrix_type::HostMirror getLocalMatrixHost() const
Access the underlying local Kokkos::CrsMatrix object.
bool bRangeThyraMode_
boolean flag, which is true, if BlockedCrsMatrix has been created using Thyra-style numbering for sub...
virtual size_t Rows() const
number of row blocks
local_matrix_type getLocalMatrixDevice() const
Access the underlying local Kokkos::CrsMatrix object.
KokkosSparse::CrsMatrix< impl_scalar_type, LocalOrdinal, execution_space, void, typename local_graph_type::size_type > local_matrix_type
The specialization of Kokkos::CrsMatrix that represents the part of the sparse matrix on each MPI pro...
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
Exception indicating invalid cast attempted.
Exception throws to report incompatible objects (like maps).
Exception throws when you call an unimplemented method of Xpetra.
Exception throws to report errors in the internal logical of the program.
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, LocalGlobal lg=Xpetra::GloballyDistributed)
Map constructor with Xpetra-defined contiguous uniform distribution.
static RCP< Matrix > Build(const RCP< const Map > &rowMap)
Xpetra-specific matrix class.
virtual bool isFillComplete() const =0
Returns true if fillComplete() has been called and the matrix is in compute mode.
virtual void scale(const Scalar &alpha)=0
Scale the current values of a matrix, this = alpha*this.
virtual void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)=0
Insert matrix entries, using global IDs.
virtual size_t getNumVectors() const =0
Number of columns in the multivector.
virtual void update(const Scalar &alpha, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Scalar &beta)=0
Update multi-vector values with scaled values of A, this = beta*this + alpha*A.
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
bool is_null(const std::shared_ptr< T > &p)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
size_t global_size_t
Global size_t object.
CombineMode
Xpetra::Combine Mode enumerable type.
static magnitudeType magnitude(T a)