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
104 ret->replaceLocalValue(Teuchos::as<LocalOrdinal>(r), c, data[r]);
122 for(
size_t i = 0; i<input.
getColMap()->getNodeNumElements(); i++) {
123 GlobalOrdinal gcid = input.
getColMap()->getGlobalElement(i);
131 std::vector<int> myUnknownDofGIDs(comm->getSize(),0);
132 std::vector<int> numUnknownDofGIDs(comm->getSize(),0);
133 myUnknownDofGIDs[comm->getRank()] = ovlUnknownStatusGids.
size();
134 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,comm->getSize(),&myUnknownDofGIDs[0],&numUnknownDofGIDs[0]);
137 size_t cntUnknownDofGIDs = 0;
138 for(
int p = 0; p < comm->getSize(); p++) cntUnknownDofGIDs += numUnknownDofGIDs[p];
139 std::vector<GlobalOrdinal> lUnknownDofGIDs(cntUnknownDofGIDs,-1);
140 std::vector<GlobalOrdinal> gUnknownDofGIDs(cntUnknownDofGIDs,-1);
142 size_t cntUnknownOffset = 0;
143 for(
int p = 0; p < comm->getRank(); p++) cntUnknownOffset += numUnknownDofGIDs[p];
144 for(
size_t k=0; k < Teuchos::as<size_t>(ovlUnknownStatusGids.
size()); k++) {
145 lUnknownDofGIDs[k+cntUnknownOffset] = ovlUnknownStatusGids[k];
147 if(cntUnknownDofGIDs > 0)
148 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,Teuchos::as<int>(cntUnknownDofGIDs),&lUnknownDofGIDs[0],&gUnknownDofGIDs[0]);
149 std::sort(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end());
150 gUnknownDofGIDs.erase(std::unique(gUnknownDofGIDs.begin(), gUnknownDofGIDs.end()), gUnknownDofGIDs.end());
153 for(
size_t k=0; k < gUnknownDofGIDs.size(); k++) {
154 GlobalOrdinal curgid = gUnknownDofGIDs[k];
160 std::vector<int> myFoundDofGIDs(comm->getSize(),0);
161 std::vector<int> numFoundDofGIDs(comm->getSize(),0);
162 myFoundDofGIDs[comm->getRank()] = ovlFoundStatusGids.
size();
163 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,comm->getSize(),&myFoundDofGIDs[0],&numFoundDofGIDs[0]);
166 size_t cntFoundDofGIDs = 0;
167 for(
int p = 0; p < comm->getSize(); p++) cntFoundDofGIDs += numFoundDofGIDs[p];
168 std::vector<GlobalOrdinal> lFoundDofGIDs(cntFoundDofGIDs,-1);
169 std::vector<GlobalOrdinal> gFoundDofGIDs(cntFoundDofGIDs,-1);
171 size_t cntFoundOffset = 0;
172 for(
int p = 0; p < comm->getRank(); p++) cntFoundOffset += numFoundDofGIDs[p];
173 for(
size_t k=0; k < Teuchos::as<size_t>(ovlFoundStatusGids.
size()); k++) {
174 lFoundDofGIDs[k+cntFoundOffset] = ovlFoundStatusGids[k];
176 if(cntFoundDofGIDs > 0)
177 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MAX,Teuchos::as<int>(cntFoundDofGIDs),&lFoundDofGIDs[0],&gFoundDofGIDs[0]);
180 for(
size_t i = 0; i<input.
getColMap()->getNodeNumElements(); i++) {
181 GlobalOrdinal gcid = input.
getColMap()->getGlobalElement(i);
183 std::find(gFoundDofGIDs.begin(), gFoundDofGIDs.end(), gcid) != gFoundDofGIDs.end()) {
204 bool bThyraMode =
false) {
210 size_t numRows = rangeMapExtractor->NumMaps();
211 size_t numCols = domainMapExtractor->NumMaps();
213 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.")
214 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.")
226 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())
233 if(columnMapExtractor == Teuchos::null) {
236 std::vector<Teuchos::RCP<const Map> > ovlxmaps(numCols, Teuchos::null);
237 for(
size_t c = 0; c < numCols; c++) {
240 ovlxmaps[c] = colMap;
246 myColumnMapExtractor = columnMapExtractor;
253 if(bThyraMode ==
true) {
255 std::vector<Teuchos::RCP<const Map> > thyRgMapExtractorMaps(numRows, Teuchos::null);
256 for (
size_t r = 0; r < numRows; r++) {
260 if(strRangeMap != Teuchos::null) {
261 std::vector<size_t> strInfo = strRangeMap->getStridingData();
262 GlobalOrdinal offset = strRangeMap->getOffset();
263 LocalOrdinal stridedBlockId = strRangeMap->getStridedBlockId();
265 thyRgMapExtractorMaps[r] = strShrinkedMap;
267 thyRgMapExtractorMaps[r] = shrinkedMap;
273 std::vector<Teuchos::RCP<const Map> > thyDoMapExtractorMaps (numCols, Teuchos::null);
274 std::vector<Teuchos::RCP<const Map> > thyColMapExtractorMaps(numCols, Teuchos::null);
275 for (
size_t c = 0; c < numCols; c++) {
280 if(strDomainMap != Teuchos::null) {
281 std::vector<size_t> strInfo = strDomainMap->getStridingData();
282 GlobalOrdinal offset = strDomainMap->getOffset();
283 LocalOrdinal stridedBlockId = strDomainMap->getStridedBlockId();
285 thyDoMapExtractorMaps[c] = strShrinkedDomainMap;
287 thyDoMapExtractorMaps[c] = shrinkedDomainMap;
292 if(strColMap != Teuchos::null) {
293 std::vector<size_t> strInfo = strColMap->getStridingData();
294 GlobalOrdinal offset = strColMap->getOffset();
295 LocalOrdinal stridedBlockId = strColMap->getStridedBlockId();
297 thyColMapExtractorMaps[c] = strShrinkedColMap;
299 thyColMapExtractorMaps[c] = shrinkedColMap;
311 std::vector<Teuchos::RCP<Matrix> > subMatrices(numRows*numCols, Teuchos::null);
312 for (
size_t r = 0; r < numRows; r++) {
313 for (
size_t c = 0; c < numCols; c++) {
317 if(bThyraMode ==
true)
330 #if 0 // TAW needs to be fixed (does not compile for Scalar=complex)
337 doCheck->putScalar(1.0);
343 doCheck->putScalar(-1.0);
344 coCheck->putScalar(-1.0);
347 for (
size_t rrr = 0; rrr < input.getDomainMap()->getNodeNumElements(); rrr++) {
349 GlobalOrdinal
id = input.getDomainMap()->getGlobalElement(rrr);
352 size_t BlockId = domainMapExtractor->getMapIndexForGID(
id);
354 doCheckData[rrr] = Teuchos::as<Scalar>(BlockId);
362 for (
size_t rr = 0; rr < input.
getRowMap()->getNodeNumElements(); rr++) {
365 GlobalOrdinal growid = input.
getRowMap()->getGlobalElement(rr);
374 size_t rowBlockId = rangeMapExtractor->getMapIndexForGID(growid);
377 GlobalOrdinal subblock_growid = growid;
378 if(bThyraMode ==
true) {
380 LocalOrdinal lrowid = rangeMapExtractor->getMap(rowBlockId)->getLocalElement(growid);
382 subblock_growid = thyRangeMapExtractor->getMap(rowBlockId,
true)->getGlobalElement(lrowid);
395 for(
size_t i=0; i<(size_t)indices.
size(); i++) {
397 GlobalOrdinal gcolid = input.
getColMap()->getGlobalElement(indices[i]);
399 size_t colBlockId = myColumnMapExtractor->getMapIndexForGID(gcolid);
403 GlobalOrdinal subblock_gcolid = gcolid;
404 if(bThyraMode ==
true) {
406 LocalOrdinal lcolid = myColumnMapExtractor->getMap(colBlockId)->getLocalElement(gcolid);
408 subblock_gcolid = thyColMapExtractor->getMap(colBlockId,
true)->getGlobalElement(lcolid);
410 blockColIdx [colBlockId].push_back(subblock_gcolid);
411 blockColVals[colBlockId].push_back(vals[i]);
414 for (
size_t c = 0; c < numCols; c++) {
415 subMatrices[rowBlockId*numCols+c]->insertGlobalValues(subblock_growid,blockColIdx[c].view(0,blockColIdx[c].size()),blockColVals[c].view(0,blockColVals[c].size()));
422 if(bThyraMode ==
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(thyDomainMapExtractor->getMap(c,
true), thyRangeMapExtractor->getMap(r,
true));
430 for (
size_t r = 0; r < numRows; r++) {
431 for (
size_t c = 0; c < numCols; c++) {
432 subMatrices[r*numCols+c]->fillComplete(domainMapExtractor->getMap(c), rangeMapExtractor->getMap(r));
438 for (
size_t r = 0; r < numRows; r++) {
439 for (
size_t c = 0; c < numCols; c++) {
440 bA->setMatrix(r,c,subMatrices[r*numCols+c]);
453 Scalar one = TST::one();
456 p->set(
"DoOptimizeStorage",
true);
460 Ac->getLocalDiagCopy(*diagVec);
462 LocalOrdinal lZeroDiags = 0;
465 for (
size_t i = 0; i < rowMap->getNodeNumElements(); i++) {
466 if (TST::magnitude(diagVal[i]) <= threshold) {
470 GlobalOrdinal gZeroDiags;
471 Teuchos::reduceAll(*(rowMap->getComm()), Teuchos::REDUCE_SUM, Teuchos::as<GlobalOrdinal>(lZeroDiags),
472 Teuchos::outArg(gZeroDiags));
474 if (repairZeroDiagonals && gZeroDiags > 0) {
492 for (
size_t r = 0; r < rowMap->getNodeNumElements(); r++) {
493 if (TST::magnitude(diagVal[r]) <= threshold) {
494 GlobalOrdinal grid = rowMap->getGlobalElement(r);
497 fixDiagMatrix->insertGlobalValues(grid,indout(), valout());
502 fixDiagMatrix->fillComplete(Ac->getDomainMap(),Ac->getRangeMap());
506 Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::TwoMatrixAdd(*Ac,
false, 1.0, *fixDiagMatrix,
false, 1.0, newAc, fos);
507 if (Ac->IsView(
"stridedMaps"))
508 newAc->CreateView(
"stridedMaps", Ac);
511 fixDiagMatrix = Teuchos::null;
525 fos <<
"CheckRepairMainDiagonal: " << (repairZeroDiagonals ?
"repaired " :
"found ")
526 << gZeroDiags <<
" too small entries on main diagonal of Ac." << std::endl;
528 #ifdef HAVE_XPETRA_DEBUG // only for debugging
530 Ac->getLocalDiagCopy(*diagVec);
532 for (
size_t r = 0; r < Ac->getRowMap()->getNodeNumElements(); r++) {
533 if (TST::magnitude(diagVal[r]) <= threshold) {
534 fos <<
"Error: there are too small entries left on diagonal after repair..." << std::endl;
556 LocalOrdinal numPDEs = A->GetFixedBlockSize();
559 Scalar zero = TST::zero();
560 Scalar one = TST::one();
564 A->getLocalDiagCopy(*diag);
566 size_t N = A->getRowMap()->getNodeNumElements();
569 std::vector<MT> l_diagMax(numPDEs), g_diagMax(numPDEs);
570 for(
size_t i=0; i<N; i++) {
571 int pde = (int) (i % numPDEs);
573 l_diagMax[pde] = TST::magnitude(dataVal[i]);
575 l_diagMax[pde] = std::max(l_diagMax[pde],TST::magnitude(dataVal[i]));
577 Teuchos::reduceAll(*A->getRowMap()->getComm(), Teuchos::REDUCE_MAX, numPDEs, l_diagMax.data(), g_diagMax.data() );
583 for (
size_t i = 0; i<N; i++) {
584 GlobalOrdinal GRID = A->getRowMap()->getGlobalElement(i);
585 int pde = (int) (i % numPDEs);
587 if (TST::magnitude(dataVal[i]) < relativeThreshold[pde] * g_diagMax[pde])
588 value[0] = relativeThreshold[pde] * g_diagMax[pde] - TST::magnitude(dataVal[i]);
591 boostMatrix->insertGlobalValues(GRID,index(),value());
593 boostMatrix->fillComplete(A->getDomainMap(),A->getRangeMap());
597 Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::TwoMatrixAdd(*A,
false,one, *boostMatrix,
false,one,newA,fos);
598 if (A->IsView(
"stridedMaps"))
599 newA->CreateView(
"stridedMaps", A);
611 #if defined(HAVE_XPETRA_EPETRA)
613 #endif // HAVE_XPETRA_EPETRA
615 #ifdef HAVE_XPETRA_TPETRA
618 Tpetra::Details::extractBlockDiagonal(At,Dt);
619 #endif // HAVE_XPETRA_TPETRA
631 #if defined(HAVE_XPETRA_EPETRA)
633 #endif // HAVE_XPETRA_EPETRA
635 #ifdef HAVE_XPETRA_TPETRA
636 const Tpetra::MultiVector<SC,LO,GO,NO> & Dt =
Xpetra::toTpetra(blockDiagonal);
638 Tpetra::Details::inverseScaleBlockDiagonal(Dt,doTranspose,St);
639 #endif // HAVE_XPETRA_TPETRA
648 #define XPETRA_MATRIXUTILS_SHORT
650 #endif // PACKAGES_XPETRA_SUP_MATRIX_UTILS_HPP_