47 #ifndef MUELU_HIERARCHY_DEF_HPP
48 #define MUELU_HIERARCHY_DEF_HPP
56 #include <Xpetra_MultiVectorFactory.hpp>
63 #include "MueLu_FactoryManager.hpp"
64 #include "MueLu_HierarchyUtils.hpp"
65 #include "MueLu_TopRAPFactory.hpp"
66 #include "MueLu_TopSmootherFactory.hpp"
69 #include "MueLu_PerfUtils.hpp"
70 #include "MueLu_PFactory.hpp"
72 #include "MueLu_SmootherFactory.hpp"
81 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
83 : maxCoarseSize_(GetDefaultMaxCoarseSize()), implicitTranspose_(GetDefaultImplicitTranspose()),
84 fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate()),
85 doPRrebalance_(GetDefaultPRrebalance()), isPreconditioner_(true), Cycle_(GetDefaultCycle()),
86 scalingFactor_(Teuchos::ScalarTraits<double>::one()), lib_(Xpetra::
UseTpetra), isDumpingEnabled_(false), dumpLevel_(-1), rate_(-1),
87 sizeOfAllocatedLevelMultiVectors_(0)
92 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
97 Levels_[0]->setObjectLabel(label);
100 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
102 : maxCoarseSize_(GetDefaultMaxCoarseSize()), implicitTranspose_(GetDefaultImplicitTranspose()),
103 fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate()),
104 doPRrebalance_(GetDefaultPRrebalance()), isPreconditioner_(true), Cycle_(GetDefaultCycle()),
105 scalingFactor_(Teuchos::ScalarTraits<double>::one()), isDumpingEnabled_(false), dumpLevel_(-1), rate_(-1),
106 sizeOfAllocatedLevelMultiVectors_(0)
108 lib_ = A->getDomainMap()->lib();
116 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
121 Levels_[0]->setObjectLabel(label);
124 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
126 int levelID = LastLevelID() + 1;
130 " have been added at the end of the hierarchy\n but its ID have been redefined" <<
131 " because last level ID of the hierarchy was " << LastLevelID() <<
"." << std::endl;
133 Levels_.push_back(level);
137 level->
SetPreviousLevel( (levelID == 0) ? Teuchos::null : Levels_[LastLevelID() - 1] );
141 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
143 RCP<Level> newLevel = Levels_[LastLevelID()]->Build();
145 this->AddLevel(newLevel);
148 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
151 "MueLu::Hierarchy::GetLevel(): invalid input parameter value: LevelID = " << levelID);
152 return Levels_[levelID];
155 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
157 return Levels_.size();
160 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
162 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator> >(
"A");
165 int numLevels = GetNumLevels();
169 return numGlobalLevels;
172 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
174 double totalNnz = 0, lev0Nnz = 1;
175 for (
int i = 0; i < GetNumLevels(); ++i) {
177 "Operator complexity cannot be calculated because A is unavailable on level " << i);
178 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator> >(
"A");
184 GetOStream(
Warnings0) <<
"Some level operators are not matrices, operator complexity calculation aborted" << std::endl;
188 totalNnz += as<double>(Am->getGlobalNumEntries());
192 return totalNnz / lev0Nnz;
195 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
197 double node_sc = 0, global_sc=0;
201 if (GetNumLevels() <= 0)
return -1.0;
202 if (!Levels_[0]->IsAvailable(
"A"))
return -1.0;
204 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator> >(
"A");
208 a0_nnz = as<double>(Am->getGlobalNumEntries());
211 for (
int i = 0; i < GetNumLevels(); ++i) {
213 if(!Levels_[i]->IsAvailable(
"PreSmoother"))
continue;
214 RCP<SmootherBase> S = Levels_[i]->template Get<RCP<SmootherBase> >(
"PreSmoother");
217 if(level_sc == INVALID) {global_sc=-1.0;
break;}
219 node_sc += as<double>(level_sc);
227 if(min_sc < 0.0)
return -1.0;
228 else return global_sc / a0_nnz;
235 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
238 "MueLu::Hierarchy::CheckLevel(): wrong underlying linear algebra library.");
240 "MueLu::Hierarchy::CheckLevel(): wrong level ID");
242 "MueLu::Hierarchy::Setup(): wrong level parent");
245 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
247 for (
int i = 0; i < GetNumLevels(); ++i) {
255 xpImporter->setDistributorParameters(matvecParams);
258 xpExporter->setDistributorParameters(matvecParams);
265 xpImporter->setDistributorParameters(matvecParams);
268 xpExporter->setDistributorParameters(matvecParams);
274 xpImporter->setDistributorParameters(matvecParams);
277 xpExporter->setDistributorParameters(matvecParams);
282 xpImporter->setDistributorParameters(matvecParams);
289 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
298 "MueLu::Hierarchy:Setup(): level " << coarseLevelID <<
" (specified by coarseLevelID argument) "
299 "must be built before calling this function.");
301 Level& level = *Levels_[coarseLevelID];
304 TimeMonitor m1(*
this, label + this->ShortClassName() +
": " +
"Setup (total)");
309 "MueLu::Hierarchy::Setup(): argument coarseLevelManager cannot be null");
314 if (levelManagers_.size() < coarseLevelID+1)
315 levelManagers_.resize(coarseLevelID+1);
316 levelManagers_[coarseLevelID] = coarseLevelManager;
318 bool isFinestLevel = (fineLevelManager.
is_null());
319 bool isLastLevel = (nextLevelManager.
is_null());
332 oldRank = SetProcRankVerbose(comm->getRank());
336 lib_ = domainMap->lib();
343 Level& prevLevel = *Levels_[coarseLevelID-1];
344 oldRank = SetProcRankVerbose(prevLevel.
GetComm()->getRank());
347 CheckLevel(level, coarseLevelID);
354 if (isFinestLevel && Levels_[coarseLevelID]->IsAvailable(
"Coordinates"))
355 ReplaceCoordinateMap(*Levels_[coarseLevelID]);
360 if (isDumpingEnabled_ && dumpLevel_ == 0 && coarseLevelID == 1)
366 int nextLevelID = coarseLevelID + 1;
369 if (isLastLevel ==
false) {
371 if (nextLevelID > LastLevelID())
373 CheckLevel(*Levels_[nextLevelID], nextLevelID);
377 Levels_[nextLevelID]->Request(TopRAPFactory(coarseLevelManager, nextLevelManager));
413 TopRAPFactory coarseRAPFactory(fineLevelManager, coarseLevelManager);
417 }
else if (!isFinestLevel) {
428 level.
SetComm(Ac->getDomainMap()->getComm());
431 bool isOrigLastLevel = isLastLevel;
443 if (!Acm.
is_null() && Acm->getGlobalNumRows() <= maxCoarseSize_) {
445 GetOStream(
Runtime0) <<
"Max coarse size (<= " << maxCoarseSize_ <<
") achieved" << std::endl;
450 if (!Ac.
is_null() && !isFinestLevel) {
451 RCP<Operator> A = Levels_[coarseLevelID-1]->template Get< RCP<Operator> >(
"A");
454 const double maxCoarse2FineRatio = 0.8;
455 if (!Acm.
is_null() && !Am.is_null() && Acm->getGlobalNumRows() > maxCoarse2FineRatio * Am->getGlobalNumRows()) {
463 GetOStream(
Warnings0) <<
"Aggregation stagnated. Please check your matrix and/or adjust your configuration file."
464 <<
"Possible fixes:\n"
465 <<
" - reduce the maximum number of levels\n"
466 <<
" - enable repartitioning\n"
467 <<
" - increase the minimum coarse size." << std::endl;
473 if (!isOrigLastLevel) {
483 coarseFact->
Build(level);
494 smootherFact->
Build(level);
499 if (isLastLevel ==
true) {
500 if (isOrigLastLevel ==
false) {
503 Levels_[nextLevelID]->Release(TopRAPFactory(coarseLevelManager, nextLevelManager));
505 Levels_.resize(nextLevelID);
509 if (isDumpingEnabled_ && dumpLevel_ > 0 && coarseLevelID == dumpLevel_)
512 if (!isFinestLevel) {
516 level.
Release(coarseRAPFactory);
520 SetProcRankVerbose(oldRank);
525 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
527 int numLevels = Levels_.size();
529 "Hierarchy::SetupRe: " << Levels_.size() <<
" levels, but " << levelManagers_.size() <<
" level factory managers");
531 const int startLevel = 0;
534 #ifdef HAVE_MUELU_DEBUG
536 for (
int i = 0; i < numLevels; i++)
537 levelManagers_[i]->ResetDebugData();
542 for (levelID = startLevel; levelID < numLevels;) {
543 bool r = Setup(levelID,
544 (levelID != 0 ? levelManagers_[levelID-1] : Teuchos::null),
545 levelManagers_[levelID],
546 (levelID+1 != numLevels ? levelManagers_[levelID+1] : Teuchos::null));
552 Levels_ .resize(levelID);
553 levelManagers_.resize(levelID);
565 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
574 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") does not exist");
577 "Constructing non-positive (" << numDesiredLevels <<
") number of levels does not make sense.");
580 TEUCHOS_TEST_FOR_EXCEPTION(!Levels_[startLevel]->IsAvailable(
"A"), Exceptions::RuntimeError,
581 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") has no matrix A! "
582 "Set fine level matrix A using Level.Set()");
584 RCP<Operator> A = Levels_[startLevel]->template Get<RCP<Operator> >(
"A");
585 lib_ = A->getDomainMap()->lib();
592 params->
set(
"printLoadBalancingInfo",
true);
593 params->
set(
"printCommInfo",
true);
597 GetOStream(
Warnings1) <<
"Fine level operator is not a matrix, statistics are not available" << std::endl;
603 const int lastLevel = startLevel + numDesiredLevels - 1;
604 GetOStream(
Runtime0) <<
"Setup loop: startLevel = " << startLevel <<
", lastLevel = " << lastLevel
605 <<
" (stop if numLevels = " << numDesiredLevels <<
" or Ac.size() < " << maxCoarseSize_ <<
")" << std::endl;
609 if (numDesiredLevels == 1) {
611 Setup(startLevel, Teuchos::null, rcpmanager, Teuchos::null);
614 bool bIsLastLevel = Setup(startLevel, Teuchos::null, rcpmanager, rcpmanager);
615 if (bIsLastLevel ==
false) {
616 for (iLevel = startLevel + 1; iLevel < lastLevel; iLevel++) {
617 bIsLastLevel = Setup(iLevel, rcpmanager, rcpmanager, rcpmanager);
618 if (bIsLastLevel ==
true)
621 if (bIsLastLevel ==
false)
622 Setup(lastLevel, rcpmanager, rcpmanager, Teuchos::null);
627 TEUCHOS_TEST_FOR_EXCEPTION(iLevel != Levels_.size() - 1, Exceptions::RuntimeError,
628 "MueLu::Hierarchy::Setup(): number of level");
637 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
639 if (startLevel < GetNumLevels())
640 GetOStream(
Runtime0) <<
"Clearing old data (if any)" << std::endl;
642 for (
int iLevel = startLevel; iLevel < GetNumLevels(); iLevel++)
643 Levels_[iLevel]->Clear();
646 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
648 GetOStream(
Runtime0) <<
"Clearing old data (expert)" << std::endl;
649 for (
int iLevel = 0; iLevel < GetNumLevels(); iLevel++)
650 Levels_[iLevel]->ExpertClear();
653 #if defined(HAVE_MUELU_EXPERIMENTAL) && defined(HAVE_MUELU_ADDITIVE_VARIANT)
654 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
656 bool InitialGuessIsZero,
LO startLevel) {
657 LO nIts = conv.maxIts_;
658 MagnitudeType tol = conv.tol_;
660 std::string prefix = this->ShortClassName() +
": ";
661 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
662 std::string levelSuffix1 =
" (level=" +
toString(startLevel+1) +
")";
664 using namespace Teuchos;
689 SC one = STS::one(), zero = STS::zero();
691 bool zeroGuess = InitialGuessIsZero;
702 bool emptyCoarseSolve =
true;
703 RCP<MultiVector> coarseX_prolonged = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
707 if (Levels_.size() > 1) {
709 if (Coarse->IsAvailable(
"Importer"))
719 coarseRhs = MultiVectorFactory::Build(R->getRangeMap(), B.getNumVectors(),
true);
728 if (doPRrebalance_ || importer.is_null()) {
729 coarseX = MultiVectorFactory::Build(coarseRhs->getMap(), X.getNumVectors(),
true);
737 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getTargetMap(), coarseRhs->getNumVectors());
739 coarseRhs.
swap(coarseTmp);
741 coarseX = MultiVectorFactory::Build(importer->getTargetMap(), X.getNumVectors(),
true);
744 if (Coarse->IsAvailable(
"PreSmoother"))
746 if (Coarse->IsAvailable(
"PostSmoother"))
753 MagnitudeType prevNorm = STS::magnitude(STS::one()), curNorm = STS::magnitude(STS::one());
756 for (
LO i = 1; i <= nIts; i++) {
757 #ifdef HAVE_MUELU_DEBUG
758 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
759 std::ostringstream ss;
760 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
761 throw Exceptions::Incompatible(ss.str());
764 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
765 std::ostringstream ss;
766 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
767 throw Exceptions::Incompatible(ss.str());
772 bool emptyFineSolve =
true;
775 fineX = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
784 if (Fine->IsAvailable(
"PreSmoother")) {
787 preSmoo->Apply(*fineX, B, zeroGuess);
789 emptyFineSolve =
false;
791 if (Fine->IsAvailable(
"PostSmoother")) {
794 postSmoo->Apply(*fineX, B, zeroGuess);
797 emptyFineSolve =
false;
799 if (emptyFineSolve ==
true) {
800 GetOStream(
Warnings1) <<
"No fine grid smoother" << std::endl;
802 fineX->update(one, B, zero);
805 if (Levels_.size() > 1) {
807 if (Coarse->IsAvailable(
"PreSmoother")) {
809 preSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
811 emptyCoarseSolve =
false;
814 if (Coarse->IsAvailable(
"PostSmoother")) {
816 postSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
818 emptyCoarseSolve =
false;
821 if (emptyCoarseSolve ==
true) {
822 GetOStream(
Warnings1) <<
"No coarse grid solver" << std::endl;
824 coarseX->update(one, *coarseRhs, zero);
831 if (!doPRrebalance_ && !importer.is_null()) {
836 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getSourceMap(), coarseX->getNumVectors());
838 coarseX.
swap(coarseTmp);
847 X.update(1.0, *fineX, 1.0, *coarseX_prolonged, 0.0);
858 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
860 bool InitialGuessIsZero,
LO startLevel) {
879 std::string prefix = label + this->ShortClassName() +
": ";
880 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
881 std::string levelSuffix1 =
" (level=" +
toString(startLevel+1) +
")";
889 else if (!useStackedTimer)
892 std::string iterateLevelTimeLabel = prefix +
"Solve" + levelSuffix;
895 bool zeroGuess = InitialGuessIsZero;
898 using namespace Teuchos;
912 const BlockedMultiVector * Bblocked =
dynamic_cast<const BlockedMultiVector*
>(&B);
913 if(residual_.size() > startLevel &&
914 ( ( Bblocked && !Bblocked->isSameSize(*residual_[startLevel])) ||
915 (!Bblocked && !residual_[startLevel]->isSameSize(B))))
916 DeleteLevelMultiVectors();
917 AllocateLevelMultiVectors(X.getNumVectors());
923 if (startLevel == 0 && !isPreconditioner_ &&
932 for (
LO k = 0; k < rn.
size(); k++)
942 << std::setiosflags(std::ios::left)
943 << std::setprecision(3) << 0
945 << std::setprecision(10) << rn
949 SC one = STS::one(), zero = STS::zero();
950 for (
LO i = 1; i <= nIts; i++) {
951 #ifdef HAVE_MUELU_DEBUG
953 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
954 std::ostringstream ss;
955 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
959 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
960 std::ostringstream ss;
961 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
967 if (startLevel == as<LO>(Levels_.size())-1) {
971 bool emptySolve =
true;
974 if (Fine->IsAvailable(
"PreSmoother")) {
977 preSmoo->Apply(X, B, zeroGuess);
982 if (Fine->IsAvailable(
"PostSmoother")) {
985 postSmoo->Apply(X, B, zeroGuess);
989 if (emptySolve ==
true) {
990 GetOStream(
Warnings1) <<
"No coarse grid solver" << std::endl;
992 X.update(one, B, zero);
1001 if (!useStackedTimer)
1005 if (Fine->IsAvailable(
"PreSmoother")) {
1007 preSmoo->Apply(X, B, zeroGuess);
1014 if (!useStackedTimer)
1018 residual = residual_[startLevel];
1022 if (Coarse->IsAvailable(
"Pbar"))
1030 if (!useStackedTimer)
1033 coarseRhs = coarseRhs_[startLevel];
1035 if (implicitTranspose_) {
1045 if (Coarse->IsAvailable(
"Importer"))
1048 coarseX = coarseX_[startLevel];
1049 if (!doPRrebalance_ && !importer.
is_null()) {
1051 if (!useStackedTimer)
1058 coarseRhs.
swap(coarseTmp);
1067 coarseRhs->replaceMap(Ac->getRangeMap());
1068 coarseX ->replaceMap(Ac->getDomainMap());
1071 iterateLevelTime = Teuchos::null;
1073 Iterate(*coarseRhs, *coarseX, 1,
true, startLevel+1);
1076 Iterate(*coarseRhs, *coarseX, 1,
false, startLevel+1);
1079 iterateLevelTime =
rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel));
1081 coarseX->replaceMap(origXMap);
1082 coarseRhs->replaceMap(origRhsMap);
1085 if (!doPRrebalance_ && !importer.
is_null()) {
1087 if (!useStackedTimer)
1094 coarseX.
swap(coarseTmp);
1100 if (!useStackedTimer)
1107 if (fuseProlongationAndUpdate_) {
1112 X.update(scalingFactor_, *correction, one);
1119 if (!useStackedTimer)
1123 if (Fine->IsAvailable(
"PostSmoother")) {
1125 postSmoo->Apply(X, B,
false);
1131 if (startLevel == 0 && !isPreconditioner_ &&
1140 rate_ = as<MagnitudeType>(curNorm / prevNorm);
1144 << std::setiosflags(std::ios::left)
1145 << std::setprecision(3) << i
1147 << std::setprecision(10) << rn
1152 for (
LO k = 0; k < rn.
size(); k++)
1166 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1168 LO startLevel = (start != -1 ? start : 0);
1169 LO endLevel = (end != -1 ? end : Levels_.size()-1);
1172 "MueLu::Hierarchy::Write : startLevel must be <= endLevel");
1175 "MueLu::Hierarchy::Write bad start or end level");
1177 for (
LO i = startLevel; i < endLevel + 1; i++) {
1178 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get< RCP< Operator> >(
"A")), P, R;
1180 P = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get< RCP< Operator> >(
"P"));
1181 if (!implicitTranspose_)
1182 R = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get< RCP< Operator> >(
"R"));
1195 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1197 for (
Array<
RCP<Level> >::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1198 (*it)->Keep(ename, factory);
1201 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1203 for (
Array<
RCP<Level> >::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1204 (*it)->Delete(ename, factory);
1207 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1209 for (
Array<
RCP<Level> >::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1210 (*it)->AddKeepFlag(ename, factory, keep);
1213 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1215 for (
Array<
RCP<Level> >::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1216 (*it)->RemoveKeepFlag(ename, factory, keep);
1219 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1221 if ( description_.empty() )
1223 std::ostringstream out;
1225 out <<
"{#levels = " << GetGlobalNumLevels() <<
", complexity = " << GetOperatorComplexity() <<
"}";
1226 description_ = out.str();
1228 return description_;
1231 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1236 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1238 RCP<Operator> A0 = Levels_[0]->template Get<RCP<Operator> >(
"A");
1241 int numLevels = GetNumLevels();
1242 RCP<Operator> Ac = Levels_[numLevels-1]->template Get<RCP<Operator> >(
"A");
1249 int root = comm->getRank();
1252 int smartData = numLevels*comm->getSize() + comm->getRank(), maxSmartData;
1254 root = maxSmartData % comm->getSize();
1258 double smoother_comp =-1.0;
1260 smoother_comp = GetSmootherComplexity();
1264 std::vector<Xpetra::global_size_t> nnzPerLevel;
1265 std::vector<Xpetra::global_size_t> rowsPerLevel;
1266 std::vector<int> numProcsPerLevel;
1267 bool aborted =
false;
1268 for (
int i = 0; i < numLevels; i++) {
1270 "Operator A is not available on level " << i);
1272 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator> >(
"A");
1274 "Operator A on level " << i <<
" is null.");
1278 GetOStream(
Warnings0) <<
"Some level operators are not matrices, statistics calculation aborted" << std::endl;
1284 nnzPerLevel .push_back(nnz);
1285 rowsPerLevel .push_back(Am->getGlobalNumRows());
1286 numProcsPerLevel.push_back(Am->getRowMap()->getComm()->getSize());
1290 std::string label = Levels_[0]->getObjectLabel();
1291 std::ostringstream oss;
1292 oss << std::setfill(
' ');
1293 oss <<
"\n--------------------------------------------------------------------------------\n";
1294 oss <<
"--- Multigrid Summary " << std::setw(28) << std::left << label <<
"---\n";
1295 oss <<
"--------------------------------------------------------------------------------" << std::endl;
1296 oss <<
"Number of levels = " << numLevels << std::endl;
1297 oss <<
"Operator complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1298 << GetOperatorComplexity() << std::endl;
1300 if(smoother_comp!=-1.0) {
1301 oss <<
"Smoother complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1302 << smoother_comp << std::endl;
1307 oss <<
"Cycle type = V" << std::endl;
1310 oss <<
"Cycle type = W" << std::endl;
1318 int rowspacer = 2;
while (tt != 0) { tt /= 10; rowspacer++; }
1319 tt = nnzPerLevel[0];
1320 int nnzspacer = 2;
while (tt != 0) { tt /= 10; nnzspacer++; }
1321 tt = numProcsPerLevel[0];
1322 int npspacer = 2;
while (tt != 0) { tt /= 10; npspacer++; }
1323 oss <<
"level " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " <<
" nnz/row" << std::setw(npspacer) <<
" c ratio" <<
" procs" << std::endl;
1324 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1325 oss <<
" " << i <<
" ";
1326 oss << std::setw(rowspacer) << rowsPerLevel[i];
1327 oss << std::setw(nnzspacer) << nnzPerLevel[i];
1328 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1329 oss << std::setw(9) << as<double>(nnzPerLevel[i]) / rowsPerLevel[i];
1330 if (i) oss << std::setw(9) << as<double>(rowsPerLevel[i-1])/rowsPerLevel[i];
1331 else oss << std::setw(9) <<
" ";
1332 oss <<
" " << std::setw(npspacer) << numProcsPerLevel[i] << std::endl;
1335 for (
int i = 0; i < GetNumLevels(); ++i) {
1337 if (Levels_[i]->IsAvailable(
"PreSmoother"))
1339 if (Levels_[i]->IsAvailable(
"PostSmoother"))
1342 if (preSmoo != null && preSmoo == postSmoo)
1343 oss <<
"Smoother (level " << i <<
") both : " << preSmoo->
description() << std::endl;
1345 oss <<
"Smoother (level " << i <<
") pre : "
1346 << (preSmoo != null ? preSmoo->
description() :
"no smoother") << std::endl;
1347 oss <<
"Smoother (level " << i <<
") post : "
1348 << (postSmoo != null ? postSmoo->
description() :
"no smoother") << std::endl;
1360 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1362 int strLength = outstr.size();
1363 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1364 if (comm->getRank() != root)
1365 outstr.resize(strLength);
1366 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1373 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1376 for (
int i = 0; i < GetNumLevels(); ++i)
1377 Levels_[i]->print(out, verbLevel);
1380 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1382 isPreconditioner_ = flag;
1385 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1387 if (GetProcRankVerbose() != 0)
1389 #if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
1393 dp.property(
"label", boost::get(boost::vertex_name, graph));
1394 dp.property(
"id", boost::get(boost::vertex_index, graph));
1395 dp.property(
"label", boost::get(boost::edge_name, graph));
1396 dp.property(
"color", boost::get(boost::edge_color, graph));
1399 std::map<const FactoryBase*, BoostVertex> vindices;
1400 typedef std::map<std::pair<BoostVertex,BoostVertex>, std::string> emap; emap edges;
1402 static int call_id=0;
1404 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator> >(
"A");
1405 int rank = A->getDomainMap()->getComm()->getRank();
1408 for (
int i = dumpLevel_; i <= dumpLevel_+1 && i < GetNumLevels(); i++) {
1410 Levels_[i]->UpdateGraph(vindices, edges, dp, graph);
1412 for (emap::const_iterator eit = edges.begin(); eit != edges.end(); eit++) {
1413 std::pair<BoostEdge, bool> boost_edge = boost::add_edge(eit->first.first, eit->first.second, graph);
1416 if(eit->second==std::string(
"Graph")) boost::put(
"label", dp, boost_edge.first, std::string(
"Graph_"));
1417 else boost::put(
"label", dp, boost_edge.first, eit->second);
1418 if (i == dumpLevel_)
1419 boost::put(
"color", dp, boost_edge.first, std::string(
"red"));
1421 boost::put(
"color", dp, boost_edge.first, std::string(
"blue"));
1426 std::ostringstream legend;
1427 legend <<
"< <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\"> \
1428 <TR><TD COLSPAN=\"2\">Legend</TD></TR> \
1429 <TR><TD><FONT color=\"red\">Level " << dumpLevel_ <<
"</FONT></TD><TD><FONT color=\"blue\">Level " << dumpLevel_+1 <<
"</FONT></TD></TR> \
1431 BoostVertex boost_vertex = boost::add_vertex(graph);
1432 boost::put(
"label", dp, boost_vertex, legend.str());
1435 std::ofstream out(dumpFile_.c_str() +std::to_string(call_id)+std::string(
"_")+ std::to_string(rank) + std::string(
".dot"));
1436 boost::write_graphviz_dp(out, graph, dp, std::string(
"id"));
1440 GetOStream(
Errors) <<
"Dependency graph output requires boost and MueLu_ENABLE_Boost_for_real" << std::endl;
1445 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1450 GetOStream(
Warnings1) <<
"Hierarchy::ReplaceCoordinateMap: operator is not a matrix, skipping..." << std::endl;
1453 if(Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A) != Teuchos::null) {
1454 GetOStream(
Warnings1) <<
"Hierarchy::ReplaceCoordinateMap: operator is a BlockedCrsMatrix, skipping..." << std::endl;
1462 if (A->getRowMap()->isSameAs(*(coords->getMap()))) {
1463 GetOStream(
Warnings1) <<
"Hierarchy::ReplaceCoordinateMap: matrix and coordinates maps are same, skipping..." << std::endl;
1467 if (A->IsView(
"stridedMaps") && rcp_dynamic_cast<
const StridedMap>(A->getRowMap(
"stridedMaps")) != Teuchos::null) {
1468 RCP<const StridedMap> stridedRowMap = rcp_dynamic_cast<
const StridedMap>(A->getRowMap(
"stridedMaps"));
1472 Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: nontrivial maps (block id = " << stridedRowMap->getStridedBlockId()
1473 <<
", offset = " << stridedRowMap->getOffset() <<
")");
1476 GetOStream(
Runtime1) <<
"Replacing coordinate map" << std::endl;
1478 size_t blkSize = A->GetFixedBlockSize();
1484 GO indexBase = dofMap->getIndexBase();
1485 size_t numLocalDOFs = dofMap->getNodeNumElements();
1487 "Hierarchy::ReplaceCoordinateMap: block size (" << blkSize <<
") is incompatible with the number of local dofs in a row map (" << numLocalDOFs);
1490 Array<GO> nodeGIDs(numLocalDOFs/blkSize);
1491 for (
size_t i = 0; i < numLocalDOFs; i += blkSize)
1492 nodeGIDs[i/blkSize] = (GIDs[i] - indexBase)/blkSize + indexBase;
1495 nodeMap = MapFactory::Build(dofMap->lib(), INVALID, nodeGIDs(), indexBase, dofMap->getComm());
1501 if(coords->getLocalLength() != A->getRowMap()->getNodeNumElements()) {
1502 GetOStream(
Warnings) <<
"Coordinate vector does not match row map of matrix A!" << std::endl;
1508 std::vector<ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> > coordData;
1509 for (
size_t i = 0; i < coords->getNumVectors(); i++) {
1510 coordData.
push_back(coords->getData(i));
1511 coordDataView.
push_back(coordData[i]());
1515 level.
Set(
"Coordinates", newCoords);
1518 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1520 int N = Levels_.size();
1521 if( (sizeOfAllocatedLevelMultiVectors_ == numvecs && residual_.size() == N) || numvecs<=0 )
return;
1524 if(residual_.size() != N) {
1525 DeleteLevelMultiVectors();
1527 residual_.resize(N);
1528 coarseRhs_.resize(N);
1530 coarseImport_.resize(N);
1531 coarseExport_.resize(N);
1532 correction_.resize(N);
1535 for(
int i=0; i<N; i++) {
1536 RCP<Operator> A = Levels_[i]->template Get< RCP<Operator> >(
"A");
1543 Adm = A_as_blocked->getFullDomainMap();
1547 residual_[i] = MultiVectorFactory::Build(Arm, numvecs,
true);
1548 correction_[i] = MultiVectorFactory::Build(Adm, numvecs,
false);
1553 if(implicitTranspose_) {
1554 RCP<Operator> P = Levels_[i+1]->template Get< RCP<Operator> >(
"P");
1555 if(!P.
is_null()) coarseRhs_[i] = MultiVectorFactory::Build(P->getDomainMap(),numvecs,
true);
1557 RCP<Operator> R = Levels_[i+1]->template Get< RCP<Operator> >(
"R");
1558 if(!R.
is_null()) coarseRhs_[i] = MultiVectorFactory::Build(R->getRangeMap(),numvecs,
true);
1563 if(Levels_[i+1]->IsAvailable(
"Importer"))
1565 if (doPRrebalance_ || importer.
is_null())
1566 coarseX_[i] = MultiVectorFactory::Build(coarseRhs_[i]->getMap(),numvecs,
false);
1568 coarseImport_[i] = MultiVectorFactory::Build(importer->getTargetMap(), numvecs,
false);
1569 coarseExport_[i] = MultiVectorFactory::Build(importer->getSourceMap(), numvecs,
false);
1570 coarseX_[i] = MultiVectorFactory::Build(importer->getTargetMap(),numvecs,
false);
1574 sizeOfAllocatedLevelMultiVectors_ = numvecs;
1578 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1580 if(sizeOfAllocatedLevelMultiVectors_==0)
return;
1581 residual_.resize(0);
1582 coarseRhs_.resize(0);
1584 coarseImport_.resize(0);
1585 coarseExport_.resize(0);
1586 correction_.resize(0);
1587 sizeOfAllocatedLevelMultiVectors_ = 0;
1593 #endif // MUELU_HIERARCHY_DEF_HPP
Important warning messages (one line)
void Build(Level &level) const
Build an object with this factory.
void IsPreconditioner(const bool flag)
RCP< Level > & GetPreviousLevel()
Previous level.
static Teuchos::RCP< Teuchos::StackedTimer > getStackedTimer()
static void SetRandomSeed(const Teuchos::Comm< int > &comm)
High level timing information (use Teuchos::TimeMonitor::summarize() to print)
virtual std::string getObjectLabel() const
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level->Get< RCP<Matrix> >("A", factory) if factory == NULL => use default factory.
RCP< Level > & GetLevel(const int levelID=0)
Retrieve a certain level from hierarchy.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
Hierarchy()
Default constructor.
virtual size_t getNodeSmootherComplexity() const =0
Compute a rough estimate of the cost to apply this smoother on this MPI rank. Return Teuchos::Ordinal...
void DeleteLevelMultiVectors()
void Release(const FactoryBase &factory)
Decrement the storage counter for all the inputs of a factory.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
void AddLevel(const RCP< Level > &level)
Add a level at the end of the hierarchy.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static void Write(const std::string &fileName, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &M)
void AddNewLevel()
Add a new level at the end of the hierarchy.
VerbLevel toMueLuVerbLevel(const Teuchos::EVerbosityLevel verbLevel)
void swap(RCP< T > &r_ptr)
One-liner description of what is happening.
virtual void Clean() const
void DumpCurrentGraph() const
void Clear(int startLevel=0)
Clear impermanent data from previous setup.
void SetPreviousLevel(const RCP< Level > &previousLevel)
Exception throws to report incompatible objects (like maps).
Integrates Teuchos::TimeMonitor with MueLu verbosity system.
void ReplaceCoordinateMap(Level &level)
void AllocateLevelMultiVectors(int numvecs)
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
Call Level::AddKeepFlag for each level of the Hierarchy.
Print even more statistics.
void setlib(Xpetra::UnderlyingLib lib2)
void print(std::ostream &out=std::cout, const VerbLevel verbLevel=(MueLu::Parameters|MueLu::Statistics0)) const
double GetSmootherComplexity() const
Base class for factories (e.g., R, P, and A_coarse).
Print statistics that do not involve significant additional computation.
Xpetra::UnderlyingLib lib_
static RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Residual(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &RHS)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void Write(const LO &start=-1, const LO &end=-1, const std::string &suffix="")
Print matrices in the multigrid hierarchy to file.
Class that holds all level-specific information.
std::string description() const
Return a simple one-line description of this object.
Class that provides default factories within Needs class.
void RemoveKeepFlag(const std::string &ename, const FactoryBase *factory, KeepType keep=MueLu::All)
Call Level::RemoveKeepFlag for each level of the Hierarchy.
void CheckLevel(Level &level, int levelID)
Helper function.
Xpetra::UnderlyingLib lib()
virtual void setObjectLabel(const std::string &objectLabel)
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
void SetMatvecParams(RCP< ParameterList > matvecParams)
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
int GetGlobalNumLevels() const
void push_back(const value_type &x)
Data struct for defining stopping criteria of multigrid iteration.
static Teuchos::Array< Magnitude > ResidualNorm(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &RHS)
void SetLevelID(int levelID)
Set level number.
STS::magnitudeType MagnitudeType
void Delete(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Call Level::Delete(ename, factory) for each level of the Hierarchy.
Timer to be used in non-factories.
Array< RCP< Level > > Levels_
Container for Level objects.
int GetLevelID() const
Return level number.
Exception throws to report errors in the internal logical of the program.
An exception safe way to call the method 'Level::SetFactoryManager()'.
void SetComm(RCP< const Teuchos::Comm< int > > const &comm)
void describe(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the Hierarchy with some verbosity level to a FancyOStream object.
Print all warning messages.
ReturnType Iterate(const MultiVector &B, MultiVector &X, ConvData conv=ConvData(), bool InitialGuessIsZero=false, LO startLevel=0)
Apply the multigrid preconditioner.
Description of what is happening (more verbose)
void Keep(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Call Level::Keep(ename, factory) for each level of the Hierarchy.
double GetOperatorComplexity() const
bool Setup(int coarseLevelID, const RCP< const FactoryManagerBase > fineLevelManager, const RCP< const FactoryManagerBase > coarseLevelManager, const RCP< const FactoryManagerBase > nextLevelManager=Teuchos::null)
Multi-level setup phase: build a new level of the hierarchy.
RCP< const Teuchos::Comm< int > > GetComm() const
virtual std::string description() const
Return a simple one-line description of this object.
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
std::string toString(const T &t)
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void Request(const FactoryBase &factory)
Increment the storage counter for all the inputs of a factory.