47 #ifndef PACKAGES_XPETRA_SUP_MATRIX_UTILS_HPP_
48 #define PACKAGES_XPETRA_SUP_MATRIX_UTILS_HPP_
53 #include "Xpetra_Map.hpp"
55 #include "Xpetra_StridedMap.hpp"
56 #include "Xpetra_MapFactory.hpp"
57 #include "Xpetra_MapExtractor.hpp"
66 #ifdef HAVE_XPETRA_TPETRA
67 #include "Xpetra_TpetraMultiVector.hpp"
68 #include <Tpetra_RowMatrixTransposer.hpp>
69 #include <Tpetra_Details_extractBlockDiagonal.hpp>
70 #include <Tpetra_Details_scaleBlockDiagonal.hpp>
84 template <
class Scalar,
89 #undef XPETRA_MATRIXUTILS_SHORT
101 ret->replaceLocalValue(Teuchos::as<LocalOrdinal>(r), c, data[r]);
119 for(
size_t i = 0; i<input.
getColMap()->getNodeNumElements(); i++) {
120 GlobalOrdinal gcid = input.
getColMap()->getGlobalElement(i);
128 std::vector<int> myUnknownDofGIDs(comm->getSize(),0);
129 std::vector<int> numUnknownDofGIDs(comm->getSize(),0);
130 myUnknownDofGIDs[comm->getRank()] = ovlUnknownStatusGids.
size();
131 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,comm->getSize(),&myUnknownDofGIDs[0],&numUnknownDofGIDs[0]);
134 size_t cntUnknownDofGIDs = 0;
135 for(
int p = 0; p < comm->getSize(); p++) cntUnknownDofGIDs += numUnknownDofGIDs[p];
136 std::vector<GlobalOrdinal> lUnknownDofGIDs(cntUnknownDofGIDs,-1);
137 std::vector<GlobalOrdinal> gUnknownDofGIDs(cntUnknownDofGIDs,-1);
139 size_t cntUnknownOffset = 0;
140 for(
int p = 0; p < comm->getRank(); p++) cntUnknownOffset += numUnknownDofGIDs[p];
141 for(
size_t k=0; k < Teuchos::as<size_t>(ovlUnknownStatusGids.
size()); k++) {
142 lUnknownDofGIDs[k+cntUnknownOffset] = ovlUnknownStatusGids[k];
144 if(cntUnknownDofGIDs > 0)
145 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,Teuchos::as<int>(cntUnknownDofGIDs),&lUnknownDofGIDs[0],&gUnknownDofGIDs[0]);
146 std::sort(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end());
147 gUnknownDofGIDs.erase(std::unique(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end()), gUnknownDofGIDs.end());
150 for(
size_t k=0; k < gUnknownDofGIDs.size(); k++) {
151 GlobalOrdinal curgid = gUnknownDofGIDs[k];
157 std::vector<int> myFoundDofGIDs(comm->getSize(),0);
158 std::vector<int> numFoundDofGIDs(comm->getSize(),0);
159 myFoundDofGIDs[comm->getRank()] = ovlFoundStatusGids.
size();
160 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,comm->getSize(),&myFoundDofGIDs[0],&numFoundDofGIDs[0]);
163 size_t cntFoundDofGIDs = 0;
164 for(
int p = 0; p < comm->getSize(); p++) cntFoundDofGIDs += numFoundDofGIDs[p];
165 std::vector<GlobalOrdinal> lFoundDofGIDs(cntFoundDofGIDs,-1);
166 std::vector<GlobalOrdinal> gFoundDofGIDs(cntFoundDofGIDs,-1);
168 size_t cntFoundOffset = 0;
169 for(
int p = 0; p < comm->getRank(); p++) cntFoundOffset += numFoundDofGIDs[p];
170 for(
size_t k=0; k < Teuchos::as<size_t>(ovlFoundStatusGids.
size()); k++) {
171 lFoundDofGIDs[k+cntFoundOffset] = ovlFoundStatusGids[k];
173 if(cntFoundDofGIDs > 0)
174 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,Teuchos::as<int>(cntFoundDofGIDs),&lFoundDofGIDs[0],&gFoundDofGIDs[0]);
177 for(
size_t i = 0; i<input.
getColMap()->getNodeNumElements(); i++) {
178 GlobalOrdinal gcid = input.
getColMap()->getGlobalElement(i);
180 std::find(gFoundDofGIDs.begin(), gFoundDofGIDs.end(), gcid) != gFoundDofGIDs.end()) {
201 bool bThyraMode =
false) {
203 size_t numRows = rangeMapExtractor->NumMaps();
204 size_t numCols = domainMapExtractor->NumMaps();
206 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.")
207 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.")
219 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())
226 if(columnMapExtractor == Teuchos::null) {
229 std::vector<Teuchos::RCP<const Map> > ovlxmaps(numCols, Teuchos::null);
230 for(
size_t c = 0; c < numCols; c++) {
233 ovlxmaps[c] = colMap;
239 myColumnMapExtractor = columnMapExtractor;
246 if(bThyraMode ==
true) {
248 std::vector<Teuchos::RCP<const Map> > thyRgMapExtractorMaps(numRows, Teuchos::null);
249 for (
size_t r = 0; r < numRows; r++) {
253 if(strRangeMap != Teuchos::null) {
254 std::vector<size_t> strInfo = strRangeMap->getStridingData();
255 GlobalOrdinal offset = strRangeMap->getOffset();
256 LocalOrdinal stridedBlockId = strRangeMap->getStridedBlockId();
258 thyRgMapExtractorMaps[r] = strShrinkedMap;
260 thyRgMapExtractorMaps[r] = shrinkedMap;
266 std::vector<Teuchos::RCP<const Map> > thyDoMapExtractorMaps (numCols, Teuchos::null);
267 std::vector<Teuchos::RCP<const Map> > thyColMapExtractorMaps(numCols, Teuchos::null);
268 for (
size_t c = 0; c < numCols; c++) {
273 if(strDomainMap != Teuchos::null) {
274 std::vector<size_t> strInfo = strDomainMap->getStridingData();
275 GlobalOrdinal offset = strDomainMap->getOffset();
276 LocalOrdinal stridedBlockId = strDomainMap->getStridedBlockId();
278 thyDoMapExtractorMaps[c] = strShrinkedDomainMap;
280 thyDoMapExtractorMaps[c] = shrinkedDomainMap;
285 if(strColMap != Teuchos::null) {
286 std::vector<size_t> strInfo = strColMap->getStridingData();
287 GlobalOrdinal offset = strColMap->getOffset();
288 LocalOrdinal stridedBlockId = strColMap->getStridedBlockId();
290 thyColMapExtractorMaps[c] = strShrinkedColMap;
292 thyColMapExtractorMaps[c] = shrinkedColMap;
304 std::vector<Teuchos::RCP<Matrix> > subMatrices(numRows*numCols, Teuchos::null);
305 for (
size_t r = 0; r < numRows; r++) {
306 for (
size_t c = 0; c < numCols; c++) {
310 if(bThyraMode ==
true)
330 doCheck->putScalar(1.0);
336 doCheck->putScalar(-1.0);
337 coCheck->putScalar(-1.0);
340 for (
size_t rrr = 0; rrr < input.
getDomainMap()->getNodeNumElements(); rrr++) {
342 GlobalOrdinal
id = input.
getDomainMap()->getGlobalElement(rrr);
345 size_t BlockId = domainMapExtractor->getMapIndexForGID(
id);
347 doCheckData[rrr] = Teuchos::as<Scalar>(BlockId);
355 for (
size_t rr = 0; rr < input.
getRowMap()->getNodeNumElements(); rr++) {
358 GlobalOrdinal growid = input.
getRowMap()->getGlobalElement(rr);
367 size_t rowBlockId = rangeMapExtractor->getMapIndexForGID(growid);
370 GlobalOrdinal subblock_growid = growid;
371 if(bThyraMode ==
true) {
373 LocalOrdinal lrowid = rangeMapExtractor->getMap(rowBlockId)->getLocalElement(growid);
375 subblock_growid = thyRangeMapExtractor->getMap(rowBlockId,
true)->getGlobalElement(lrowid);
388 for(
size_t i=0; i<(size_t)indices.
size(); i++) {
390 GlobalOrdinal gcolid = input.
getColMap()->getGlobalElement(indices[i]);
392 size_t colBlockId = myColumnMapExtractor->getMapIndexForGID(gcolid);
396 GlobalOrdinal subblock_gcolid = gcolid;
397 if(bThyraMode ==
true) {
399 LocalOrdinal lcolid = myColumnMapExtractor->getMap(colBlockId)->getLocalElement(gcolid);
401 subblock_gcolid = thyColMapExtractor->getMap(colBlockId,
true)->getGlobalElement(lcolid);
403 blockColIdx [colBlockId].push_back(subblock_gcolid);
404 blockColVals[colBlockId].push_back(vals[i]);
407 for (
size_t c = 0; c < numCols; c++) {
408 subMatrices[rowBlockId*numCols+c]->insertGlobalValues(subblock_growid,blockColIdx[c].view(0,blockColIdx[c].size()),blockColVals[c].view(0,blockColVals[c].size()));
415 if(bThyraMode ==
true) {
416 for (
size_t r = 0; r < numRows; r++) {
417 for (
size_t c = 0; c < numCols; c++) {
418 subMatrices[r*numCols+c]->fillComplete(thyDomainMapExtractor->getMap(c,
true), thyRangeMapExtractor->getMap(r,
true));
423 for (
size_t r = 0; r < numRows; r++) {
424 for (
size_t c = 0; c < numCols; c++) {
425 subMatrices[r*numCols+c]->fillComplete(domainMapExtractor->getMap(c), rangeMapExtractor->getMap(r));
431 for (
size_t r = 0; r < numRows; r++) {
432 for (
size_t c = 0; c < numCols; c++) {
433 bA->setMatrix(r,c,subMatrices[r*numCols+c]);
446 Scalar one = TST::one();
449 p->set(
"DoOptimizeStorage",
true);
453 Ac->getLocalDiagCopy(*diagVec);
455 LocalOrdinal lZeroDiags = 0;
458 for (
size_t i = 0; i < rowMap->getNodeNumElements(); i++) {
459 if (TST::magnitude(diagVal[i]) <= threshold) {
463 GlobalOrdinal gZeroDiags;
464 Teuchos::reduceAll(*(rowMap->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(lZeroDiags),
465 Teuchos::outArg(gZeroDiags));
467 if (repairZeroDiagonals && gZeroDiags > 0) {
485 for (
size_t r = 0; r < rowMap->getNodeNumElements(); r++) {
486 if (TST::magnitude(diagVal[r]) <= threshold) {
487 GlobalOrdinal grid = rowMap->getGlobalElement(r);
490 fixDiagMatrix->insertGlobalValues(grid,indout(), valout());
495 fixDiagMatrix->fillComplete(Ac->getDomainMap(),Ac->getRangeMap());
499 Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::TwoMatrixAdd(*Ac,
false, 1.0, *fixDiagMatrix,
false, 1.0, newAc, fos);
500 if (Ac->IsView(
"stridedMaps"))
501 newAc->CreateView(
"stridedMaps", Ac);
504 fixDiagMatrix = Teuchos::null;
518 fos <<
"CheckRepairMainDiagonal: " << (repairZeroDiagonals ?
"repaired " :
"found ")
519 << gZeroDiags <<
" too small entries on main diagonal of Ac." << std::endl;
521 #ifdef HAVE_XPETRA_DEBUG
523 Ac->getLocalDiagCopy(*diagVec);
524 diagVal = diagVec->getData(0);
525 for (
size_t r = 0; r < Ac->getRowMap()->getNodeNumElements(); r++) {
526 if (TST::magnitude(diagVal[r]) <= threshold) {
527 fos <<
"Error: there are too small entries left on diagonal after repair..." << std::endl;
549 LocalOrdinal numPDEs = A->GetFixedBlockSize();
552 Scalar zero = TST::zero();
553 Scalar one = TST::one();
557 A->getLocalDiagCopy(*diag);
559 size_t N = A->getRowMap()->getNodeNumElements();
562 std::vector<MT> l_diagMax(numPDEs), g_diagMax(numPDEs);
563 for(
size_t i=0; i<N; i++) {
564 int pde = (int) (i % numPDEs);
566 l_diagMax[pde] = TST::magnitude(dataVal[i]);
568 l_diagMax[pde] = std::max(l_diagMax[pde],TST::magnitude(dataVal[i]));
570 Teuchos::reduceAll(*A->getRowMap()->getComm(), Teuchos::REDUCE_MAX, numPDEs, l_diagMax.data(), g_diagMax.data() );
576 for (
size_t i = 0; i<N; i++) {
577 GlobalOrdinal GRID = A->getRowMap()->getGlobalElement(i);
578 int pde = (int) (i % numPDEs);
580 if (TST::magnitude(dataVal[i]) < relativeThreshold[pde] * g_diagMax[pde])
581 value[0] = relativeThreshold[pde] * g_diagMax[pde] - TST::magnitude(dataVal[i]);
584 boostMatrix->insertGlobalValues(GRID,index(),value());
586 boostMatrix->fillComplete(A->getDomainMap(),A->getRangeMap());
590 Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::TwoMatrixAdd(*A,
false,one, *boostMatrix,
false,one,newA,fos);
591 if (A->IsView(
"stridedMaps"))
592 newA->CreateView(
"stridedMaps", A);
604 #if defined(HAVE_XPETRA_EPETRA)
608 #ifdef HAVE_XPETRA_TPETRA
611 Tpetra::Details::extractBlockDiagonal(At,Dt);
624 #if defined(HAVE_XPETRA_EPETRA)
628 #ifdef HAVE_XPETRA_TPETRA
629 const Tpetra::MultiVector<SC,LO,GO,NO> & Dt =
Xpetra::toTpetra(blockDiagonal);
631 Tpetra::Details::inverseScaleBlockDiagonal(Dt,doTranspose,St);
640 LO numRows = Teuchos::as<LocalOrdinal>(rowMap->getNodeNumElements());
642 for (
LO rowLID = 0; rowLID < numRows; rowLID++) {
643 GO rowGID = rowMap->getGlobalElement(rowLID);
644 LO colLID = colMap->getLocalElement(rowGID);
645 if (rowLID != colLID) {
647 std::cerr <<
"On rank " << comm->getRank() <<
", GID " << rowGID <<
" is LID " << rowLID <<
"in the rowmap, but LID " << colLID <<
" in the column map.\n";
651 "Local parts of row and column map do not match!");
659 #define XPETRA_MATRIXUTILS_SHORT
void push_back(const value_type &x)
static RCP< Time > getNewTimer(const std::string &name)
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
Exception throws to report incompatible objects (like maps).
Exception throws to report errors in the internal logical of the program.
static RCP< const Tpetra::CrsMatrix< SC, LO, GO, NO > > Op2TpetraCrs(RCP< Matrix > Op)
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.
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< 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.
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.
virtual UnderlyingLib lib() const =0
Get the library used by this object (Tpetra or Epetra?)
virtual bool isNodeGlobalElement(GlobalOrdinal globalIndex) const =0
Whether the given global index is valid for this Map on this process.
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.
Xpetra utility class for common matrix-related routines.
static Teuchos::RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > xpetraGidNumbering2ThyraGidNumbering(const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input)
static Teuchos::RCP< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > findColumnSubMap(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &domainMap)
static void checkLocalRowMapMatchesColMap(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
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())
static void inverseScaleBlockDiagonal(const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &blockDiagonal, bool doTranspose, Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &toBeScaled)
static void RelativeDiagonalBoost(RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &A, const Teuchos::ArrayView< const double > &relativeThreshold, Teuchos::FancyOStream &fos)
static void extractBlockDiagonal(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &diagonal)
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)
Xpetra-specific matrix class.
virtual size_t getNodeMaxNumRowEntries() const =0
Returns the maximum number of entries across all rows/columns on this node.
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 const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
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 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 size_t getNumVectors() const =0
Number of columns in the multivector.
virtual size_t getLocalLength() const =0
Local number of rows on the calling process.
virtual Teuchos::ArrayRCP< const Scalar > getData(size_t j) const =0
Const view of the local values in a particular vector of this multivector.
virtual Teuchos::RCP< const Map > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y....
virtual Teuchos::RCP< const Map > getDomainMap() const =0
The Map associated with the domain of this operator, which must be compatible with X....
Class that stores a strided map.
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.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
RCP< const Tpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > toTpetra(const RCP< const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > &graph)