46 #ifndef XPETRA_BLOCKEDCRSMATRIX_HPP
47 #define XPETRA_BLOCKEDCRSMATRIX_HPP
49 #include <Tpetra_KokkosCompat_DefaultNode.hpp>
51 #include <Teuchos_SerialDenseMatrix.hpp>
52 #include <Teuchos_Hashtable.hpp>
57 #include "Xpetra_MapFactory.hpp"
58 #include "Xpetra_MultiVector.hpp"
59 #include "Xpetra_BlockedMultiVector.hpp"
60 #include "Xpetra_MultiVectorFactory.hpp"
61 #include "Xpetra_BlockedVector.hpp"
66 #include "Xpetra_MapExtractor.hpp"
71 #include "Xpetra_CrsMatrixWrap.hpp"
73 #ifdef HAVE_XPETRA_THYRA
74 #include <Thyra_ProductVectorSpaceBase.hpp>
75 #include <Thyra_VectorSpaceBase.hpp>
76 #include <Thyra_LinearOpBase.hpp>
77 #include <Thyra_BlockedLinearOpBase.hpp>
78 #include <Thyra_PhysicallyBlockedLinearOpBase.hpp>
82 #include "Xpetra_VectorFactory.hpp"
90 #ifdef HAVE_XPETRA_THYRA
91 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
97 template <
class Scalar,
100 class Node = Tpetra::KokkosClassic::DefaultNode::DefaultNodeType>
109 #undef XPETRA_BLOCKEDCRSMATRIX_SHORT
123 const Teuchos::RCP<const BlockedMap>& domainMaps,
124 size_t numEntriesPerRow)
134 for (
size_t r = 0; r <
Rows(); ++r)
135 for (
size_t c = 0; c <
Cols(); ++c)
151 Teuchos::RCP<const MapExtractor>& domainMapExtractor,
152 size_t numEntriesPerRow)
162 for (
size_t r = 0; r <
Rows(); ++r)
163 for (
size_t c = 0; c <
Cols(); ++c)
170 #ifdef HAVE_XPETRA_THYRA
177 BlockedCrsMatrix(
const Teuchos::RCP<
const Thyra::BlockedLinearOpBase<Scalar> >& thyraOp,
const Teuchos::RCP<
const Teuchos::Comm<int> >& )
179 , thyraOp_(thyraOp) {
181 const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<Scalar> > productRangeSpace = thyraOp->productRange();
182 const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<Scalar> > productDomainSpace = thyraOp->productDomain();
184 int numRangeBlocks = productRangeSpace->numBlocks();
185 int numDomainBlocks = productDomainSpace->numBlocks();
188 std::vector<Teuchos::RCP<const Map> > subRangeMaps(numRangeBlocks);
189 for (
size_t r = 0; r < Teuchos::as<size_t>(numRangeBlocks); ++r) {
190 for (
size_t c = 0; c < Teuchos::as<size_t>(numDomainBlocks); ++c) {
191 if (thyraOp->blockExists(r, c)) {
193 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r, c);
194 Teuchos::RCP<const Xpetra::Matrix<Scalar, LO, GO, Node> > xop =
196 subRangeMaps[r] = xop->getRangeMap();
202 Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > fullRangeMap = mergeMaps(subRangeMaps);
206 bool bRangeUseThyraStyleNumbering =
false;
207 size_t numAllElements = 0;
208 for (
size_t v = 0; v < subRangeMaps.size(); ++v) {
209 numAllElements += subRangeMaps[v]->getGlobalNumElements();
211 if (fullRangeMap->getGlobalNumElements() != numAllElements) bRangeUseThyraStyleNumbering =
true;
215 std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > > subDomainMaps(numDomainBlocks);
216 for (
size_t c = 0; c < Teuchos::as<size_t>(numDomainBlocks); ++c) {
217 for (
size_t r = 0; r < Teuchos::as<size_t>(numRangeBlocks); ++r) {
218 if (thyraOp->blockExists(r, c)) {
220 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r, c);
221 Teuchos::RCP<const Xpetra::Matrix<Scalar, LO, GO, Node> > xop =
223 subDomainMaps[c] = xop->getDomainMap();
228 Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > fullDomainMap = mergeMaps(subDomainMaps);
230 bool bDomainUseThyraStyleNumbering =
false;
232 for (
size_t v = 0; v < subDomainMaps.size(); ++v) {
233 numAllElements += subDomainMaps[v]->getGlobalNumElements();
235 if (fullDomainMap->getGlobalNumElements() != numAllElements) bDomainUseThyraStyleNumbering =
true;
244 for (
size_t r = 0; r <
Rows(); ++r) {
245 for (
size_t c = 0; c <
Cols(); ++c) {
246 if (thyraOp->blockExists(r, c)) {
248 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r, c);
249 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > op = Teuchos::rcp_const_cast<Thyra::LinearOpBase<Scalar> >(const_op);
250 Teuchos::RCP<Xpetra::Matrix<Scalar, LO, GO, Node> > xop =
252 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LO, GO, Node> > xwrap =
278 std::vector<GlobalOrdinal> gids;
279 for (
size_t tt = 0; tt < subMaps.size(); ++tt) {
280 Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > subMap = subMaps[tt];
282 Teuchos::ArrayView<const GlobalOrdinal> subMapGids = subMap->getLocalElementList();
283 gids.insert(gids.end(), subMapGids.begin(), subMapGids.end());
285 size_t myNumElements = subMap->getLocalNumElements();
286 for (LocalOrdinal l = 0; l < Teuchos::as<LocalOrdinal>(myNumElements); ++l) {
287 GlobalOrdinal gid = subMap->getGlobalElement(l);
297 const GO INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
298 std::sort(gids.begin(), gids.end());
299 gids.erase(std::unique(gids.begin(), gids.end()), gids.end());
300 Teuchos::ArrayView<GO> gidsView(&gids[0], gids.size());
342 void insertGlobalValues(GlobalOrdinal globalRow,
const ArrayView<const GlobalOrdinal>& cols,
const ArrayView<const Scalar>& vals) {
345 getMatrix(0, 0)->insertGlobalValues(globalRow, cols, vals);
362 void insertLocalValues(LocalOrdinal localRow,
const ArrayView<const LocalOrdinal>& cols,
const ArrayView<const Scalar>& vals) {
365 getMatrix(0, 0)->insertLocalValues(localRow, cols, vals);
372 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::removeEmptyProcessesInPlace");
374 getMatrix(0, 0)->removeEmptyProcessesInPlace(newMap);
390 const ArrayView<const GlobalOrdinal>& cols,
391 const ArrayView<const Scalar>& vals) {
394 getMatrix(0, 0)->replaceGlobalValues(globalRow, cols, vals);
406 const ArrayView<const LocalOrdinal>& cols,
407 const ArrayView<const Scalar>& 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++) {
468 void fillComplete(
const RCP<const Map>& domainMap,
const RCP<const Map>& rangeMap,
const RCP<ParameterList>& params = null) {
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) {
498 Teuchos::RCP<Matrix> Ablock =
getMatrix(r, c);
500 if (Ablock != Teuchos::null && !Ablock->isFillComplete())
507 RCP<const Map> rangeMap =
rangemaps_->getFullMap();
508 fullrowmap_ =
MapFactory::Build(rangeMap()->lib(), rangeMap()->getGlobalNumElements(), rangeMap()->getLocalElementList(), 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) {
518 Teuchos::RCP<CrsMatrix> Ablock =
getMatrix(r,c);
520 if (Ablock != Teuchos::null) {
521 Teuchos::ArrayView<const GO> colElements = Ablock->getColMap()->getLocalElementList();
522 Teuchos::RCP<const Map> colmap = Ablock->getColMap();
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));
541 const Teuchos::ArrayView<const GO> aView = Teuchos::ArrayView<const GO>(colmapentries);
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)->getLocalNumRows();
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)->getLocalNumEntries();
620 return nodeNumEntries;
626 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNumEntriesInLocalRow");
627 GlobalOrdinal gid = this->
getRowMap()->getGlobalElement(localRow);
630 size_t numEntriesInLocalRow = 0;
631 for (
size_t col = 0; col <
Cols(); ++col)
633 numEntriesInLocalRow +=
getMatrix(row, col)->getNumEntriesInLocalRow(lid);
634 return numEntriesInLocalRow;
640 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNumEntriesInGlobalRow");
642 size_t numEntriesInGlobalRow = 0;
643 for (
size_t col = 0; col <
Cols(); ++col)
645 numEntriesInGlobalRow +=
getMatrix(row, col)->getNumEntriesInGlobalRow(globalRow);
646 return numEntriesInGlobalRow;
653 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getGlobalMaxNumRowEntries");
656 for (
size_t row = 0; row <
Rows(); row++) {
658 for (
size_t col = 0; col <
Cols(); col++) {
660 globalMaxEntriesBlockRows +=
getMatrix(row, col)->getGlobalMaxNumRowEntries();
663 if (globalMaxEntriesBlockRows > globalMaxEntries)
664 globalMaxEntries = globalMaxEntriesBlockRows;
666 return globalMaxEntries;
673 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getLocalMaxNumRowEntries");
674 size_t localMaxEntries = 0;
676 for (
size_t row = 0; row <
Rows(); row++) {
677 size_t localMaxEntriesBlockRows = 0;
678 for (
size_t col = 0; col <
Cols(); col++) {
680 localMaxEntriesBlockRows +=
getMatrix(row, col)->getLocalMaxNumRowEntries();
683 if (localMaxEntriesBlockRows > localMaxEntries)
684 localMaxEntries = localMaxEntriesBlockRows;
686 return localMaxEntries;
695 for (
size_t i = 0; i <
blocks_.size(); ++i)
707 for (
size_t i = 0; i <
blocks_.size(); i++)
716 for (
size_t i = 0; i <
blocks_.size(); i++)
738 const ArrayView<LocalOrdinal>& Indices,
739 const ArrayView<Scalar>& Values,
740 size_t& NumEntries)
const {
743 getMatrix(0, 0)->getLocalRowCopy(LocalRow, Indices, Values, NumEntries);
759 void getGlobalRowView(GlobalOrdinal GlobalRow, ArrayView<const GlobalOrdinal>& indices, ArrayView<const Scalar>& values)
const {
762 getMatrix(0, 0)->getGlobalRowView(GlobalRow, indices, values);
778 void getLocalRowView(LocalOrdinal LocalRow, ArrayView<const LocalOrdinal>& indices, ArrayView<const Scalar>& values)
const {
781 getMatrix(0, 0)->getLocalRowView(LocalRow, indices, values);
784 GlobalOrdinal gid = this->
getRowMap()->getGlobalElement(LocalRow);
801 Teuchos::RCP<Vector> rcpdiag = Teuchos::rcpFromRef(diag);
802 Teuchos::RCP<BlockedVector> bdiag = Teuchos::rcp_dynamic_cast<
BlockedVector>(rcpdiag);
807 if (
Rows() == 1 &&
Cols() == 1 && bdiag.is_null() ==
true) {
808 Teuchos::RCP<const Matrix> rm =
getMatrix(0, 0);
809 rm->getLocalDiagCopy(diag);
813 TEUCHOS_TEST_FOR_EXCEPTION(bdiag.is_null() ==
true,
Xpetra::Exceptions::RuntimeError,
"BlockedCrsMatrix::getLocalDiagCopy: diag must be a Blocked(Multi)Vector.");
814 TEUCHOS_TEST_FOR_EXCEPTION(bdiag->getNumVectors() != 1,
Xpetra::Exceptions::RuntimeError,
"BlockedCrsMatrix::getLocalDiagCopy: diag must be a Blocked(Multi)Vector with exactly one vector. However, the number of stored vectors is " << bdiag->getNumVectors());
816 "BlockedCrsMatrix::getLocalDiagCopy(): the number of blocks in diag differ from the number of blocks in this operator.");
820 for (
size_t row = 0; row <
Rows(); row++) {
821 Teuchos::RCP<const Matrix> rm =
getMatrix(row, row);
823 Teuchos::RCP<Vector> rv =
VectorFactory::Build(bdiag->getBlockedMap()->getMap(row, bdiag->getBlockedMap()->getThyraMode()));
824 rm->getLocalDiagCopy(*rv);
825 bdiag->setMultiVector(row, rv, bdiag->getBlockedMap()->getThyraMode());
834 Teuchos::RCP<const Vector> rcpx = Teuchos::rcpFromRef(x);
835 Teuchos::RCP<const BlockedVector> bx = Teuchos::rcp_dynamic_cast<
const BlockedVector>(rcpx);
842 if (
Rows() == 1 && bx.is_null() ==
true) {
843 for (
size_t col = 0; col <
Cols(); ++col) {
844 Teuchos::RCP<Matrix> rm =
getMatrix(0, col);
851 TEUCHOS_TEST_FOR_EXCEPTION(bx->getNumVectors() != 1,
Xpetra::Exceptions::RuntimeError,
"BlockedCrsMatrix::leftScale: x must be a Blocked(Multi)Vector with exactly one vector. However, the number of stored vectors is " << bx->getNumVectors());
853 "BlockedCrsMatrix::leftScale(): the number of blocks in diag differ from the number of blocks in this operator.");
855 for (
size_t row = 0; row <
Rows(); row++) {
856 Teuchos::RCP<const MultiVector> rmv = bx->getMultiVector(row);
857 Teuchos::RCP<const Vector> rscale = rmv->getVector(0);
859 for (
size_t col = 0; col <
Cols(); ++col) {
860 Teuchos::RCP<Matrix> rm =
getMatrix(row, col);
862 rm->leftScale(*rscale);
872 Teuchos::RCP<const Vector> rcpx = Teuchos::rcpFromRef(x);
873 Teuchos::RCP<const BlockedVector> bx = Teuchos::rcp_dynamic_cast<
const BlockedVector>(rcpx);
880 if (
Cols() == 1 && bx.is_null() ==
true) {
881 for (
size_t row = 0; row <
Rows(); ++row) {
882 Teuchos::RCP<Matrix> rm =
getMatrix(row, 0);
889 TEUCHOS_TEST_FOR_EXCEPTION(bx->getNumVectors() != 1,
Xpetra::Exceptions::RuntimeError,
"BlockedCrsMatrix::rightScale: x must be a Blocked(Multi)Vector with exactly one vector. However, the number of stored vectors is " << bx->getNumVectors());
891 "BlockedCrsMatrix::rightScale(): the number of blocks in diag differ from the number of blocks in this operator.");
893 for (
size_t col = 0; col <
Cols(); ++col) {
894 Teuchos::RCP<const MultiVector> rmv = bx->getMultiVector(col);
895 Teuchos::RCP<const Vector> rscale = rmv->getVector(0);
897 for (
size_t row = 0; row <
Rows(); row++) {
898 Teuchos::RCP<Matrix> rm =
getMatrix(row, col);
900 rm->rightScale(*rscale);
909 typename ScalarTraits<Scalar>::magnitudeType ret = Teuchos::ScalarTraits<Scalar>::magnitude(Teuchos::ScalarTraits<Scalar>::zero());
910 for (
size_t col = 0; col <
Cols(); ++col) {
911 for (
size_t row = 0; row <
Rows(); ++row) {
912 if (
getMatrix(row, col) != Teuchos::null) {
913 typename ScalarTraits<Scalar>::magnitudeType n =
getMatrix(row, col)->getFrobeniusNorm();
918 return Teuchos::ScalarTraits<typename ScalarTraits<Scalar>::magnitudeType>::squareroot(ret);
957 const Teuchos::ArrayRCP<LocalOrdinal>& regionInterfaceLIDs)
const {}
964 Teuchos::ETransp mode = Teuchos::NO_TRANS,
965 Scalar alpha = ScalarTraits<Scalar>::one(),
966 Scalar beta = ScalarTraits<Scalar>::zero())
const {
971 "apply() only supports the following modes: NO_TRANS and TRANS.");
974 RCP<const MultiVector> refX = rcpFromRef(X);
975 RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<
const BlockedMultiVector>(refX);
980 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
988 SC one = ScalarTraits<SC>::one();
990 if (mode == Teuchos::NO_TRANS) {
991 for (
size_t row = 0; row <
Rows(); row++) {
993 for (
size_t col = 0; col <
Cols(); col++) {
995 RCP<Matrix> Ablock =
getMatrix(row, col);
997 if (Ablock.is_null())
1002 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(Ablock) == Teuchos::null ?
false :
true;
1005 RCP<const MultiVector> Xblock = Teuchos::null;
1016 Ablock->apply(*Xblock, *tmpYblock);
1018 Yblock->update(one, *tmpYblock, one);
1023 }
else if (mode == Teuchos::TRANS) {
1025 for (
size_t col = 0; col <
Cols(); col++) {
1028 for (
size_t row = 0; row <
Rows(); row++) {
1029 RCP<Matrix> Ablock =
getMatrix(row, col);
1031 if (Ablock.is_null())
1036 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(Ablock) == Teuchos::null ?
false :
true;
1038 RCP<const MultiVector> Xblock = Teuchos::null;
1046 Ablock->apply(*Xblock, *tmpYblock, Teuchos::TRANS);
1048 Yblock->update(one, *tmpYblock, one);
1053 Y.
update(alpha, *tmpY, beta);
1082 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getDomainMap(size_t,bool)");
1112 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getRangeMap(size_t,bool)");
1118 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getRangeMapExtractor()");
1124 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getDomainMapExtractor()");
1145 Teuchos::ETransp mode = Teuchos::NO_TRANS,
1146 Scalar alpha = ScalarTraits<Scalar>::one(),
1147 Scalar beta = ScalarTraits<Scalar>::zero()
1153 "apply() only supports the following modes: NO_TRANS and TRANS.");
1156 RCP<const MultiVector> refX = rcpFromRef(X);
1157 RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<
const BlockedMultiVector>(refX);
1161 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
1167 SC one = ScalarTraits<SC>::one();
1169 if (mode == Teuchos::NO_TRANS) {
1171 for (
size_t col = 0; col <
Cols(); col++) {
1173 RCP<Matrix> Ablock =
getMatrix(row, col);
1175 if (Ablock.is_null())
1180 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(Ablock) == Teuchos::null ?
false :
true;
1183 RCP<const MultiVector> Xblock = Teuchos::null;
1194 Ablock->apply(*Xblock, *tmpYblock);
1196 Yblock->update(one, *tmpYblock, one);
1202 Y.
update(alpha, *tmpY, beta);
1211 const Teuchos::RCP<const Map>
getMap()
const {
1223 getMatrix(0, 0)->doImport(source, importer, CM);
1233 getMatrix(0, 0)->doExport(dest, importer, CM);
1243 getMatrix(0, 0)->doImport(source, exporter, CM);
1253 getMatrix(0, 0)->doExport(dest, exporter, CM);
1265 std::string
description()
const {
return "Xpetra_BlockedCrsMatrix.description()"; }
1268 void describe(Teuchos::FancyOStream& out,
const Teuchos::EVerbosityLevel verbLevel = Teuchos::Describable::verbLevel_default)
const {
1269 out <<
"Xpetra::BlockedCrsMatrix: " <<
Rows() <<
" x " <<
Cols() << std::endl;
1272 out <<
"BlockMatrix is fillComplete" << std::endl;
1285 out <<
"BlockMatrix is NOT fillComplete" << std::endl;
1288 for (
size_t r = 0; r <
Rows(); ++r)
1289 for (
size_t c = 0; c <
Cols(); ++c) {
1291 out <<
"Block(" << r <<
"," << c <<
")" << std::endl;
1292 getMatrix(r, c)->describe(out, verbLevel);
1294 out <<
"Block(" << r <<
"," << c <<
") = null" << std::endl;
1302 for (
size_t r = 0; r <
Rows(); ++r)
1303 for (
size_t c = 0; c <
Cols(); ++c) {
1305 std::ostringstream oss;
1306 oss << objectLabel <<
"(" << r <<
"," << c <<
")";
1307 getMatrix(r, c)->setObjectLabel(oss.str());
1352 TEUCHOS_TEST_FOR_EXCEPTION(
Rows() != 1, std::out_of_range,
"Can only unwrap a 1x1 blocked matrix. The matrix has " <<
Rows() <<
" block rows, though.");
1353 TEUCHOS_TEST_FOR_EXCEPTION(
Cols() != 1, std::out_of_range,
"Can only unwrap a 1x1 blocked matrix. The matrix has " <<
Cols() <<
" block columns, though.");
1356 RCP<BlockedCrsMatrix> bmat = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(mat);
1357 if (bmat == Teuchos::null)
return mat;
1364 size_t row =
Rows() + 1, col =
Cols() + 1;
1365 for (
size_t r = 0; r <
Rows(); ++r)
1366 for (
size_t c = 0; c <
Cols(); ++c)
1372 TEUCHOS_TEST_FOR_EXCEPTION(row ==
Rows() + 1 || col ==
Cols() + 1,
Xpetra::Exceptions::Incompatible,
"Xpetra::BlockedCrsMatrix::getInnermostCrsMatrix: Could not find a non-zero sub-block in blocked operator.")
1374 RCP<BlockedCrsMatrix> bmat = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(mm);
1375 if (bmat == Teuchos::null)
return mm;
1382 TEUCHOS_TEST_FOR_EXCEPTION(r >
Rows(), std::out_of_range,
"Error, r = " <<
Rows() <<
" is too big");
1383 TEUCHOS_TEST_FOR_EXCEPTION(c >
Cols(), std::out_of_range,
"Error, c = " <<
Cols() <<
" is too big");
1394 void setMatrix(
size_t r,
size_t c, Teuchos::RCP<Matrix> mat) {
1398 TEUCHOS_TEST_FOR_EXCEPTION(r >
Rows(), std::out_of_range,
"Error, r = " <<
Rows() <<
" is too big");
1399 TEUCHOS_TEST_FOR_EXCEPTION(c >
Cols(), std::out_of_range,
"Error, c = " <<
Cols() <<
" is too big");
1411 using Teuchos::rcp_dynamic_cast;
1412 Scalar one = ScalarTraits<SC>::one();
1415 "BlockedCrsMatrix::Merge: only implemented for Xpetra-style or Thyra-style numbering. No mixup allowed!");
1418 "BlockedCrsMatrix::Merge: BlockMatrix must be fill-completed.");
1421 Teuchos::ArrayRCP<size_t> numEntPerRow(lclNumRows);
1422 for (LocalOrdinal lclRow = 0; lclRow < lclNumRows; ++lclRow)
1429 for (
size_t i = 0; i <
Rows(); i++) {
1430 for (
size_t j = 0; j <
Cols(); j++) {
1432 RCP<const Matrix> mat =
getMatrix(i, j);
1435 RCP<const BlockedCrsMatrix> bMat = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(mat);
1436 if (bMat != Teuchos::null) mat = bMat->
Merge();
1440 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!");
1443 if (mat->getLocalNumEntries() == 0)
continue;
1445 this->
Add(*mat, one, *sparse, one);
1451 for (
size_t i = 0; i <
Rows(); i++) {
1452 for (
size_t j = 0; j <
Cols(); j++) {
1454 RCP<const Matrix> mat =
getMatrix(i, j);
1456 RCP<const BlockedCrsMatrix> bMat = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(mat);
1457 if (bMat != Teuchos::null) mat = bMat->
Merge();
1461 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!");
1464 RCP<const CrsMatrixWrap> crsMat = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(mat);
1465 TEUCHOS_ASSERT(crsMat != Teuchos::null);
1468 RCP<const Map> trowMap = mat->getRowMap();
1469 RCP<const Map> tcolMap = mat->getColMap();
1470 RCP<const Map> tdomMap = mat->getDomainMap();
1485 if (mat->getLocalNumEntries() == 0)
continue;
1487 size_t maxNumEntries = mat->getLocalMaxNumRowEntries();
1490 Array<GO> inds(maxNumEntries);
1491 Array<GO> inds2(maxNumEntries);
1492 Array<SC> vals(maxNumEntries);
1495 for (
size_t k = 0; k < mat->getLocalNumRows(); k++) {
1496 GlobalOrdinal rowTGID = trowMap->getGlobalElement(k);
1497 crsMat->getCrsMatrix()->getGlobalRowCopy(rowTGID, inds(), vals(), numEntries);
1500 for (
size_t l = 0; l < numEntries; ++l) {
1501 LocalOrdinal lid = tcolMap->getLocalElement(inds[l]);
1502 inds2[l] = xcolMap->getGlobalElement(lid);
1505 GlobalOrdinal rowXGID = xrowMap->getGlobalElement(k);
1506 sparse->insertGlobalValues(
1507 rowXGID, inds2(0, numEntries),
1508 vals(0, numEntries));
1518 "BlockedCrsMatrix::Merge: Local number of entries of merged matrix does not coincide with local number of entries of blocked operator.");
1521 "BlockedCrsMatrix::Merge: Global number of entries of merged matrix does not coincide with global number of entries of blocked operator.");
1531 return getMatrix(0, 0)->getLocalMatrixDevice();
1538 return getMatrix(0, 0)->getLocalMatrixHost();
1543 #ifdef HAVE_XPETRA_THYRA
1544 Teuchos::RCP<Thyra::BlockedLinearOpBase<Scalar> > getThyraOperator() {
1545 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thOp =
1546 Xpetra::ThyraUtils<Scalar, LO, GO, Node>::toThyra(Teuchos::rcpFromRef(*
this));
1547 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(thOp));
1549 Teuchos::RCP<Thyra::BlockedLinearOpBase<Scalar> > thbOp =
1550 Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<Scalar> >(thOp);
1551 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(thbOp));
1562 using STS = Teuchos::ScalarTraits<Scalar>;
1563 R.
update(STS::one(), B, STS::zero());
1564 this->
apply(X, R, Teuchos::NO_TRANS, -STS::one(), STS::one());
1585 "Matrix A is not completed");
1586 using Teuchos::Array;
1587 using Teuchos::ArrayView;
1591 Scalar one = ScalarTraits<SC>::one();
1592 Scalar zero = ScalarTraits<SC>::zero();
1594 if (scalarA == zero)
1597 Teuchos::RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
1598 Teuchos::RCP<const CrsMatrixWrap> rcpAwrap = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(rcpA);
1600 "BlockedCrsMatrix::Add: matrix A must be of type CrsMatrixWrap.");
1601 Teuchos::RCP<const CrsMatrix> crsA = rcpAwrap->getCrsMatrix();
1603 size_t maxNumEntries = crsA->getLocalMaxNumRowEntries();
1606 Array<GO> inds(maxNumEntries);
1607 Array<SC> vals(maxNumEntries);
1609 RCP<const Map> rowMap = crsA->getRowMap();
1610 RCP<const Map> colMap = crsA->getColMap();
1612 ArrayView<const GO> rowGIDs = crsA->getRowMap()->getLocalElementList();
1613 for (
size_t i = 0; i < crsA->getLocalNumRows(); i++) {
1614 GO row = rowGIDs[i];
1615 crsA->getGlobalRowCopy(row, inds(), vals(), numEntries);
1618 for (
size_t j = 0; j < numEntries; ++j)
1646 #ifdef HAVE_XPETRA_THYRA
1647 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > thyraOp_;
1655 #define XPETRA_BLOCKEDCRSMATRIX_SHORT
virtual void getLocalRowCopy(LocalOrdinal LocalRow, const ArrayView< LocalOrdinal > &Indices, const ArrayView< Scalar > &Values, size_t &NumEntries) const
Extract a list of entries in a specified local row of the matrix. Put into storage allocated by calli...
size_t getLocalNumRows() const
Returns the number of matrix rows owned on the calling node.
CrsMatrix::local_matrix_type local_matrix_type
virtual void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode, Scalar alpha, Scalar beta, bool sumInterfaceValues, const RCP< Xpetra::Import< LocalOrdinal, GlobalOrdinal, Node > > ®ionInterfaceImporter, const Teuchos::ArrayRCP< LocalOrdinal > ®ionInterfaceLIDs) const
sparse matrix-multivector multiplication for the region layout matrices (currently no blocked impleme...
RCP< const Map > getDomainMap(size_t i, bool bThyraMode) const
Returns the Map associated with the i'th block domain of this operator.
static Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map, size_t NumVectors, bool zeroOut=true)
Constructor specifying the number of non-zeros for all rows.
const RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
bool isFillComplete() const
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
void replaceGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Replace matrix entries, using global IDs.
void fillComplete(const RCP< const Map > &domainMap, const RCP< const Map > &rangeMap, const RCP< ParameterList > ¶ms=null)
Signal that data entry is complete.
virtual void setAllToScalar(const Scalar &alpha)
Set all matrix entries equal to scalar.
LocalOrdinal GetStorageBlockSize() const
Returns the block size of the storage mechanism.
Teuchos::RCP< const MapExtractor > rangemaps_
full range map together with all partial domain maps
void doImport(const Matrix &source, const Import &importer, CombineMode CM)
Import.
void getLocalRowView(LocalOrdinal LocalRow, ArrayView< const LocalOrdinal > &indices, ArrayView< const Scalar > &values) const
Extract a const, non-persisting view of local indices in a specified row of the matrix.
static Teuchos::RCP< Xpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node >> &map, bool zeroOut=true)
Constructor specifying the number of non-zeros for all rows.
static RCP< Matrix > Build(const RCP< const Map > &rowMap)
virtual void bgs_apply(const MultiVector &X, MultiVector &Y, size_t row, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=ScalarTraits< Scalar >::one(), Scalar beta=ScalarTraits< Scalar >::zero()) const
Special multiplication routine (for BGS/Jacobi smoother)
Exception throws to report errors in the internal logical of the program.
RCP< const Map > getFullDomainMap() const
Returns the Map associated with the full domain of this operator.
virtual ~BlockedCrsMatrix()
Destructor.
Teuchos::RCP< Matrix > getCrsMatrix() const
return unwrap 1x1 blocked operators
void doExport(const Matrix &dest, const Import &importer, CombineMode CM)
Export.
LocalOrdinal local_ordinal_type
RCP< const Map > getRangeMap(size_t i, bool bThyraMode) const
Returns the Map associated with the i'th block range of this operator.
local_matrix_type::HostMirror getLocalMatrixHost() const
Access the underlying local Kokkos::CrsMatrix object.
size_t getGlobalMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on all nodes.
void Add(const Matrix &A, const Scalar scalarA, Matrix &B, const Scalar scalarB) const
Add a Xpetra::CrsMatrix to another: B = B*scalarB + A*scalarA.
void resumeFill(const RCP< ParameterList > ¶ms=null)
global_size_t getGlobalNumCols() const
Returns the number of global columns in the matrix.
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.
void rightScale(const Vector &x)
Right scale matrix using the given vector entries.
const Teuchos::RCP< const Map > getMap() const
Implements DistObject interface.
size_t getLocalMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on this node.
global_size_t getGlobalNumEntries() const
Returns the global number of entries in this matrix.
size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const
Returns the current number of entries on this node in the specified local row.
RCP< const CrsGraph > getCrsGraph() const
Returns the CrsGraph associated with this matrix.
local_matrix_type getLocalMatrixDevice() const
Access the underlying local Kokkos::CrsMatrix object.
Exception indicating invalid cast attempted.
virtual bool haveGlobalConstants() const
Returns true if globalConstants have been computed; false otherwise.
void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Insert matrix entries, using global IDs.
void getLocalDiagCopy(Vector &diag) const
Get a copy of the diagonal entries owned by this node, with local row indices.
viewLabel_t defaultViewLabel_
virtual void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)=0
Insert matrix entries, using global IDs.
GlobalOrdinal global_ordinal_type
RCP< const Map > getRangeMap(size_t i) const
Returns the Map associated with the i'th block range of this operator.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
bool is_diagonal_
If we're diagonal, a bunch of the extraction stuff should work.
void doExport(const Matrix &dest, const Export &exporter, CombineMode CM)
Export (using an Importer).
void leftScale(const Vector &x)
Left scale matrix using the given vector entries.
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.
void setObjectLabel(const std::string &objectLabel)
Teuchos::RCP< Matrix > getInnermostCrsMatrix()
helper routine recursively returns the first inner-most non-null matrix block from a (nested) blocked...
void insertLocalValues(LocalOrdinal localRow, const ArrayView< const LocalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Insert matrix entries, using local IDs.
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
virtual bool isFillComplete() const =0
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to an FancyOStream object.
virtual size_t Cols() const
number of column blocks
static Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > transformThyra2XpetraGIDs(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlInput, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlReferenceInput)
replace set of global ids by new global ids
void scale(const Scalar &alpha)
Scale the current values of a matrix, this = alpha*this.
void CreateView(viewLabel_t viewLabel, const RCP< const Map > &rowMap, const RCP< const Map > &colMap)
RCP< const Map > getFullRangeMap() const
Returns the Map associated with the full range of this operator.
void residual(const MultiVector &X, const MultiVector &B, MultiVector &R) const
Compute a residual R = B - (*this) * X.
viewLabel_t currentViewLabel_
RCP< const Map > getDomainMap(size_t i) const
Returns the Map associated with the i'th block domain of this operator.
RCP< const BlockedMap > getBlockedRangeMap() const
Returns the BlockedMap associated with the range of this operator.
void doImport(const Matrix &source, const Export &exporter, CombineMode CM)
Import (using an Exporter).
void getGlobalRowView(GlobalOrdinal GlobalRow, ArrayView< const GlobalOrdinal > &indices, ArrayView< const Scalar > &values) const
Extract a const, non-persisting view of global indices in a specified row of the matrix.
Exception throws when you call an unimplemented method of Xpetra.
bool hasCrsGraph() const
Supports the getCrsGraph() call.
size_t global_size_t
Global size_t object.
std::vector< Teuchos::RCP< Matrix > > blocks_
row major matrix block storage
Teuchos::RCP< Matrix > Merge() const
merge BlockedCrsMatrix blocks in a CrsMatrix
BlockedCrsMatrix(const Teuchos::RCP< const BlockedMap > &rangeMaps, const Teuchos::RCP< const BlockedMap > &domainMaps, size_t numEntriesPerRow)
Constructor.
RCP< const MapExtractor > getDomainMapExtractor() const
Returns map extractor for domain map.
global_size_t getGlobalNumRows() const
Returns the number of global rows.
const RCP< const Map > getDomainMap() const
Returns the Map associated with the domain of this operator.
#define XPETRA_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const
Returns the current number of entries in the specified (locally owned) global row.
virtual bool isDiagonal() const
size_t getLocalNumEntries() const
Returns the local number of entries in this matrix.
void setMatrix(size_t r, size_t c, Teuchos::RCP< Matrix > mat)
set matrix block
std::string description() const
Return a simple one-line description of this object.
bool bDomainThyraMode_
boolean flag, which is true, if BlockedCrsMatrix has been created using Thyra-style numbering for sub...
bool isGloballyIndexed() const
If matrix indices are in the global range, this function returns true. Otherwise, this function retur...
Exception throws to report incompatible objects (like maps).
Concrete implementation of Xpetra::Matrix.
BlockedCrsMatrix(Teuchos::RCP< const MapExtractor > &rangeMapExtractor, Teuchos::RCP< const MapExtractor > &domainMapExtractor, size_t numEntriesPerRow)
Constructor.
virtual size_t Rows() const
number of row blocks
CombineMode
Xpetra::Combine Mode enumerable type.
#define XPETRA_MONITOR(funcName)
virtual const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
virtual void scale(const Scalar &alpha)=0
Scale the current values of a matrix, this = alpha*this.
void fillComplete(const RCP< ParameterList > ¶ms=null)
Signal that data entry is complete.
const viewLabel_t & GetDefaultViewLabel() const
virtual size_t getNumVectors() const =0
Number of columns in the multivector.
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 ScalarTraits< Scalar >::magnitudeType getFrobeniusNorm() const
Get Frobenius norm of the matrix.
void removeEmptyProcessesInPlace(const Teuchos::RCP< const Map > &newMap)
bool isLocallyIndexed() const
If matrix indices of all matrix blocks are in the local range, this function returns true...
void replaceLocalValues(LocalOrdinal localRow, const ArrayView< const LocalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Replace matrix entries, using local IDs.
Xpetra-specific matrix class.
Teuchos::RCP< const MapExtractor > domainmaps_
full domain map together with all partial domain maps
virtual void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=ScalarTraits< Scalar >::one(), Scalar beta=ScalarTraits< Scalar >::zero()) const
Computes the sparse matrix-multivector multiplication.
bool bRangeThyraMode_
boolean flag, which is true, if BlockedCrsMatrix has been created using Thyra-style numbering for sub...
RCP< const BlockedMap > getBlockedDomainMap() const
Returns the BlockedMap associated with the domain of this operator.
RCP< const MapExtractor > getRangeMapExtractor() const
Returns map extractor class for range map.
RCP< const CrsGraph< int, GlobalOrdinal, Node > > toXpetra(const Epetra_CrsGraph &g)