46 #ifndef XPETRA_BLOCKEDCRSMATRIX_HPP
47 #define XPETRA_BLOCKEDCRSMATRIX_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"
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>
81 #include "Xpetra_VectorFactory.hpp"
92 template <
class Scalar,
97 public Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
105 #undef XPETRA_BLOCKEDCRSMATRIX_SHORT
120 const Teuchos::RCP<const BlockedMap>& domainMaps,
131 for (
size_t r = 0; r <
Rows(); ++r)
132 for (
size_t c = 0; c <
Cols(); ++c)
148 Teuchos::RCP<const MapExtractor>& domainMaps,
158 for (
size_t r = 0; r <
Rows(); ++r)
159 for (
size_t c = 0; c <
Cols(); ++c)
166 #ifdef HAVE_XPETRA_THYRA
173 BlockedCrsMatrix(
const Teuchos::RCP<
const Thyra::BlockedLinearOpBase<Scalar> >& thyraOp,
const Teuchos::RCP<
const Teuchos::Comm<int> >& )
177 const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<Scalar> > productRangeSpace = thyraOp->productRange();
178 const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<Scalar> > productDomainSpace = thyraOp->productDomain();
180 int numRangeBlocks = productRangeSpace->numBlocks();
181 int numDomainBlocks = productDomainSpace->numBlocks();
184 std::vector<Teuchos::RCP<const Map> > subRangeMaps(numRangeBlocks);
185 for (
size_t r=0; r<Teuchos::as<size_t>(numRangeBlocks); ++r) {
186 for (
size_t c=0; c<Teuchos::as<size_t>(numDomainBlocks); ++c) {
187 if (thyraOp->blockExists(r,c)) {
189 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r,c);
190 Teuchos::RCP<const Xpetra::CrsMatrix<Scalar,LO,GO,Node> > xop =
192 subRangeMaps[r] = xop->getRangeMap();
198 Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > fullRangeMap = mergeMaps(subRangeMaps);
202 bool bRangeUseThyraStyleNumbering =
false;
203 size_t numAllElements = 0;
204 for(
size_t v = 0; v < subRangeMaps.size(); ++v) {
205 numAllElements += subRangeMaps[v]->getGlobalNumElements();
207 if ( fullRangeMap->getGlobalNumElements() != numAllElements) bRangeUseThyraStyleNumbering =
true;
211 std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > > subDomainMaps(numDomainBlocks);
212 for (
size_t c=0; c<Teuchos::as<size_t>(numDomainBlocks); ++c) {
213 for (
size_t r=0; r<Teuchos::as<size_t>(numRangeBlocks); ++r) {
214 if (thyraOp->blockExists(r,c)) {
216 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r,c);
217 Teuchos::RCP<const Xpetra::CrsMatrix<Scalar,LO,GO,Node> > xop =
219 subDomainMaps[c] = xop->getDomainMap();
224 Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > fullDomainMap = mergeMaps(subDomainMaps);
226 bool bDomainUseThyraStyleNumbering =
false;
228 for(
size_t v = 0; v < subDomainMaps.size(); ++v) {
229 numAllElements += subDomainMaps[v]->getGlobalNumElements();
231 if (fullDomainMap->getGlobalNumElements() != numAllElements) bDomainUseThyraStyleNumbering =
true;
240 for (
size_t r = 0; r <
Rows(); ++r) {
241 for (
size_t c = 0; c <
Cols(); ++c) {
242 if(thyraOp->blockExists(r,c)) {
244 Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r,c);
245 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > op = Teuchos::rcp_const_cast<Thyra::LinearOpBase<Scalar> >(const_op);
246 Teuchos::RCP<Xpetra::CrsMatrix<Scalar,LO,GO,Node> > xop =
248 Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar,LO,GO,Node> > xwrap =
274 std::vector<GlobalOrdinal> gids;
275 for(
size_t tt = 0; tt<subMaps.size(); ++tt) {
276 Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > subMap = subMaps[tt];
278 Teuchos::ArrayView< const GlobalOrdinal > subMapGids = subMap->getNodeElementList();
279 gids.insert(gids.end(), subMapGids.begin(), subMapGids.end());
281 size_t myNumElements = subMap->getNodeNumElements();
282 for(LocalOrdinal l = 0; l < Teuchos::as<LocalOrdinal>(myNumElements); ++l) {
283 GlobalOrdinal gid = subMap->getGlobalElement(l);
293 const GO INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
294 std::sort(gids.begin(), gids.end());
295 gids.erase(std::unique(gids.begin(), gids.end()), gids.end());
296 Teuchos::ArrayView<GO> gidsView(&gids[0], gids.size());
339 void insertGlobalValues(GlobalOrdinal globalRow,
const ArrayView<const GlobalOrdinal>& cols,
const ArrayView<const Scalar>& vals) {
342 getMatrix(0,0)->insertGlobalValues(globalRow, cols, vals);
359 void insertLocalValues(LocalOrdinal localRow,
const ArrayView<const LocalOrdinal>& cols,
const ArrayView<const Scalar>& vals) {
362 getMatrix(0,0)->insertLocalValues(localRow, cols, vals);
369 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::removeEmptyProcessesInPlace");
371 getMatrix(0,0)->removeEmptyProcessesInPlace(newMap);
387 const ArrayView<const GlobalOrdinal> &cols,
388 const ArrayView<const Scalar> &vals) {
391 getMatrix(0,0)->replaceGlobalValues(globalRow,cols,vals);
403 const ArrayView<const LocalOrdinal> &cols,
404 const ArrayView<const Scalar> &vals) {
407 getMatrix(0,0)->replaceLocalValues(localRow,cols,vals);
416 for (
size_t row = 0; row <
Rows(); row++) {
417 for (
size_t col = 0; col <
Cols(); col++) {
419 getMatrix(row,col)->setAllToScalar(alpha);
428 for (
size_t row = 0; row <
Rows(); row++) {
429 for (
size_t col = 0; col <
Cols(); col++) {
451 for (
size_t row = 0; row <
Rows(); row++) {
452 for (
size_t col = 0; col <
Cols(); col++) {
465 void fillComplete(
const RCP<const Map>& domainMap,
const RCP<const Map>& rangeMap,
const RCP<ParameterList>& params = null) {
468 getMatrix(0,0)->fillComplete(domainMap, rangeMap, params);
492 for (
size_t r = 0; r <
Rows(); ++r)
493 for (
size_t c = 0; c <
Cols(); ++c) {
495 Teuchos::RCP<Matrix> Ablock =
getMatrix(r,c);
497 if (Ablock != Teuchos::null && !Ablock->isFillComplete())
504 RCP<const Map> rangeMap =
rangemaps_->getFullMap();
505 fullrowmap_ =
MapFactory::Build(rangeMap()->lib(), rangeMap()->getGlobalNumElements(), rangeMap()->getNodeElementList(), rangeMap()->getIndexBase(), rangeMap()->getComm());
508 fullcolmap_ = Teuchos::null;
510 std::vector<GO> colmapentries;
511 for (
size_t c = 0; c <
Cols(); ++c) {
514 for (
size_t r = 0; r <
Rows(); ++r) {
515 Teuchos::RCP<CrsMatrix> Ablock =
getMatrix(r,c);
517 if (Ablock != Teuchos::null) {
518 Teuchos::ArrayView<const GO> colElements = Ablock->getColMap()->getNodeElementList();
519 Teuchos::RCP<const Map> colmap = Ablock->getColMap();
520 copy(colElements.getRawPtr(), colElements.getRawPtr() + colElements.size(), inserter(colset, colset.begin()));
525 colmapentries.reserve(colmapentries.size() + colset.size());
526 copy(colset.begin(), colset.end(), back_inserter(colmapentries));
527 sort(colmapentries.begin(), colmapentries.end());
528 typename std::vector<GO>::iterator gendLocation;
529 gendLocation = std::unique(colmapentries.begin(), colmapentries.end());
530 colmapentries.erase(gendLocation,colmapentries.end());
534 size_t numGlobalElements = 0;
535 Teuchos::reduceAll(*(rangeMap->getComm()), Teuchos::REDUCE_SUM, colmapentries.size(), Teuchos::outArg(numGlobalElements));
538 const Teuchos::ArrayView<const GO> aView = Teuchos::ArrayView<const GO>(colmapentries);
539 fullcolmap_ =
MapFactory::Build(rangeMap->lib(), numGlobalElements, aView, 0, rangeMap->getComm());
552 for (
size_t row = 0; row <
Rows(); row++)
553 for (
size_t col = 0; col <
Cols(); col++)
555 globalNumRows +=
getMatrix(row,col)->getGlobalNumRows();
559 return globalNumRows;
569 for (
size_t col = 0; col <
Cols(); col++)
570 for (
size_t row = 0; row <
Rows(); row++)
572 globalNumCols +=
getMatrix(row,col)->getGlobalNumCols();
576 return globalNumCols;
584 for (
size_t row = 0; row <
Rows(); ++row)
585 for (
size_t col = 0; col <
Cols(); col++)
587 nodeNumRows +=
getMatrix(row,col)->getNodeNumRows();
599 for (
size_t row = 0; row <
Rows(); ++row)
600 for (
size_t col = 0; col <
Cols(); ++col)
602 globalNumEntries +=
getMatrix(row,col)->getGlobalNumEntries();
604 return globalNumEntries;
612 for (
size_t row = 0; row <
Rows(); ++row)
613 for (
size_t col = 0; col <
Cols(); ++col)
615 nodeNumEntries +=
getMatrix(row,col)->getNodeNumEntries();
617 return nodeNumEntries;
623 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNumEntriesInLocalRow");
624 GlobalOrdinal gid = this->
getRowMap()->getGlobalElement(localRow);
627 size_t numEntriesInLocalRow = 0;
628 for (
size_t col = 0; col <
Cols(); ++col)
630 numEntriesInLocalRow +=
getMatrix(row,col)->getNumEntriesInLocalRow(lid);
631 return numEntriesInLocalRow;
637 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNumEntriesInGlobalRow");
639 size_t numEntriesInGlobalRow = 0;
640 for (
size_t col = 0; col <
Cols(); ++col)
642 numEntriesInGlobalRow +=
getMatrix(row,col)->getNumEntriesInGlobalRow(globalRow);
643 return numEntriesInGlobalRow;
650 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getGlobalMaxNumRowEntries");
653 for (
size_t row = 0; row <
Rows(); row++) {
655 for (
size_t col = 0; col <
Cols(); col++) {
657 globalMaxEntriesBlockRows +=
getMatrix(row,col)->getGlobalMaxNumRowEntries();
660 if(globalMaxEntriesBlockRows > globalMaxEntries)
661 globalMaxEntries = globalMaxEntriesBlockRows;
663 return globalMaxEntries;
670 XPETRA_MONITOR(
"XpetraBlockedCrsMatrix::getNodeMaxNumRowEntries");
671 size_t localMaxEntries = 0;
673 for (
size_t row = 0; row <
Rows(); row++) {
674 size_t localMaxEntriesBlockRows = 0;
675 for (
size_t col = 0; col <
Cols(); col++) {
677 localMaxEntriesBlockRows +=
getMatrix(row,col)->getNodeMaxNumRowEntries();
680 if(localMaxEntriesBlockRows > localMaxEntries)
681 localMaxEntries = localMaxEntriesBlockRows;
683 return localMaxEntries;
692 for (
size_t i = 0; i <
blocks_.size(); ++i)
704 for (
size_t i = 0; i <
blocks_.size(); i++)
713 for (
size_t i = 0; i <
blocks_.size(); i++)
735 const ArrayView<LocalOrdinal>& Indices,
736 const ArrayView<Scalar>& Values,
737 size_t &NumEntries)
const {
740 getMatrix(0,0)->getLocalRowCopy(LocalRow, Indices, Values, NumEntries);
756 void getGlobalRowView(GlobalOrdinal GlobalRow, ArrayView<const GlobalOrdinal>& indices, ArrayView<const Scalar>& values)
const {
759 getMatrix(0,0)->getGlobalRowView(GlobalRow, indices, values);
775 void getLocalRowView(LocalOrdinal LocalRow, ArrayView<const LocalOrdinal>& indices, ArrayView<const Scalar>& values)
const {
778 getMatrix(0,0)->getLocalRowView(LocalRow, indices, values);
782 GlobalOrdinal gid = this->
getRowMap()->getGlobalElement(LocalRow);
799 Teuchos::RCP<Vector> rcpdiag = Teuchos::rcpFromRef(diag);
800 Teuchos::RCP<BlockedVector> bdiag = Teuchos::rcp_dynamic_cast<
BlockedVector>(rcpdiag);
805 if(
Rows() == 1 &&
Cols() == 1 && bdiag.is_null() ==
true) {
806 Teuchos::RCP<const Matrix> rm =
getMatrix(0,0);
807 rm->getLocalDiagCopy(diag);
811 TEUCHOS_TEST_FOR_EXCEPTION(bdiag.is_null() ==
true,
Xpetra::Exceptions::RuntimeError,
"BlockedCrsMatrix::getLocalDiagCopy: diag must be a Blocked(Multi)Vector.");
812 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());
814 "BlockedCrsMatrix::getLocalDiagCopy(): the number of blocks in diag differ from the number of blocks in this operator." );
818 for (
size_t row = 0; row <
Rows(); row++) {
819 Teuchos::RCP<const Matrix> rm =
getMatrix(row,row);
821 Teuchos::RCP<Vector> rv =
VectorFactory::Build(bdiag->getBlockedMap()->getMap(row,bdiag->getBlockedMap()->getThyraMode()));
822 rm->getLocalDiagCopy(*rv);
823 bdiag->setMultiVector(row,rv,bdiag->getBlockedMap()->getThyraMode());
832 Teuchos::RCP<const Vector> rcpx = Teuchos::rcpFromRef(x);
833 Teuchos::RCP<const BlockedVector> bx = Teuchos::rcp_dynamic_cast<
const BlockedVector>(rcpx);
840 if(
Rows() == 1 && bx.is_null() ==
true) {
841 for (
size_t col = 0; col <
Cols(); ++col) {
842 Teuchos::RCP<Matrix> rm =
getMatrix(0,col);
849 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());
851 "BlockedCrsMatrix::leftScale(): the number of blocks in diag differ from the number of blocks in this operator." );
853 for (
size_t row = 0; row <
Rows(); row++) {
854 Teuchos::RCP<const MultiVector> rmv = bx->getMultiVector(row);
855 Teuchos::RCP<const Vector> rscale = rmv->getVector(0);
857 for (
size_t col = 0; col <
Cols(); ++col) {
858 Teuchos::RCP<Matrix> rm =
getMatrix(row,col);
860 rm->leftScale(*rscale);
870 Teuchos::RCP<const Vector> rcpx = Teuchos::rcpFromRef(x);
871 Teuchos::RCP<const BlockedVector> bx = Teuchos::rcp_dynamic_cast<
const BlockedVector>(rcpx);
878 if(
Cols() == 1 && bx.is_null() ==
true) {
879 for (
size_t row = 0; row <
Rows(); ++row) {
880 Teuchos::RCP<Matrix> rm =
getMatrix(row,0);
887 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());
889 "BlockedCrsMatrix::rightScale(): the number of blocks in diag differ from the number of blocks in this operator." );
891 for (
size_t col = 0; col <
Cols(); ++col) {
892 Teuchos::RCP<const MultiVector> rmv = bx->getMultiVector(col);
893 Teuchos::RCP<const Vector> rscale = rmv->getVector(0);
895 for (
size_t row = 0; row <
Rows(); row++) {
896 Teuchos::RCP<Matrix> rm =
getMatrix(row,col);
898 rm->rightScale(*rscale);
908 typename ScalarTraits<Scalar>::magnitudeType ret = Teuchos::ScalarTraits<Scalar>::magnitude(Teuchos::ScalarTraits<Scalar>::zero());
909 for (
size_t col = 0; col <
Cols(); ++col) {
910 for (
size_t row = 0; row <
Rows(); ++row) {
912 typename ScalarTraits<Scalar>::magnitudeType n =
getMatrix(row,col)->getFrobeniusNorm();
917 return Teuchos::ScalarTraits< typename ScalarTraits<Scalar>::magnitudeType >::squareroot(ret);
960 Teuchos::ETransp mode = Teuchos::NO_TRANS,
961 Scalar alpha = ScalarTraits<Scalar>::one(),
962 Scalar beta = ScalarTraits<Scalar>::zero())
const
968 "apply() only supports the following modes: NO_TRANS and TRANS." );
971 RCP<const MultiVector> refX = rcpFromRef(X);
972 RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<
const BlockedMultiVector>(refX);
977 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
985 SC one = ScalarTraits<SC>::one();
987 if (mode == Teuchos::NO_TRANS) {
989 for (
size_t row = 0; row <
Rows(); row++) {
991 for (
size_t col = 0; col <
Cols(); col++) {
994 RCP<Matrix> Ablock =
getMatrix(row, col);
996 if (Ablock.is_null())
1001 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(Ablock) == Teuchos::null ?
false :
true;
1004 RCP<const MultiVector> Xblock = Teuchos::null;
1013 Ablock->apply(*Xblock, *tmpYblock);
1015 Yblock->update(one, *tmpYblock, one);
1020 }
else if (mode == Teuchos::TRANS) {
1022 for (
size_t col = 0; col <
Cols(); col++) {
1025 for (
size_t row = 0; row<
Rows(); row++) {
1026 RCP<Matrix> Ablock =
getMatrix(row, col);
1028 if (Ablock.is_null())
1033 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(Ablock) == Teuchos::null ?
false :
true;
1035 RCP<const MultiVector> Xblock = Teuchos::null;
1041 Ablock->apply(*Xblock, *tmpYblock, Teuchos::TRANS);
1043 Yblock->update(one, *tmpYblock, one);
1048 Y.
update(alpha, *tmpY, beta);
1104 Teuchos::ETransp mode = Teuchos::NO_TRANS,
1105 Scalar alpha = ScalarTraits<Scalar>::one(),
1106 Scalar beta = ScalarTraits<Scalar>::zero()
1113 "apply() only supports the following modes: NO_TRANS and TRANS." );
1116 RCP<const MultiVector> refX = rcpFromRef(X);
1117 RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<
const BlockedMultiVector>(refX);
1121 bool bBlockedX = (refbX != Teuchos::null) ?
true :
false;
1127 SC one = ScalarTraits<SC>::one();
1129 if (mode == Teuchos::NO_TRANS) {
1131 for (
size_t col = 0; col <
Cols(); col++) {
1134 RCP<Matrix> Ablock =
getMatrix(row, col);
1136 if (Ablock.is_null())
1141 bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(Ablock) == Teuchos::null ?
false :
true;
1144 RCP<const MultiVector> Xblock = Teuchos::null;
1153 Ablock->apply(*Xblock, *tmpYblock);
1155 Yblock->update(one, *tmpYblock, one);
1161 Y.
update(alpha, *tmpY, beta);
1172 const Teuchos::RCP< const Map >
getMap()
const {
1184 getMatrix(0,0)->doImport(source, importer, CM);
1194 getMatrix(0,0)->doExport(dest, importer, CM);
1204 getMatrix(0,0)->doImport(source, exporter, CM);
1214 getMatrix(0,0)->doExport(dest, exporter, CM);
1226 std::string
description()
const {
return "Xpetra_BlockedCrsMatrix.description()"; }
1229 void describe(Teuchos::FancyOStream& out,
const Teuchos::EVerbosityLevel verbLevel = Teuchos::Describable::verbLevel_default)
const {
1230 out <<
"Xpetra::BlockedCrsMatrix: " <<
Rows() <<
" x " <<
Cols() << std::endl;
1233 out <<
"BlockMatrix is fillComplete" << std::endl;
1246 out <<
"BlockMatrix is NOT fillComplete" << std::endl;
1249 for (
size_t r = 0; r <
Rows(); ++r)
1250 for (
size_t c = 0; c <
Cols(); ++c) {
1252 out <<
"Block(" << r <<
"," << c <<
")" << std::endl;
1253 getMatrix(r,c)->describe(out,verbLevel);
1254 }
else out <<
"Block(" << r <<
"," << c <<
") = null" << std::endl;
1262 for (
size_t r = 0; r <
Rows(); ++r)
1263 for (
size_t c = 0; c <
Cols(); ++c) {
1265 std::ostringstream oss; oss<< objectLabel <<
"(" << r <<
"," << c <<
")";
1266 getMatrix(r,c)->setObjectLabel(oss.str());
1275 if (
Rows() == 1 &&
Cols () == 1)
return true;
1304 TEUCHOS_TEST_FOR_EXCEPTION(
Rows()!=1, std::out_of_range,
"Can only unwrap a 1x1 blocked matrix. The matrix has " <<
Rows() <<
" block rows, though.");
1305 TEUCHOS_TEST_FOR_EXCEPTION(
Cols()!=1, std::out_of_range,
"Can only unwrap a 1x1 blocked matrix. The matrix has " <<
Cols() <<
" block columns, though.");
1308 RCP<BlockedCrsMatrix> bmat = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(mat);
1309 if (bmat == Teuchos::null)
return mat;
1316 size_t row =
Rows()+1, col =
Cols()+1;
1317 for (
size_t r = 0; r <
Rows(); ++r)
1318 for(
size_t c = 0; c <
Cols(); ++c)
1324 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.")
1326 RCP<BlockedCrsMatrix> bmat = Teuchos::rcp_dynamic_cast<
BlockedCrsMatrix>(mm);
1327 if (bmat == Teuchos::null)
return mm;
1334 TEUCHOS_TEST_FOR_EXCEPTION(r >
Rows(), std::out_of_range,
"Error, r = " <<
Rows() <<
" is too big");
1335 TEUCHOS_TEST_FOR_EXCEPTION(c >
Cols(), std::out_of_range,
"Error, c = " <<
Cols() <<
" is too big");
1346 void setMatrix(
size_t r,
size_t c, Teuchos::RCP<Matrix> mat) {
1350 TEUCHOS_TEST_FOR_EXCEPTION(r >
Rows(), std::out_of_range,
"Error, r = " <<
Rows() <<
" is too big");
1351 TEUCHOS_TEST_FOR_EXCEPTION(c >
Cols(), std::out_of_range,
"Error, c = " <<
Cols() <<
" is too big");
1363 using Teuchos::rcp_dynamic_cast;
1364 Scalar one = ScalarTraits<SC>::one();
1367 "BlockedCrsMatrix::Merge: only implemented for Xpetra-style or Thyra-style numbering. No mixup allowed!" );
1370 "BlockedCrsMatrix::Merge: BlockMatrix must be fill-completed." );
1373 Teuchos::ArrayRCP<size_t> numEntPerRow (lclNumRows);
1374 for (LocalOrdinal lclRow = 0; lclRow < lclNumRows; ++lclRow)
1381 for (
size_t i = 0; i <
Rows(); i++) {
1382 for (
size_t j = 0; j <
Cols(); j++) {
1387 RCP<const BlockedCrsMatrix> bMat = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(mat);
1388 if (bMat != Teuchos::null) mat = bMat->
Merge();
1392 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!" );
1395 if(mat->getNodeNumEntries() == 0)
continue;
1397 this->
Add(*mat, one, *sparse, one);
1403 for (
size_t i = 0; i <
Rows(); i++) {
1404 for (
size_t j = 0; j <
Cols(); j++) {
1408 RCP<const BlockedCrsMatrix> bMat = Teuchos::rcp_dynamic_cast<
const BlockedCrsMatrix>(mat);
1409 if (bMat != Teuchos::null) mat = bMat->
Merge();
1413 "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!" );
1416 RCP<const CrsMatrixWrap> crsMat = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(mat);
1417 TEUCHOS_ASSERT(crsMat != Teuchos::null);
1420 RCP<const Map> trowMap = mat->getRowMap();
1421 RCP<const Map> tcolMap = mat->getColMap();
1422 RCP<const Map> tdomMap = mat->getDomainMap();
1437 if(mat->getNodeNumEntries() == 0)
continue;
1439 size_t maxNumEntries = mat->getNodeMaxNumRowEntries();
1442 Array<GO> inds (maxNumEntries);
1443 Array<GO> inds2(maxNumEntries);
1444 Array<SC> vals (maxNumEntries);
1447 for (
size_t k = 0; k < mat->getNodeNumRows(); k++) {
1448 GlobalOrdinal rowTGID = trowMap->getGlobalElement(k);
1449 crsMat->getCrsMatrix()->getGlobalRowCopy(rowTGID, inds(), vals(), numEntries);
1452 for (
size_t l = 0; l < numEntries; ++l) {
1453 LocalOrdinal lid = tcolMap->getLocalElement(inds[l]);
1454 inds2[l] = xcolMap->getGlobalElement(lid);
1457 GlobalOrdinal rowXGID = xrowMap->getGlobalElement(k);
1458 sparse->insertGlobalValues(
1459 rowXGID, inds2(0, numEntries),
1460 vals(0, numEntries));
1470 "BlockedCrsMatrix::Merge: Local number of entries of merged matrix does not coincide with local number of entries of blocked operator." );
1473 "BlockedCrsMatrix::Merge: Global number of entries of merged matrix does not coincide with global number of entries of blocked operator." );
1479 #ifdef HAVE_XPETRA_KOKKOS_REFACTOR
1480 typedef typename CrsMatrix::local_matrix_type local_matrix_type;
1483 local_matrix_type getLocalMatrix ()
const {
1485 return getMatrix(0,0)->getLocalMatrix();
1491 #ifdef HAVE_XPETRA_THYRA
1492 Teuchos::RCP<Thyra::BlockedLinearOpBase<Scalar> > getThyraOperator() {
1493 Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thOp =
1494 Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(Teuchos::rcpFromRef(*
this));
1495 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(thOp));
1497 Teuchos::RCP<Thyra::BlockedLinearOpBase<Scalar> > thbOp =
1498 Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<Scalar> >(thOp);
1499 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(thbOp));
1508 using STS = Teuchos::ScalarTraits<Scalar>;
1509 R.
update(STS::one(),B,STS::zero());
1510 this->
apply (X, R, Teuchos::NO_TRANS, -STS::one(), STS::one());
1532 "Matrix A is not completed");
1533 using Teuchos::Array;
1534 using Teuchos::ArrayView;
1538 Scalar one = ScalarTraits<SC>::one();
1539 Scalar zero = ScalarTraits<SC>::zero();
1541 if (scalarA == zero)
1544 Teuchos::RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
1545 Teuchos::RCP<const CrsMatrixWrap> rcpAwrap = Teuchos::rcp_dynamic_cast<
const CrsMatrixWrap>(rcpA);
1547 "BlockedCrsMatrix::Add: matrix A must be of type CrsMatrixWrap.");
1548 Teuchos::RCP<const CrsMatrix> crsA = rcpAwrap->getCrsMatrix();
1550 size_t maxNumEntries = crsA->getNodeMaxNumRowEntries();
1553 Array<GO> inds(maxNumEntries);
1554 Array<SC> vals(maxNumEntries);
1556 RCP<const Map> rowMap = crsA->getRowMap();
1557 RCP<const Map> colMap = crsA->getColMap();
1559 ArrayView<const GO> rowGIDs = crsA->getRowMap()->getNodeElementList();
1560 for (
size_t i = 0; i < crsA->getNodeNumRows(); i++) {
1561 GO row = rowGIDs[i];
1562 crsA->getGlobalRowCopy(row, inds(), vals(), numEntries);
1565 for (
size_t j = 0; j < numEntries; ++j)
1593 #ifdef HAVE_XPETRA_THYRA
1594 Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > thyraOp_;
1603 #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...
RCP< const Map > getDomainMap(size_t i, bool bThyraMode) const
Returns the Map associated with the i'th block domain of this operator.
BlockedCrsMatrix(Teuchos::RCP< const MapExtractor > &rangeMaps, Teuchos::RCP< const MapExtractor > &domainMaps, size_t npr)
Constructor.
RCP< const Map > getFullDomainMap() const
Returns the Map associated with the full domain of this operator.
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 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.
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.
RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
RCP< const Map > getRangeMap(size_t i, bool bThyraMode) const
Returns the Map associated with the i'th block range of this operator.
Teuchos::RCP< const MapExtractor > rangemaps_
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 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.
size_t getNodeNumEntries() const
Returns the local number of entries in this matrix.
virtual ~BlockedCrsMatrix()
Destructor.
RCP< const Map > getRangeMap(size_t i) const
Returns the Map associated with the i'th block range of this operator.
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
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.
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.
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
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)
RCP< const BlockedMap > getBlockedDomainMap() const
Returns the BlockedMap associated with the domain of this operator.
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
RCP< const Map > getFullRangeMap() const
Returns the Map associated with the full range of this operator.
const Teuchos::RCP< const Map > getMap() const
Implements DistObject interface.
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)
void residual(const MultiVector &X, const MultiVector &B, MultiVector &R) const
Compute a residual R = B - (*this) * X.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
viewLabel_t currentViewLabel_
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.
size_t getNodeMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on this node.
std::vector< Teuchos::RCP< Matrix > > blocks_
Teuchos::RCP< Matrix > Merge() const
merge BlockedCrsMatrix blocks in a CrsMatrix
RCP< const MapExtractor > getDomainMapExtractor() const
Returns map extractor for domain map.
global_size_t getGlobalNumRows() const
Returns the number of global rows.
RCP< const CrsGraph< int, GlobalOrdinal, Node > > toXpetra(const Epetra_CrsGraph &g)
#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
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).
RCP< const Map > getDomainMap() const
Returns the Map associated with the domain of this operator.
Concrete implementation of Xpetra::Matrix.
virtual size_t Rows() const
number of row blocks
BlockedCrsMatrix(const Teuchos::RCP< const BlockedMap > &rangeMaps, const Teuchos::RCP< const BlockedMap > &domainMaps, size_t npr)
Constructor.
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
RCP< const BlockedMap > getBlockedRangeMap() const
Returns the BlockedMap associated with the range of this operator.
RCP< const Map > getDomainMap(size_t i) const
Returns the Map associated with the i'th block domain of this operator.
virtual size_t getNumVectors() const =0
Number of columns in the multivector.
size_t getNodeNumRows() const
Returns the number of matrix rows owned on the calling node.
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_
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 MapExtractor > getRangeMapExtractor() const
Returns map extractor class for range map.