10 #ifndef PACKAGES_XPETRA_SUP_MATRIX_UTILS_DEF_HPP_
11 #define PACKAGES_XPETRA_SUP_MATRIX_UTILS_DEF_HPP_
15 #include "Xpetra_Map.hpp"
17 #include "Xpetra_StridedMap.hpp"
18 #include "Xpetra_MapFactory.hpp"
19 #include "Xpetra_MapExtractor.hpp"
21 #include "Xpetra_Matrix.hpp"
22 #include "Xpetra_MatrixFactory.hpp"
23 #include "Xpetra_BlockedCrsMatrix.hpp"
24 #include "Xpetra_MatrixMatrix.hpp"
26 #ifdef HAVE_XPETRA_TPETRA
27 #include "Xpetra_TpetraMultiVector.hpp"
28 #include <Tpetra_RowMatrixTransposer.hpp>
29 #include <Tpetra_Details_extractBlockDiagonal.hpp>
30 #include <Tpetra_Details_scaleBlockDiagonal.hpp>
37 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
43 Teuchos::ArrayRCP<const Scalar> data = input.
getData(c);
45 ret->replaceLocalValue(Teuchos::as<LocalOrdinal>(r), c, data[r]);
52 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
56 RCP<const Teuchos::Comm<int>> comm = input.
getRowMap()->getComm();
59 Teuchos::Array<GlobalOrdinal> ovlUnknownStatusGids;
60 Teuchos::Array<GlobalOrdinal> ovlFoundStatusGids;
63 for (
size_t i = 0; i < input.
getColMap()->getLocalNumElements(); i++) {
64 GlobalOrdinal gcid = input.
getColMap()->getGlobalElement(i);
66 ovlUnknownStatusGids.push_back(gcid);
72 std::vector<int> myUnknownDofGIDs(comm->getSize(), 0);
73 std::vector<int> numUnknownDofGIDs(comm->getSize(), 0);
74 myUnknownDofGIDs[comm->getRank()] = ovlUnknownStatusGids.size();
75 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, comm->getSize(), &myUnknownDofGIDs[0], &numUnknownDofGIDs[0]);
78 size_t cntUnknownDofGIDs = 0;
79 for (
int p = 0; p < comm->getSize(); p++) cntUnknownDofGIDs += numUnknownDofGIDs[p];
80 std::vector<GlobalOrdinal> lUnknownDofGIDs(cntUnknownDofGIDs, -1);
81 std::vector<GlobalOrdinal> gUnknownDofGIDs(cntUnknownDofGIDs, -1);
83 size_t cntUnknownOffset = 0;
84 for (
int p = 0; p < comm->getRank(); p++) cntUnknownOffset += numUnknownDofGIDs[p];
85 for (
size_t k = 0; k < Teuchos::as<size_t>(ovlUnknownStatusGids.size()); k++) {
86 lUnknownDofGIDs[k + cntUnknownOffset] = ovlUnknownStatusGids[k];
88 if (cntUnknownDofGIDs > 0)
89 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(cntUnknownDofGIDs), &lUnknownDofGIDs[0], &gUnknownDofGIDs[0]);
90 std::sort(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end());
91 gUnknownDofGIDs.erase(std::unique(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end()), gUnknownDofGIDs.end());
94 for (
size_t k = 0; k < gUnknownDofGIDs.size(); k++) {
95 GlobalOrdinal curgid = gUnknownDofGIDs[k];
97 ovlFoundStatusGids.push_back(curgid);
101 std::vector<int> myFoundDofGIDs(comm->getSize(), 0);
102 std::vector<int> numFoundDofGIDs(comm->getSize(), 0);
103 myFoundDofGIDs[comm->getRank()] = ovlFoundStatusGids.size();
104 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, comm->getSize(), &myFoundDofGIDs[0], &numFoundDofGIDs[0]);
107 size_t cntFoundDofGIDs = 0;
108 for (
int p = 0; p < comm->getSize(); p++) cntFoundDofGIDs += numFoundDofGIDs[p];
109 std::vector<GlobalOrdinal> lFoundDofGIDs(cntFoundDofGIDs, -1);
110 std::vector<GlobalOrdinal> gFoundDofGIDs(cntFoundDofGIDs, -1);
112 size_t cntFoundOffset = 0;
113 for (
int p = 0; p < comm->getRank(); p++) cntFoundOffset += numFoundDofGIDs[p];
114 for (
size_t k = 0; k < Teuchos::as<size_t>(ovlFoundStatusGids.size()); k++) {
115 lFoundDofGIDs[k + cntFoundOffset] = ovlFoundStatusGids[k];
117 if (cntFoundDofGIDs > 0)
118 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, Teuchos::as<int>(cntFoundDofGIDs), &lFoundDofGIDs[0], &gFoundDofGIDs[0]);
120 Teuchos::Array<GlobalOrdinal> ovlDomainMapArray;
121 for (
size_t i = 0; i < input.
getColMap()->getLocalNumElements(); i++) {
122 GlobalOrdinal gcid = input.
getColMap()->getGlobalElement(i);
124 std::find(gFoundDofGIDs.begin(), gFoundDofGIDs.end(), gcid) != gFoundDofGIDs.end()) {
125 ovlDomainMapArray.push_back(gcid);
128 RCP<Map> ovlDomainMap =
MapFactory::Build(domainMap.
lib(), Teuchos::OrdinalTraits<GlobalOrdinal>::invalid(), ovlDomainMapArray(), 0, comm);
132 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
139 size_t numRows = rangeMapExtractor->NumMaps();
140 size_t numCols = domainMapExtractor->NumMaps();
142 TEUCHOS_TEST_FOR_EXCEPTION(rangeMapExtractor->getThyraMode() ==
true,
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: RangeMapExtractor must not use Thyra style numbering of GIDs. The MapExtractor must contain all GIDs of the full range map in order to define a proper splitting.")
143 TEUCHOS_TEST_FOR_EXCEPTION(domainMapExtractor->getThyraMode() ==
true,
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: DomainMapExtractor must not use Thyra style numbering of GIDs. The MapExtractor must contain all GIDs of the full domain map in order to define a proper splitting.")
145 RCP<const Map> fullRangeMap = rangeMapExtractor->getFullMap();
146 RCP<const Map> fullDomainMap = domainMapExtractor->getFullMap();
148 TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getMaxAllGlobalIndex() != input.
getRowMap()->getMaxAllGlobalIndex(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
149 TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getGlobalNumElements() != input.
getRowMap()->getGlobalNumElements(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
150 TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getLocalNumElements() != input.
getRowMap()->getLocalNumElements(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
151 TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getMaxAllGlobalIndex() != input.
getRangeMap()->getMaxAllGlobalIndex(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
152 TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getGlobalNumElements() != input.
getRangeMap()->getGlobalNumElements(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
153 TEUCHOS_TEST_FOR_EXCEPTION(fullRangeMap->getLocalNumElements() != input.
getRangeMap()->getLocalNumElements(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: RangeMapExtractor incompatible to row map of input matrix.")
155 TEUCHOS_TEST_FOR_EXCEPTION(fullDomainMap->getMaxAllGlobalIndex() != input.
getColMap()->getMaxAllGlobalIndex(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: DomainMapExtractor incompatible to domain map of input matrix. fullDomainMap->getMaxAllGlobalIndex() = " << fullDomainMap->getMaxAllGlobalIndex() <<
" vs. input.getColMap()->getMaxAllGlobalIndex() = " << input.
getColMap()->getMaxAllGlobalIndex())
156 TEUCHOS_TEST_FOR_EXCEPTION(fullDomainMap->getMaxAllGlobalIndex() != input.
getDomainMap()->getMaxAllGlobalIndex(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: DomainMapExtractor incompatible to domain map of input matrix.")
157 TEUCHOS_TEST_FOR_EXCEPTION(fullDomainMap->getGlobalNumElements() != input.
getDomainMap()->getGlobalNumElements(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: DomainMapExtractor incompatible to domain map of input matrix.")
158 TEUCHOS_TEST_FOR_EXCEPTION(fullDomainMap->getLocalNumElements() != input.
getDomainMap()->getLocalNumElements(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: DomainMapExtractor incompatible to domain map of input matrix.")
161 Teuchos::RCP<const MapExtractor> myColumnMapExtractor = Teuchos::null;
162 if (columnMapExtractor == Teuchos::null) {
163 TEUCHOS_TEST_FOR_EXCEPTION(domainMapExtractor->getThyraMode() ==
true,
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: Auto generation of column map extractor not supported for Thyra style numbering.");
165 std::vector<Teuchos::RCP<const Map>> ovlxmaps(numCols, Teuchos::null);
166 for (
size_t c = 0; c < numCols; c++) {
169 ovlxmaps[c] = colMap;
175 myColumnMapExtractor = columnMapExtractor;
179 Teuchos::RCP<const MapExtractor> thyRangeMapExtractor = Teuchos::null;
180 Teuchos::RCP<const MapExtractor> thyDomainMapExtractor = Teuchos::null;
181 Teuchos::RCP<const MapExtractor> thyColMapExtractor = Teuchos::null;
182 if (bThyraMode ==
true) {
184 std::vector<Teuchos::RCP<const Map>> thyRgMapExtractorMaps(numRows, Teuchos::null);
185 for (
size_t r = 0; r < numRows; r++) {
186 RCP<const Map> rMap = rangeMapExtractor->getMap(r);
188 RCP<const StridedMap> strRangeMap = Teuchos::rcp_dynamic_cast<
const StridedMap>(rMap);
189 if (strRangeMap != Teuchos::null) {
191 GlobalOrdinal offset = strRangeMap->getOffset();
192 LocalOrdinal stridedBlockId = strRangeMap->getStridedBlockId();
193 RCP<const StridedMap> strShrinkedMap = Teuchos::rcp(
new StridedMap(shrinkedMap, strInfo, shrinkedMap->getIndexBase(), stridedBlockId, offset));
194 thyRgMapExtractorMaps[r] = strShrinkedMap;
196 thyRgMapExtractorMaps[r] = shrinkedMap;
198 TEUCHOS_TEST_FOR_EXCEPTION(thyRgMapExtractorMaps[r]->getLocalNumElements() != rMap->getLocalNumElements(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: Thyra-style range map extractor contains faulty data.")
202 std::vector<Teuchos::RCP<const Map>> thyDoMapExtractorMaps(numCols, Teuchos::null);
203 std::vector<Teuchos::RCP<const Map>> thyColMapExtractorMaps(numCols, Teuchos::null);
204 for (
size_t c = 0; c < numCols; c++) {
205 RCP<const Map> cMap = domainMapExtractor->getMap(c);
208 RCP<const StridedMap> strDomainMap = Teuchos::rcp_dynamic_cast<
const StridedMap>(cMap);
209 if (strDomainMap != Teuchos::null) {
211 GlobalOrdinal offset = strDomainMap->getOffset();
212 LocalOrdinal stridedBlockId = strDomainMap->getStridedBlockId();
213 RCP<const StridedMap> strShrinkedDomainMap = Teuchos::rcp(
new StridedMap(shrinkedDomainMap, strInfo, shrinkedDomainMap->getIndexBase(), stridedBlockId, offset));
214 thyDoMapExtractorMaps[c] = strShrinkedDomainMap;
216 thyDoMapExtractorMaps[c] = shrinkedDomainMap;
218 RCP<const Map> colMap = myColumnMapExtractor->getMap(c);
220 RCP<const StridedMap> strColMap = Teuchos::rcp_dynamic_cast<
const StridedMap>(colMap);
221 if (strColMap != Teuchos::null) {
223 GlobalOrdinal offset = strColMap->getOffset();
224 LocalOrdinal stridedBlockId = strColMap->getStridedBlockId();
225 RCP<const StridedMap> strShrinkedColMap = Teuchos::rcp(
new StridedMap(shrinkedColMap, strInfo, shrinkedColMap->getIndexBase(), stridedBlockId, offset));
226 thyColMapExtractorMaps[c] = strShrinkedColMap;
228 thyColMapExtractorMaps[c] = shrinkedColMap;
231 TEUCHOS_TEST_FOR_EXCEPTION(thyColMapExtractorMaps[c]->getLocalNumElements() != colMap->getLocalNumElements(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: Thyra-style column map extractor contains faulty data.")
232 TEUCHOS_TEST_FOR_EXCEPTION(thyDoMapExtractorMaps[c]->getLocalNumElements() != cMap->getLocalNumElements(),
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::Split: Thyra-style domain map extractor contains faulty data.")
240 std::vector<Teuchos::RCP<Matrix>> subMatrices(numRows * numCols, Teuchos::null);
241 for (
size_t r = 0; r < numRows; r++) {
242 for (
size_t c = 0; c < numCols; c++) {
246 if (bThyraMode ==
true)
259 #if 0 // TAW needs to be fixed (does not compile for Scalar=complex)
266 doCheck->putScalar(1.0);
270 TEUCHOS_TEST_FOR_EXCEPTION(coCheck->normInf() != Teuchos::ScalarTraits< Scalar >::magnitude(1.0),
Xpetra::Exceptions::RuntimeError,
"Xpetra::MatrixUtils::SplitMatrix: error when distributing data.");
272 doCheck->putScalar(-1.0);
273 coCheck->putScalar(-1.0);
275 Teuchos::ArrayRCP< Scalar > doCheckData = doCheck->getDataNonConst(0);
276 for (
size_t rrr = 0; rrr < input.
getDomainMap()->getLocalNumElements(); rrr++) {
278 GlobalOrdinal
id = input.
getDomainMap()->getGlobalElement(rrr);
281 size_t BlockId = domainMapExtractor->getMapIndexForGID(
id);
283 doCheckData[rrr] = Teuchos::as<Scalar>(BlockId);
288 Teuchos::ArrayRCP< Scalar > coCheckData = coCheck->getDataNonConst(0);
291 for (
size_t rr = 0; rr < input.
getRowMap()->getLocalNumElements(); rr++) {
293 GlobalOrdinal growid = input.
getRowMap()->getGlobalElement(rr);
302 size_t rowBlockId = rangeMapExtractor->getMapIndexForGID(growid);
305 GlobalOrdinal subblock_growid = growid;
306 if (bThyraMode ==
true) {
308 LocalOrdinal lrowid = rangeMapExtractor->getMap(rowBlockId)->getLocalElement(growid);
310 subblock_growid = thyRangeMapExtractor->getMap(rowBlockId,
true)->getGlobalElement(lrowid);
316 Teuchos::ArrayView<const LocalOrdinal> indices;
317 Teuchos::ArrayView<const Scalar> vals;
320 std::vector<Teuchos::Array<GlobalOrdinal>> blockColIdx(numCols, Teuchos::Array<GlobalOrdinal>());
321 std::vector<Teuchos::Array<Scalar>> blockColVals(numCols, Teuchos::Array<Scalar>());
323 for (
size_t i = 0; i < (size_t)indices.size(); i++) {
325 GlobalOrdinal gcolid = input.
getColMap()->getGlobalElement(indices[i]);
327 size_t colBlockId = myColumnMapExtractor->getMapIndexForGID(gcolid);
331 GlobalOrdinal subblock_gcolid = gcolid;
332 if (bThyraMode ==
true) {
334 LocalOrdinal lcolid = myColumnMapExtractor->getMap(colBlockId)->getLocalElement(gcolid);
336 subblock_gcolid = thyColMapExtractor->getMap(colBlockId,
true)->getGlobalElement(lcolid);
338 blockColIdx[colBlockId].push_back(subblock_gcolid);
339 blockColVals[colBlockId].push_back(vals[i]);
342 for (
size_t c = 0; c < numCols; c++) {
343 subMatrices[rowBlockId * numCols + c]->insertGlobalValues(subblock_growid, blockColIdx[c].view(0, blockColIdx[c].size()), blockColVals[c].view(0, blockColVals[c].size()));
348 RCP<BlockedCrsMatrix> bA = Teuchos::null;
349 if (bThyraMode ==
true) {
350 for (
size_t r = 0; r < numRows; r++) {
351 for (
size_t c = 0; c < numCols; c++) {
352 subMatrices[r * numCols + c]->fillComplete(thyDomainMapExtractor->getMap(c,
true), thyRangeMapExtractor->getMap(r,
true));
355 bA = Teuchos::rcp(
new BlockedCrsMatrix(thyRangeMapExtractor, thyDomainMapExtractor, 10 ));
357 for (
size_t r = 0; r < numRows; r++) {
358 for (
size_t c = 0; c < numCols; c++) {
359 subMatrices[r * numCols + c]->fillComplete(domainMapExtractor->getMap(c), rangeMapExtractor->getMap(r));
362 bA = Teuchos::rcp(
new BlockedCrsMatrix(rangeMapExtractor, domainMapExtractor, 10 ));
365 for (
size_t r = 0; r < numRows; r++) {
366 for (
size_t c = 0; c < numCols; c++) {
367 bA->setMatrix(r, c, subMatrices[r * numCols + c]);
373 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
375 bool const& repairZeroDiagonals, Teuchos::FancyOStream& fos,
376 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType threshold,
377 const Scalar replacementValue) {
378 using TST =
typename Teuchos::ScalarTraits<Scalar>;
379 using Teuchos::rcp_dynamic_cast;
381 GlobalOrdinal gZeroDiags;
382 bool usedEfficientPath =
false;
384 #ifdef HAVE_MUELU_TPETRA
385 RCP<CrsMatrixWrap> crsWrapAc = rcp_dynamic_cast<
CrsMatrixWrap>(Ac);
386 RCP<TpetraCrsMatrix> tpCrsAc;
387 if (!crsWrapAc.is_null())
388 tpCrsAc = rcp_dynamic_cast<TpetraCrsMatrix>(crsWrapAc->getCrsMatrix());
390 if (!tpCrsAc.is_null()) {
391 auto tpCrsGraph = tpCrsAc->getTpetra_CrsMatrix()->
getCrsGraph();
392 size_t numRows = Ac->getRowMap()->getLocalNumElements();
393 typedef typename Tpetra::CrsGraph<LocalOrdinal, GlobalOrdinal, Node>::offset_device_view_type offset_type;
394 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
395 auto offsets = offset_type(Kokkos::ViewAllocateWithoutInitializing(
"offsets"), numRows);
396 tpCrsGraph->getLocalDiagOffsets(offsets);
399 Tpetra::Details::OrdinalTraits<typename offset_type::value_type>::invalid();
401 if (repairZeroDiagonals) {
405 LO numMissingDiagonalEntries = 0;
407 Kokkos::parallel_reduce(
408 "countMissingDiagonalEntries",
409 range_type(0, numRows),
410 KOKKOS_LAMBDA(
const LO i, LO& missing) {
411 missing += (offsets(i) == STINV);
413 numMissingDiagonalEntries);
415 GlobalOrdinal gNumMissingDiagonalEntries;
416 Teuchos::reduceAll(*(Ac->getRowMap()->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(numMissingDiagonalEntries),
417 Teuchos::outArg(gNumMissingDiagonalEntries));
419 if (gNumMissingDiagonalEntries == 0) {
422 auto lclA = tpCrsAc->getTpetra_CrsMatrix()->getLocalMatrixDevice();
424 using ATS = Kokkos::ArithTraits<Scalar>;
425 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
428 typename ATS::val_type impl_replacementValue = replacementValue;
430 Kokkos::parallel_reduce(
431 "fixSmallDiagonalEntries",
432 range_type(0, numRows),
433 KOKKOS_LAMBDA(
const LO i, LO& fixed) {
434 const auto offset = offsets(i);
435 auto curRow = lclA.row(i);
436 if (impl_ATS::magnitude(curRow.value(offset)) <= threshold) {
437 curRow.value(offset) = impl_replacementValue;
443 Teuchos::reduceAll(*(Ac->getRowMap()->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(lZeroDiags),
444 Teuchos::outArg(gZeroDiags));
446 usedEfficientPath =
true;
452 auto lclA = tpCrsAc->getTpetra_CrsMatrix()->getLocalMatrixDevice();
454 using ATS = Kokkos::ArithTraits<Scalar>;
455 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
459 Kokkos::parallel_reduce(
460 "detectSmallDiagonalEntries",
461 range_type(0, numRows),
462 KOKKOS_LAMBDA(
const LO i, LO& small) {
463 const auto offset = offsets(i);
467 auto curRow = lclA.row(i);
468 if (impl_ATS::magnitude(curRow.value(offset)) <= threshold) {
475 Teuchos::reduceAll(*(Ac->getRowMap()->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(lZeroDiags),
476 Teuchos::outArg(gZeroDiags));
478 usedEfficientPath =
true;
483 if (!usedEfficientPath) {
484 RCP<const Map> rowMap = Ac->getRowMap();
486 Ac->getLocalDiagCopy(*diagVec);
488 LocalOrdinal lZeroDiags = 0;
489 Teuchos::ArrayRCP<const Scalar> diagVal = diagVec->getData(0);
491 for (
size_t i = 0; i < rowMap->getLocalNumElements(); i++) {
492 if (TST::magnitude(diagVal[i]) <= threshold) {
497 Teuchos::reduceAll(*(rowMap->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(lZeroDiags),
498 Teuchos::outArg(gZeroDiags));
500 if (repairZeroDiagonals && gZeroDiags > 0) {
516 Teuchos::Array<GlobalOrdinal> indout(1);
517 Teuchos::Array<Scalar> valout(1);
518 for (
size_t r = 0; r < rowMap->getLocalNumElements(); r++) {
519 if (TST::magnitude(diagVal[r]) <= threshold) {
520 GlobalOrdinal grid = rowMap->getGlobalElement(r);
522 valout[0] = replacementValue;
523 fixDiagMatrix->insertGlobalValues(grid, indout(), valout());
527 Teuchos::TimeMonitor m1(*Teuchos::TimeMonitor::getNewTimer(
"CheckRepairMainDiagonal: fillComplete1"));
528 fixDiagMatrix->fillComplete(Ac->getDomainMap(), Ac->getRangeMap());
532 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*Ac,
false, 1.0, *fixDiagMatrix,
false, 1.0, newAc, fos);
533 if (Ac->IsView(
"stridedMaps"))
534 newAc->CreateView(
"stridedMaps", Ac);
537 fixDiagMatrix = Teuchos::null;
542 Teuchos::RCP<Teuchos::ParameterList> p = Teuchos::rcp(
new Teuchos::ParameterList());
543 p->set(
"DoOptimizeStorage",
true);
545 Teuchos::TimeMonitor m1(*Teuchos::TimeMonitor::getNewTimer(
"CheckRepairMainDiagonal: fillComplete2"));
552 fos <<
"CheckRepairMainDiagonal: " << (repairZeroDiagonals ?
"repaired " :
"found ")
553 << gZeroDiags <<
" too small entries (threshold = " << threshold <<
") on main diagonal of Ac." << std::endl;
555 #ifdef HAVE_XPETRA_DEBUG // only for debugging
558 RCP<const Map> rowMap = Ac->getRowMap();
560 Teuchos::ArrayRCP<const Scalar> diagVal;
561 Ac->getLocalDiagCopy(*diagVec);
562 diagVal = diagVec->getData(0);
563 for (
size_t r = 0; r < Ac->getRowMap()->getLocalNumElements(); r++) {
564 if (TST::magnitude(diagVal[r]) <= threshold) {
565 fos <<
"Error: there are too small entries left on diagonal after repair..." << std::endl;
573 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
575 const Teuchos::ArrayView<const double>& relativeThreshold, Teuchos::FancyOStream& fos) {
576 Teuchos::TimeMonitor m1(*Teuchos::TimeMonitor::getNewTimer(
"RelativeDiagonalBoost"));
578 TEUCHOS_TEST_FOR_EXCEPTION(A->GetFixedBlockSize() != relativeThreshold.size() && relativeThreshold.size() != 1,
Xpetra::Exceptions::Incompatible,
"Xpetra::MatrixUtils::RelativeDiagonal Boost: Either A->GetFixedBlockSize() != relativeThreshold.size() OR relativeThreshold.size() == 1");
580 LocalOrdinal numPDEs = A->GetFixedBlockSize();
581 typedef typename Teuchos::ScalarTraits<Scalar> TST;
582 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType MT;
583 Scalar zero = TST::zero();
584 Scalar one = TST::one();
588 A->getLocalDiagCopy(*diag);
589 Teuchos::ArrayRCP<const Scalar> dataVal = diag->getData(0);
590 size_t N = A->getRowMap()->getLocalNumElements();
593 std::vector<MT> l_diagMax(numPDEs), g_diagMax(numPDEs);
594 for (
size_t i = 0; i < N; i++) {
595 int pde = (int)(i % numPDEs);
596 if ((
int)i < numPDEs)
597 l_diagMax[pde] = TST::magnitude(dataVal[i]);
599 l_diagMax[pde] = std::max(l_diagMax[pde], TST::magnitude(dataVal[i]));
601 Teuchos::reduceAll(*A->getRowMap()->getComm(), Teuchos::REDUCE_MAX, numPDEs, l_diagMax.data(), g_diagMax.data());
605 Teuchos::Array<GlobalOrdinal> index(1);
606 Teuchos::Array<Scalar> value(1);
607 for (
size_t i = 0; i < N; i++) {
608 GlobalOrdinal GRID = A->getRowMap()->getGlobalElement(i);
609 int pde = (int)(i % numPDEs);
611 if (TST::magnitude(dataVal[i]) < relativeThreshold[pde] * g_diagMax[pde])
612 value[0] = relativeThreshold[pde] * g_diagMax[pde] - TST::magnitude(dataVal[i]);
615 boostMatrix->insertGlobalValues(GRID, index(), value());
617 boostMatrix->fillComplete(A->getDomainMap(), A->getRangeMap());
621 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*A,
false, one, *boostMatrix,
false, one, newA, fos);
622 if (A->IsView(
"stridedMaps"))
623 newA->CreateView(
"stridedMaps", A);
628 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
634 #if defined(HAVE_XPETRA_EPETRA)
636 #endif // HAVE_XPETRA_EPETRA
638 #ifdef HAVE_XPETRA_TPETRA
641 Tpetra::Details::extractBlockDiagonal(At, Dt);
642 #endif // HAVE_XPETRA_TPETRA
646 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
653 #if defined(HAVE_XPETRA_EPETRA)
655 #endif // HAVE_XPETRA_EPETRA
657 #ifdef HAVE_XPETRA_TPETRA
660 Tpetra::Details::inverseScaleBlockDiagonal(Dt, doTranspose, St);
661 #endif // HAVE_XPETRA_TPETRA
665 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
671 auto tpRowMap = Teuchos::rcp_dynamic_cast<
const TpetraMap>(rowMap,
true)->getTpetra_Map();
672 auto tpColMap = Teuchos::rcp_dynamic_cast<
const TpetraMap>(colMap,
true)->getTpetra_Map();
673 fail = !tpColMap->isLocallyFitted(*tpRowMap);
675 RCP<const Teuchos::Comm<int>> comm = rowMap->getComm();
676 LO numRows = Teuchos::as<LocalOrdinal>(rowMap->getLocalNumElements());
678 for (LO rowLID = 0; rowLID < numRows; rowLID++) {
679 GO rowGID = rowMap->getGlobalElement(rowLID);
680 LO colGID = colMap->getGlobalElement(rowLID);
681 if (rowGID != colGID) {
683 std::cerr <<
"On rank " << comm->getRank() <<
", LID " << rowLID <<
" is GID " << rowGID <<
" in the rowmap, but GID " << colGID <<
" in the column map.\n";
688 "Local parts of row and column map do not match!");
691 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
694 std::vector<size_t>& rangeStridingInfo, std::vector<size_t>& domainStridingInfo) {
698 if (matrix->IsView(
"stridedMaps") ==
true) matrix->RemoveView(
"stridedMaps");
699 matrix->CreateView(
"stridedMaps", stridedRowMap, stridedColMap);
704 #endif // PACKAGES_XPETRA_SUP_MATRIX_UTILS_DEF_HPP_
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.
virtual const RCP< const Map > & getColMap() const
Returns the Map that describes the column distribution in this matrix. This might be null until fillC...
static void CheckRepairMainDiagonal(RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &Ac, bool const &repairZeroDiagonals, Teuchos::FancyOStream &fos, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType threshold=Teuchos::ScalarTraits< typename Teuchos::ScalarTraits< Scalar >::magnitudeType >::zero(), const Scalar replacementValue=Teuchos::ScalarTraits< Scalar >::one())
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.
virtual const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
Exception throws to report errors in the internal logical of the program.
static Teuchos::RCP< Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > SplitMatrix(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input, Teuchos::RCP< const Xpetra::MapExtractor< Scalar, LocalOrdinal, GlobalOrdinal, Node >> rangeMapExtractor, Teuchos::RCP< const Xpetra::MapExtractor< Scalar, LocalOrdinal, GlobalOrdinal, Node >> domainMapExtractor, Teuchos::RCP< const Xpetra::MapExtractor< Scalar, LocalOrdinal, GlobalOrdinal, Node >> columnMapExtractor=Teuchos::null, bool bThyraMode=false)
static RCP< const Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2TpetraCrs(RCP< Matrix > Op)
static Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > concatenateMaps(const std::vector< Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > > &subMaps)
Helper function to concatenate several maps.
virtual bool isNodeGlobalElement(GlobalOrdinal globalIndex) const =0
Whether the given global index is valid for this Map on this process.
virtual void getLocalRowView(LocalOrdinal LocalRow, ArrayView< const LocalOrdinal > &indices, ArrayView< const Scalar > &values) const =0
Extract a const, non-persisting view of local indices in a specified row of the matrix.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
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 Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > findColumnSubMap(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &domainMap)
virtual Teuchos::ArrayRCP< const Scalar > getData(size_t j) const =0
Const view of the local values in a particular vector of this multivector.
static void RelativeDiagonalBoost(RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &A, const Teuchos::ArrayView< const double > &relativeThreshold, Teuchos::FancyOStream &fos)
RCP< const Tpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > toTpetra(const RCP< const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > &graph)
virtual const Teuchos::RCP< const map_type > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y...
static Teuchos::RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > xpetraGidNumbering2ThyraGidNumbering(const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input)
virtual size_t getLocalLength() const =0
Local number of rows on the calling process.
RCP< const CrsGraph > getCrsGraph() const
Returns the CrsGraph associated with this matrix.
static Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > shrinkMapGIDs(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlInput)
Helper function to shrink the GIDs and generate a standard map whith GIDs starting at 0...
static void convertMatrixToStridedMaps(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> matrix, std::vector< size_t > &rangeStridingInfo, std::vector< size_t > &domainStridingInfo)
std::vector< size_t > getStridingData() const
static RCP< Matrix > Build(const RCP< const Map > &rowMap)
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
Helper function to calculate B = alpha*A + beta*B.
Exception throws to report incompatible objects (like maps).
Concrete implementation of Xpetra::Matrix.
static void extractBlockDiagonal(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &diagonal)
virtual const Teuchos::RCP< const map_type > getDomainMap() const =0
The Map associated with the domain of this operator, which must be compatible with X...
virtual size_t getLocalMaxNumRowEntries() const =0
Returns the maximum number of entries across all rows/columns on this node.
static RCP< Xpetra::StridedMap< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, std::vector< size_t > &stridingInfo, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalOrdinal stridedBlockId=-1, GlobalOrdinal offset=0, LocalGlobal lg=Xpetra::GloballyDistributed)
Map constructor with Xpetra-defined contiguous uniform distribution.
virtual size_t getNumVectors() const =0
Number of columns in the multivector.
virtual UnderlyingLib lib() const =0
Get the library used by this object (Tpetra or Epetra?)
static RCP< Import< LocalOrdinal, GlobalOrdinal, Node > > Build(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &source, const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &target, const Teuchos::RCP< Teuchos::ParameterList > &plist=Teuchos::null)
Constructor specifying the number of non-zeros for all rows.
Xpetra-specific matrix class.
Class that stores a strided map.
static void checkLocalRowMapMatchesColMap(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
static void inverseScaleBlockDiagonal(Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &blockDiagonal, bool doTranspose, Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &toBeScaled)