10 #ifndef MUELU_HIERARCHY_DEF_HPP
11 #define MUELU_HIERARCHY_DEF_HPP
19 #include <Xpetra_MultiVectorFactory.hpp>
25 #include "MueLu_FactoryManager.hpp"
26 #include "MueLu_HierarchyUtils.hpp"
27 #include "MueLu_TopRAPFactory.hpp"
28 #include "MueLu_TopSmootherFactory.hpp"
31 #include "MueLu_PerfUtils.hpp"
32 #include "MueLu_PFactory.hpp"
33 #include "MueLu_SmootherFactory.hpp"
40 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
42 : maxCoarseSize_(GetDefaultMaxCoarseSize())
43 , implicitTranspose_(GetDefaultImplicitTranspose())
44 , fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate())
45 , doPRrebalance_(GetDefaultPRrebalance())
46 , doPRViaCopyrebalance_(false)
47 , isPreconditioner_(true)
48 , Cycle_(GetDefaultCycle())
49 , WCycleStartLevel_(0)
50 , scalingFactor_(Teuchos::ScalarTraits<double>::one())
52 , isDumpingEnabled_(false)
55 , sizeOfAllocatedLevelMultiVectors_(0) {
59 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
64 Levels_[0]->setObjectLabel(label);
67 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
69 : maxCoarseSize_(GetDefaultMaxCoarseSize())
70 , implicitTranspose_(GetDefaultImplicitTranspose())
71 , fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate())
72 , doPRrebalance_(GetDefaultPRrebalance())
73 , doPRViaCopyrebalance_(false)
74 , isPreconditioner_(true)
75 , Cycle_(GetDefaultCycle())
76 , WCycleStartLevel_(0)
77 , scalingFactor_(Teuchos::ScalarTraits<double>::one())
78 , isDumpingEnabled_(false)
81 , sizeOfAllocatedLevelMultiVectors_(0) {
82 lib_ = A->getDomainMap()->lib();
90 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
94 Levels_[0]->setObjectLabel(label);
97 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
100 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
102 int levelID = LastLevelID() + 1;
105 GetOStream(
Warnings1) <<
"Hierarchy::AddLevel(): Level with ID=" << level->
GetLevelID() <<
" have been added at the end of the hierarchy\n but its ID have been redefined"
106 <<
" because last level ID of the hierarchy was " << LastLevelID() <<
"." << std::endl;
108 Levels_.push_back(level);
112 level->
SetPreviousLevel((levelID == 0) ? Teuchos::null : Levels_[LastLevelID() - 1]);
116 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
118 RCP<Level> newLevel = Levels_[LastLevelID()]->Build();
120 this->AddLevel(newLevel);
123 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
126 "MueLu::Hierarchy::GetLevel(): invalid input parameter value: LevelID = " << levelID);
127 return Levels_[levelID];
130 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
132 return Levels_.size();
135 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
137 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator>>(
"A");
140 int numLevels = GetNumLevels();
144 return numGlobalLevels;
147 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
149 double totalNnz = 0, lev0Nnz = 1;
150 for (
int i = 0; i < GetNumLevels(); ++i) {
152 "Operator complexity cannot be calculated because A is unavailable on level " << i);
153 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
159 GetOStream(
Warnings0) <<
"Some level operators are not matrices, operator complexity calculation aborted" << std::endl;
163 totalNnz += as<double>(Am->getGlobalNumEntries());
167 return totalNnz / lev0Nnz;
170 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
172 double node_sc = 0, global_sc = 0;
176 if (GetNumLevels() <= 0)
return -1.0;
177 if (!Levels_[0]->IsAvailable(
"A"))
return -1.0;
179 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator>>(
"A");
183 a0_nnz = as<double>(Am->getGlobalNumEntries());
186 for (
int i = 0; i < GetNumLevels(); ++i) {
188 if (!Levels_[i]->IsAvailable(
"PreSmoother"))
continue;
189 RCP<SmootherBase> S = Levels_[i]->template Get<RCP<SmootherBase>>(
"PreSmoother");
192 if (level_sc == INVALID) {
197 node_sc += as<double>(level_sc);
208 return global_sc / a0_nnz;
212 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
215 "MueLu::Hierarchy::CheckLevel(): wrong underlying linear algebra library.");
217 "MueLu::Hierarchy::CheckLevel(): wrong level ID");
219 "MueLu::Hierarchy::Setup(): wrong level parent");
222 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
224 for (
int i = 0; i < GetNumLevels(); ++i) {
232 xpImporter->setDistributorParameters(matvecParams);
235 xpExporter->setDistributorParameters(matvecParams);
242 xpImporter->setDistributorParameters(matvecParams);
245 xpExporter->setDistributorParameters(matvecParams);
251 xpImporter->setDistributorParameters(matvecParams);
254 xpExporter->setDistributorParameters(matvecParams);
259 xpImporter->setDistributorParameters(matvecParams);
266 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
275 "MueLu::Hierarchy:Setup(): level " << coarseLevelID <<
" (specified by coarseLevelID argument) "
276 "must be built before calling this function.");
278 Level& level = *Levels_[coarseLevelID];
280 bool useStackedTimer = !Teuchos::TimeMonitor::stackedTimerNameIsDefault();
284 if (!useStackedTimer)
285 m1 =
rcp(
new TimeMonitor(*
this, label + this->ShortClassName() +
": " +
"Setup (total)"));
290 "MueLu::Hierarchy::Setup(): argument coarseLevelManager cannot be null");
295 if (levelManagers_.size() < coarseLevelID + 1)
296 levelManagers_.resize(coarseLevelID + 1);
297 levelManagers_[coarseLevelID] = coarseLevelManager;
299 bool isFinestLevel = (fineLevelManager.
is_null());
300 bool isLastLevel = (nextLevelManager.
is_null());
313 oldRank = SetProcRankVerbose(comm->getRank());
317 lib_ = domainMap->lib();
324 Level& prevLevel = *Levels_[coarseLevelID - 1];
325 oldRank = SetProcRankVerbose(prevLevel.
GetComm()->getRank());
328 CheckLevel(level, coarseLevelID);
335 if (isFinestLevel && Levels_[coarseLevelID]->IsAvailable(
"Coordinates"))
336 ReplaceCoordinateMap(*Levels_[coarseLevelID]);
341 if (isDumpingEnabled_ && (dumpLevel_ == 0 || dumpLevel_ == -1) && coarseLevelID == 1)
347 int nextLevelID = coarseLevelID + 1;
350 if (isLastLevel ==
false) {
352 if (nextLevelID > LastLevelID())
354 CheckLevel(*Levels_[nextLevelID], nextLevelID);
358 Levels_[nextLevelID]->Request(TopRAPFactory(coarseLevelManager, nextLevelManager));
388 coarseFact =
rcp(
new TopSmootherFactory(coarseLevelManager,
"CoarseSolver"));
397 TopRAPFactory coarseRAPFactory(fineLevelManager, coarseLevelManager);
401 }
else if (!isFinestLevel) {
406 bool setLastLevelviaMaxCoarseSize =
false;
413 level.
SetComm(Ac->getDomainMap()->getComm());
416 bool isOrigLastLevel = isLastLevel;
428 if (!Acm.
is_null() && Acm->getGlobalNumRows() <= maxCoarseSize_) {
430 GetOStream(
Runtime0) <<
"Max coarse size (<= " << maxCoarseSize_ <<
") achieved" << std::endl;
432 if (Acm->getGlobalNumRows() != 0) setLastLevelviaMaxCoarseSize =
true;
436 if (!Ac.
is_null() && !isFinestLevel) {
437 RCP<Operator> A = Levels_[coarseLevelID - 1]->template Get<RCP<Operator>>(
"A");
440 const double maxCoarse2FineRatio = 0.8;
441 if (!Acm.
is_null() && !Am.is_null() && Acm->getGlobalNumRows() > maxCoarse2FineRatio * Am->getGlobalNumRows()) {
449 GetOStream(
Warnings0) <<
"Aggregation stagnated. Please check your matrix and/or adjust your configuration file."
450 <<
"Possible fixes:\n"
451 <<
" - reduce the maximum number of levels\n"
452 <<
" - enable repartitioning\n"
453 <<
" - increase the minimum coarse size." << std::endl;
458 if (!isOrigLastLevel) {
463 coarseFact =
rcp(
new TopSmootherFactory(coarseLevelManager,
"CoarseSolver"));
470 coarseFact->
Build(level);
481 smootherFact->
Build(level);
486 if (isLastLevel ==
true) {
487 int actualNumLevels = nextLevelID;
488 if (isOrigLastLevel ==
false) {
491 Levels_[nextLevelID]->Release(TopRAPFactory(coarseLevelManager, nextLevelManager));
497 if (!setLastLevelviaMaxCoarseSize) {
498 if (Levels_[nextLevelID - 1]->IsAvailable(
"P")) {
499 if (Levels_[nextLevelID - 1]->
template Get<
RCP<Matrix>>(
"P") == Teuchos::null) actualNumLevels = nextLevelID - 1;
501 actualNumLevels = nextLevelID - 1;
504 if (actualNumLevels == nextLevelID - 1) {
506 Levels_[nextLevelID - 2]->Release(*smootherFact);
508 if (Levels_[nextLevelID - 2]->IsAvailable(
"PreSmoother")) Levels_[nextLevelID - 2]->RemoveKeepFlag(
"PreSmoother",
NoFactory::get());
509 if (Levels_[nextLevelID - 2]->IsAvailable(
"PostSmoother")) Levels_[nextLevelID - 2]->RemoveKeepFlag(
"PostSmoother",
NoFactory::get());
511 coarseFact =
rcp(
new TopSmootherFactory(coarseLevelManager,
"CoarseSolver"));
512 Levels_[nextLevelID - 2]->Request(*coarseFact);
514 coarseFact->
Build(*(Levels_[nextLevelID - 2]));
515 Levels_[nextLevelID - 2]->Release(*coarseFact);
517 Levels_.resize(actualNumLevels);
521 if (isDumpingEnabled_ && ((dumpLevel_ > 0 && coarseLevelID == dumpLevel_) || dumpLevel_ == -1))
522 DumpCurrentGraph(coarseLevelID);
524 if (!isFinestLevel) {
528 level.
Release(coarseRAPFactory);
532 SetProcRankVerbose(oldRank);
537 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
539 int numLevels = Levels_.size();
541 "Hierarchy::SetupRe: " << Levels_.size() <<
" levels, but " << levelManagers_.size() <<
" level factory managers");
543 const int startLevel = 0;
546 #ifdef HAVE_MUELU_DEBUG
548 for (
int i = 0; i < numLevels; i++)
549 levelManagers_[i]->ResetDebugData();
554 for (levelID = startLevel; levelID < numLevels;) {
555 bool r = Setup(levelID,
556 (levelID != 0 ? levelManagers_[levelID - 1] : Teuchos::null),
557 levelManagers_[levelID],
558 (levelID + 1 != numLevels ? levelManagers_[levelID + 1] : Teuchos::null));
564 Levels_.resize(levelID);
565 levelManagers_.resize(levelID);
567 int sizeOfVecs = sizeOfAllocatedLevelMultiVectors_;
569 AllocateLevelMultiVectors(sizeOfVecs,
true);
576 CheckForEmptySmoothersAndCoarseSolve();
579 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
588 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") does not exist");
591 "Constructing non-positive (" << numDesiredLevels <<
") number of levels does not make sense.");
594 TEUCHOS_TEST_FOR_EXCEPTION(!Levels_[startLevel]->IsAvailable(
"A"), Exceptions::RuntimeError,
595 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") has no matrix A! "
596 "Set fine level matrix A using Level.Set()");
598 RCP<Operator> A = Levels_[startLevel]->template Get<RCP<Operator>>(
"A");
599 lib_ = A->getDomainMap()->lib();
606 params->
set(
"printLoadBalancingInfo",
true);
607 params->
set(
"printCommInfo",
true);
611 GetOStream(
Warnings1) <<
"Fine level operator is not a matrix, statistics are not available" << std::endl;
617 const int lastLevel = startLevel + numDesiredLevels - 1;
618 GetOStream(
Runtime0) <<
"Setup loop: startLevel = " << startLevel <<
", lastLevel = " << lastLevel
619 <<
" (stop if numLevels = " << numDesiredLevels <<
" or Ac.size() < " << maxCoarseSize_ <<
")" << std::endl;
623 if (numDesiredLevels == 1) {
625 Setup(startLevel, Teuchos::null, rcpmanager, Teuchos::null);
628 bool bIsLastLevel = Setup(startLevel, Teuchos::null, rcpmanager, rcpmanager);
629 if (bIsLastLevel ==
false) {
630 for (iLevel = startLevel + 1; iLevel < lastLevel; iLevel++) {
631 bIsLastLevel = Setup(iLevel, rcpmanager, rcpmanager, rcpmanager);
632 if (bIsLastLevel ==
true)
635 if (bIsLastLevel ==
false)
636 Setup(lastLevel, rcpmanager, rcpmanager, Teuchos::null);
641 TEUCHOS_TEST_FOR_EXCEPTION(iLevel != Levels_.size() - 1, Exceptions::RuntimeError,
642 "MueLu::Hierarchy::Setup(): number of level");
650 CheckForEmptySmoothersAndCoarseSolve();
653 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
655 for (
LO levelNo = 0; levelNo < GetNumLevels(); ++levelNo) {
656 auto level = Levels_[levelNo];
657 if ((level->IsAvailable(
"A") && !level->template Get<RCP<Operator>>(
"A").
is_null()) && (!level->IsAvailable(
"PreSmoother")) && (!level->IsAvailable(
"PostSmoother"))) {
658 GetOStream(
Warnings1) <<
"No " << (levelNo == as<LO>(Levels_.size()) - 1 ?
"coarse grid solver" :
"smoother") <<
" on level " << level->GetLevelID() << std::endl;
663 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
665 if (startLevel < GetNumLevels())
666 GetOStream(
Runtime0) <<
"Clearing old data (if any)" << std::endl;
668 for (
int iLevel = startLevel; iLevel < GetNumLevels(); iLevel++)
669 Levels_[iLevel]->Clear();
672 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
674 GetOStream(
Runtime0) <<
"Clearing old data (expert)" << std::endl;
675 for (
int iLevel = 0; iLevel < GetNumLevels(); iLevel++)
676 Levels_[iLevel]->ExpertClear();
679 #if defined(HAVE_MUELU_EXPERIMENTAL) && defined(HAVE_MUELU_ADDITIVE_VARIANT)
680 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
682 bool InitialGuessIsZero,
LO startLevel) {
683 LO nIts = conv.maxIts_;
684 MagnitudeType tol = conv.tol_;
686 std::string prefix = this->ShortClassName() +
": ";
687 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
688 std::string levelSuffix1 =
" (level=" +
toString(startLevel + 1) +
")";
690 using namespace Teuchos;
714 SC one = STS::one(), zero = STS::zero();
716 bool zeroGuess = InitialGuessIsZero;
727 bool emptyCoarseSolve =
true;
728 RCP<MultiVector> coarseX_prolonged = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
732 if (Levels_.size() > 1) {
734 if (Coarse->IsAvailable(
"Importer"))
743 coarseRhs = MultiVectorFactory::Build(R->getRangeMap(), B.getNumVectors(),
true);
752 if (doPRrebalance_ || importer.is_null()) {
753 coarseX = MultiVectorFactory::Build(coarseRhs->getMap(), X.getNumVectors(),
true);
760 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getTargetMap(), coarseRhs->getNumVectors());
762 coarseRhs.
swap(coarseTmp);
764 coarseX = MultiVectorFactory::Build(importer->getTargetMap(), X.getNumVectors(),
true);
767 if (Coarse->IsAvailable(
"PreSmoother"))
769 if (Coarse->IsAvailable(
"PostSmoother"))
775 MagnitudeType prevNorm = STS::magnitude(STS::one()), curNorm = STS::magnitude(STS::one());
778 for (
LO i = 1; i <= nIts; i++) {
779 #ifdef HAVE_MUELU_DEBUG
780 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
781 std::ostringstream ss;
782 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
783 throw Exceptions::Incompatible(ss.str());
786 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
787 std::ostringstream ss;
788 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
789 throw Exceptions::Incompatible(ss.str());
794 bool emptyFineSolve =
true;
797 fineX = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
806 if (Fine->IsAvailable(
"PreSmoother")) {
809 preSmoo->Apply(*fineX, B, zeroGuess);
811 emptyFineSolve =
false;
813 if (Fine->IsAvailable(
"PostSmoother")) {
816 postSmoo->Apply(*fineX, B, zeroGuess);
819 emptyFineSolve =
false;
821 if (emptyFineSolve ==
true) {
823 fineX->update(one, B, zero);
826 if (Levels_.size() > 1) {
828 if (Coarse->IsAvailable(
"PreSmoother")) {
830 preSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
832 emptyCoarseSolve =
false;
834 if (Coarse->IsAvailable(
"PostSmoother")) {
836 postSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
838 emptyCoarseSolve =
false;
840 if (emptyCoarseSolve ==
true) {
842 coarseX->update(one, *coarseRhs, zero);
849 if (!doPRrebalance_ && !importer.is_null()) {
854 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getSourceMap(), coarseX->getNumVectors());
856 coarseX.
swap(coarseTmp);
865 X.update(1.0, *fineX, 1.0, *coarseX_prolonged, 0.0);
876 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
878 bool InitialGuessIsZero,
LO startLevel) {
897 std::string prefix = label + this->ShortClassName() +
": ";
898 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
899 std::string levelSuffix1 =
" (level=" +
toString(startLevel + 1) +
")";
901 bool useStackedTimer = !Teuchos::TimeMonitor::stackedTimerNameIsDefault();
907 else if (!useStackedTimer)
910 std::string iterateLevelTimeLabel = prefix +
"Solve" + levelSuffix;
913 bool zeroGuess = InitialGuessIsZero;
916 using namespace Teuchos;
930 const BlockedMultiVector* Bblocked =
dynamic_cast<const BlockedMultiVector*
>(&B);
931 if (residual_.size() > startLevel &&
932 ((Bblocked && !Bblocked->isSameSize(*residual_[startLevel])) ||
933 (!Bblocked && !residual_[startLevel]->isSameSize(B))))
934 DeleteLevelMultiVectors();
935 AllocateLevelMultiVectors(X.getNumVectors());
941 if (IsCalculationOfResidualRequired(startLevel, conv)) {
944 return convergenceStatus;
947 SC one = STS::one(), zero = STS::zero();
948 for (
LO iteration = 1; iteration <= nIts; iteration++) {
949 #ifdef HAVE_MUELU_DEBUG
951 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
952 std::ostringstream ss;
953 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
957 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
958 std::ostringstream ss;
959 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
965 if (startLevel == as<LO>(Levels_.size()) - 1) {
969 bool emptySolve =
true;
972 if (Fine->IsAvailable(
"PreSmoother")) {
975 preSmoo->Apply(X, B, zeroGuess);
980 if (Fine->IsAvailable(
"PostSmoother")) {
983 postSmoo->Apply(X, B, zeroGuess);
988 if (emptySolve ==
true) {
990 X.update(one, B, zero);
999 if (!useStackedTimer)
1003 if (Fine->IsAvailable(
"PreSmoother")) {
1005 preSmoo->Apply(X, B, zeroGuess);
1013 if (!useStackedTimer)
1023 residual = residual_[startLevel];
1027 if (Coarse->IsAvailable(
"Pbar"))
1035 if (!useStackedTimer)
1038 coarseRhs = coarseRhs_[startLevel];
1040 if (implicitTranspose_) {
1050 if (Coarse->IsAvailable(
"Importer"))
1053 coarseX = coarseX_[startLevel];
1054 if (!doPRrebalance_ && !importer.
is_null()) {
1056 if (!useStackedTimer)
1063 coarseRhs.
swap(coarseTmp);
1072 coarseRhs->replaceMap(Ac->getRangeMap());
1073 coarseX->replaceMap(Ac->getDomainMap());
1076 iterateLevelTime = Teuchos::null;
1078 Iterate(*coarseRhs, *coarseX, 1,
true, startLevel + 1);
1080 if (Cycle_ ==
WCYCLE && WCycleStartLevel_ >= startLevel)
1081 Iterate(*coarseRhs, *coarseX, 1,
false, startLevel + 1);
1084 iterateLevelTime =
rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel));
1086 coarseX->replaceMap(origXMap);
1087 coarseRhs->replaceMap(origRhsMap);
1090 if (!doPRrebalance_ && !importer.
is_null()) {
1092 if (!useStackedTimer)
1099 coarseX.
swap(coarseTmp);
1105 if (!useStackedTimer)
1112 if (fuseProlongationAndUpdate_) {
1117 X.update(scalingFactor_, *correction, one);
1124 if (!useStackedTimer)
1128 if (Fine->IsAvailable(
"PostSmoother")) {
1130 postSmoo->Apply(X, B,
false);
1136 if (IsCalculationOfResidualRequired(startLevel, conv)) {
1137 ConvergenceStatus convergenceStatus = ComputeResidualAndPrintHistory(*A, X, B, iteration, startLevel, conv, prevNorm);
1139 return convergenceStatus;
1146 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1148 LO startLevel = (start != -1 ? start : 0);
1149 LO endLevel = (end != -1 ? end : Levels_.size() - 1);
1152 "MueLu::Hierarchy::Write : startLevel must be <= endLevel");
1155 "MueLu::Hierarchy::Write bad start or end level");
1157 for (
LO i = startLevel; i < endLevel + 1; i++) {
1158 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Levels_[i]->template Get<RCP<Operator>>(
"A")), P, R;
1160 P = rcp_dynamic_cast<Matrix>(Levels_[i]->template Get<RCP<Operator>>(
"P"));
1161 if (!implicitTranspose_)
1162 R = rcp_dynamic_cast<Matrix>(Levels_[i]->template Get<RCP<Operator>>(
"R"));
1175 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1177 for (
Array<
RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1178 (*it)->Keep(ename, factory);
1181 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1183 for (
Array<
RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1184 (*it)->Delete(ename, factory);
1187 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1189 for (
Array<
RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1190 (*it)->AddKeepFlag(ename, factory, keep);
1193 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1195 for (
Array<
RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1196 (*it)->RemoveKeepFlag(ename, factory, keep);
1199 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1201 if (description_.empty()) {
1202 std::ostringstream out;
1204 out <<
"{#levels = " << GetGlobalNumLevels() <<
", complexity = " << GetOperatorComplexity() <<
"}";
1205 description_ = out.str();
1207 return description_;
1210 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1215 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1217 RCP<Operator> A0 = Levels_[0]->template Get<RCP<Operator>>(
"A");
1220 int numLevels = GetNumLevels();
1221 RCP<Operator> Ac = Levels_[numLevels - 1]->template Get<RCP<Operator>>(
"A");
1228 int root = comm->getRank();
1231 int smartData = numLevels * comm->getSize() + comm->getRank(), maxSmartData;
1233 root = maxSmartData % comm->getSize();
1237 double smoother_comp = -1.0;
1239 smoother_comp = GetSmootherComplexity();
1243 std::vector<Xpetra::global_size_t> nnzPerLevel;
1244 std::vector<Xpetra::global_size_t> rowsPerLevel;
1245 std::vector<int> numProcsPerLevel;
1246 bool someOpsNotMatrices =
false;
1248 for (
int i = 0; i < numLevels; i++) {
1250 "Operator A is not available on level " << i);
1252 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
1254 "Operator A on level " << i <<
" is null.");
1258 someOpsNotMatrices =
true;
1259 nnzPerLevel.push_back(INVALID);
1260 rowsPerLevel.push_back(A->getDomainMap()->getGlobalNumElements());
1261 numProcsPerLevel.push_back(A->getDomainMap()->getComm()->getSize());
1263 LO storageblocksize = Am->GetStorageBlockSize();
1265 nnzPerLevel.push_back(nnz);
1266 rowsPerLevel.push_back(Am->getGlobalNumRows() * storageblocksize);
1267 numProcsPerLevel.push_back(Am->getRowMap()->getComm()->getSize());
1270 if (someOpsNotMatrices)
1271 GetOStream(
Warnings0) <<
"Some level operators are not matrices, statistics calculation are incomplete" << std::endl;
1274 std::string label = Levels_[0]->getObjectLabel();
1275 std::ostringstream oss;
1276 oss << std::setfill(
' ');
1277 oss <<
"\n--------------------------------------------------------------------------------\n";
1278 oss <<
"--- Multigrid Summary " << std::setw(32) <<
"---\n";
1279 oss <<
"--------------------------------------------------------------------------------" << std::endl;
1280 if (hierarchyLabel_ !=
"") oss <<
"Label = " << hierarchyLabel_ << std::endl;
1283 oss <<
"Number of levels = " << numLevels << std::endl;
1284 oss <<
"Operator complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1285 if (!someOpsNotMatrices)
1286 oss << GetOperatorComplexity() << std::endl;
1288 oss <<
"not available (Some operators in hierarchy are not matrices.)" << std::endl;
1290 if (smoother_comp != -1.0) {
1291 oss <<
"Smoother complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1292 << smoother_comp << std::endl;
1297 oss <<
"Cycle type = V" << std::endl;
1300 oss <<
"Cycle type = W" << std::endl;
1301 if (WCycleStartLevel_ > 0)
1302 oss <<
"Cycle start level = " << WCycleStartLevel_ << std::endl;
1315 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1316 tt = nnzPerLevel[i];
1326 tt = numProcsPerLevel[0];
1332 oss <<
"level " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz "
1333 <<
" nnz/row" << std::setw(npspacer) <<
" c ratio"
1334 <<
" procs" << std::endl;
1335 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1336 oss <<
" " << i <<
" ";
1337 oss << std::setw(rowspacer) << rowsPerLevel[i];
1338 if (nnzPerLevel[i] != INVALID) {
1339 oss << std::setw(nnzspacer) << nnzPerLevel[i];
1340 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1341 oss << std::setw(9) << as<double>(nnzPerLevel[i]) / rowsPerLevel[i];
1343 oss << std::setw(nnzspacer) <<
"Operator";
1344 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1345 oss << std::setw(9) <<
" ";
1348 oss << std::setw(9) << as<double>(rowsPerLevel[i - 1]) / rowsPerLevel[i];
1350 oss << std::setw(9) <<
" ";
1351 oss <<
" " << std::setw(npspacer) << numProcsPerLevel[i] << std::endl;
1354 for (
int i = 0; i < GetNumLevels(); ++i) {
1356 if (Levels_[i]->IsAvailable(
"PreSmoother"))
1358 if (Levels_[i]->IsAvailable(
"PostSmoother"))
1361 if (preSmoo != null && preSmoo == postSmoo)
1362 oss <<
"Smoother (level " << i <<
") both : " << preSmoo->
description() << std::endl;
1364 oss <<
"Smoother (level " << i <<
") pre : "
1365 << (preSmoo != null ? preSmoo->
description() :
"no smoother") << std::endl;
1366 oss <<
"Smoother (level " << i <<
") post : "
1367 << (postSmoo != null ? postSmoo->
description() :
"no smoother") << std::endl;
1379 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1381 int strLength = outstr.size();
1382 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1383 if (comm->getRank() != root)
1384 outstr.resize(strLength);
1385 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1392 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1395 for (
int i = 0; i < GetNumLevels(); ++i)
1396 Levels_[i]->print(out, verbLevel);
1399 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1401 isPreconditioner_ = flag;
1404 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1406 if (GetProcRankVerbose() != 0)
1408 #if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
1413 dp.property(
"label", boost::get(boost::vertex_name, graph));
1414 dp.property(
"id", boost::get(boost::vertex_index, graph));
1415 dp.property(
"label", boost::get(boost::edge_name, graph));
1416 dp.property(
"color", boost::get(boost::edge_color, graph));
1419 std::map<const FactoryBase*, BoostVertex> vindices;
1420 typedef std::map<std::pair<BoostVertex, BoostVertex>, std::string> emap;
1423 static int call_id = 0;
1425 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator>>(
"A");
1426 int rank = A->getDomainMap()->getComm()->getRank();
1429 for (
int i = currLevel; i <= currLevel + 1 && i < GetNumLevels(); i++) {
1431 Levels_[i]->UpdateGraph(vindices, edges, dp, graph);
1433 for (emap::const_iterator eit = edges.begin(); eit != edges.end(); eit++) {
1434 std::pair<BoostEdge, bool> boost_edge = boost::add_edge(eit->first.first, eit->first.second, graph);
1437 if (eit->second == std::string(
"Graph"))
1438 boost::put(
"label", dp, boost_edge.first, std::string(
"Graph_"));
1440 boost::put(
"label", dp, boost_edge.first, eit->second);
1442 boost::put(
"color", dp, boost_edge.first, std::string(
"red"));
1444 boost::put(
"color", dp, boost_edge.first, std::string(
"blue"));
1448 std::ofstream out(dumpFile_.c_str() + std::string(
"_") + std::to_string(currLevel) + std::string(
"_") + std::to_string(call_id) + std::string(
"_") + std::to_string(rank) + std::string(
".dot"));
1449 boost::write_graphviz_dp(out, graph, dp, std::string(
"id"));
1453 GetOStream(
Errors) <<
"Dependency graph output requires boost and MueLu_ENABLE_Boost_for_real" << std::endl;
1458 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1463 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is not a matrix, skipping..." << std::endl;
1466 if (Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A) != Teuchos::null) {
1467 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is a BlockedCrsMatrix, skipping..." << std::endl;
1475 if (A->getRowMap()->isSameAs(*(coords->getMap()))) {
1476 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: matrix and coordinates maps are same, skipping..." << std::endl;
1480 if (A->IsView(
"stridedMaps") && rcp_dynamic_cast<
const StridedMap>(A->getRowMap(
"stridedMaps")) != Teuchos::null) {
1481 RCP<const StridedMap> stridedRowMap = rcp_dynamic_cast<
const StridedMap>(A->getRowMap(
"stridedMaps"));
1485 Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: nontrivial maps (block id = " << stridedRowMap->getStridedBlockId() <<
", offset = " << stridedRowMap->getOffset() <<
")");
1488 GetOStream(
Runtime1) <<
"Replacing coordinate map" << std::endl;
1491 size_t blkSize = A->GetFixedBlockSize() / A->GetStorageBlockSize();
1497 GO indexBase = dofMap->getIndexBase();
1498 size_t numLocalDOFs = dofMap->getLocalNumElements();
1500 "Hierarchy::ReplaceCoordinateMap: block size (" << blkSize <<
") is incompatible with the number of local dofs in a row map (" << numLocalDOFs);
1503 Array<GO> nodeGIDs(numLocalDOFs / blkSize);
1504 for (
size_t i = 0; i < numLocalDOFs; i += blkSize)
1505 nodeGIDs[i / blkSize] = (GIDs[i] - indexBase) / blkSize + indexBase;
1508 nodeMap = MapFactory::Build(dofMap->lib(), INVALID, nodeGIDs(), indexBase, dofMap->getComm());
1514 if (coords->getLocalLength() != A->getRowMap()->getLocalNumElements()) {
1515 GetOStream(
Warnings) <<
"Coordinate vector does not match row map of matrix A!" << std::endl;
1521 std::vector<ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType>> coordData;
1522 for (
size_t i = 0; i < coords->getNumVectors(); i++) {
1523 coordData.
push_back(coords->getData(i));
1524 coordDataView.
push_back(coordData[i]());
1528 level.
Set(
"Coordinates", newCoords);
1531 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1533 int N = Levels_.size();
1534 if (((sizeOfAllocatedLevelMultiVectors_ == numvecs && residual_.size() == N) || numvecs <= 0) && !forceMapCheck)
return;
1537 if (residual_.size() != N) {
1538 DeleteLevelMultiVectors();
1540 residual_.resize(N);
1541 coarseRhs_.resize(N);
1543 coarseImport_.resize(N);
1544 coarseExport_.resize(N);
1545 correction_.resize(N);
1548 for (
int i = 0; i < N; i++) {
1549 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
1555 if (!A_as_blocked.
is_null()) {
1556 Adm = A_as_blocked->getFullDomainMap();
1559 if (residual_[i].
is_null() || !residual_[i]->getMap()->isSameAs(*Arm))
1561 residual_[i] = MultiVectorFactory::Build(Arm, numvecs,
true);
1562 if (correction_[i].
is_null() || !correction_[i]->getMap()->isSameAs(*Adm))
1563 correction_[i] = MultiVectorFactory::Build(Adm, numvecs,
false);
1568 if (implicitTranspose_) {
1569 RCP<Operator> P = Levels_[i + 1]->template Get<RCP<Operator>>(
"P");
1572 if (coarseRhs_[i].
is_null() || !coarseRhs_[i]->getMap()->isSameAs(*map))
1573 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1576 RCP<Operator> R = Levels_[i + 1]->template Get<RCP<Operator>>(
"R");
1579 if (coarseRhs_[i].
is_null() || !coarseRhs_[i]->getMap()->isSameAs(*map))
1580 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1585 if (Levels_[i + 1]->IsAvailable(
"Importer"))
1586 importer = Levels_[i + 1]->template Get<RCP<const Import>>(
"Importer");
1587 if (doPRrebalance_ || importer.
is_null()) {
1589 if (coarseX_[i].
is_null() || !coarseX_[i]->getMap()->isSameAs(*map))
1590 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1593 map = importer->getTargetMap();
1594 if (coarseImport_[i].
is_null() || !coarseImport_[i]->getMap()->isSameAs(*map)) {
1595 coarseImport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1596 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1598 map = importer->getSourceMap();
1599 if (coarseExport_[i].
is_null() || !coarseExport_[i]->getMap()->isSameAs(*map))
1600 coarseExport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1604 sizeOfAllocatedLevelMultiVectors_ = numvecs;
1607 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1609 if (sizeOfAllocatedLevelMultiVectors_ == 0)
return;
1610 residual_.resize(0);
1611 coarseRhs_.resize(0);
1613 coarseImport_.resize(0);
1614 coarseExport_.resize(0);
1615 correction_.resize(0);
1616 sizeOfAllocatedLevelMultiVectors_ = 0;
1619 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1621 const LO startLevel,
const ConvData& conv)
const {
1622 return (startLevel == 0 && !isPreconditioner_ && (IsPrint(
Statistics1) || conv.
tol_ > 0));
1625 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1632 for (
LO k = 0; k < residualNorm.
size(); k++)
1633 if (residualNorm[k] >= convergenceTolerance)
1642 return convergenceStatus;
1645 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1649 << std::setiosflags(std::ios::left)
1650 << std::setprecision(3) << std::setw(4) << iteration
1652 << std::setprecision(10) << residualNorm
1656 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1658 const Operator& A,
const MultiVector& X,
const MultiVector& B,
const LO iteration,
1664 rate_ = currentResidualNorm / previousResidualNorm;
1665 previousResidualNorm = currentResidualNorm;
1668 PrintResidualHistory(iteration, residualNorm);
1670 return IsConverged(residualNorm, conv.
tol_);
1675 #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)
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.
bool is_null(const boost::shared_ptr< T > &p)
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.
void AddLevel(const RCP< Level > &level)
Add a level at the end of the hierarchy.
void CheckForEmptySmoothersAndCoarseSolve()
void PrintResidualHistory(const LO iteration, const Teuchos::Array< MagnitudeType > &residualNorm) const
Print residualNorm for this iteration to the screen.
#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 DumpCurrentGraph(int level) const
void AddNewLevel()
Add a new level at the end of the hierarchy.
VerbLevel toMueLuVerbLevel(const Teuchos::EVerbosityLevel verbLevel)
Translate Teuchos verbosity level to MueLu verbosity level.
void swap(RCP< T > &r_ptr)
One-liner description of what is happening.
virtual void Clean() const
void Clear(int startLevel=0)
Clear impermanent data from previous setup.
void SetPreviousLevel(const RCP< Level > &previousLevel)
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Exception throws to report incompatible objects (like maps).
static void SetRandomSeed(const Teuchos::Comm< int > &comm)
Set seed for random number generator.
Integrates Teuchos::TimeMonitor with MueLu verbosity system.
static std::string name()
static const NoFactory * get()
ConvergenceStatus Iterate(const MultiVector &B, MultiVector &X, ConvData conv=ConvData(), bool InitialGuessIsZero=false, LO startLevel=0)
Apply the multigrid preconditioner.
void ReplaceCoordinateMap(Level &level)
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
Hierarchy::print is local hierarchy function, thus the statistics can be different from global ones...
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_
Epetra/Tpetra mode.
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const MultiVector &X, const MultiVector &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)
void AllocateLevelMultiVectors(int numvecs, bool forceMapCheck=false)
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 SetLabel(const std::string &hierarchyLabel)
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)
RCP< Level > & GetPreviousLevel()
Previous level.
static Teuchos::Array< Magnitude > ResidualNorm(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const MultiVector &X, const MultiVector &RHS)
Data struct for defining stopping criteria of multigrid iteration.
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.
bool IsCalculationOfResidualRequired(const LO startLevel, const ConvData &conv) const
Decide if the residual needs to be computed.
int GetLevelID() const
Return level number.
Print class parameters (more parameters, more verbose)
virtual ~Hierarchy()
Destructor.
void residual(const Operator< SC, LO, GO, NO > &Aop, const MultiVector< SC, LO, GO, NO > &X_in, const MultiVector< SC, LO, GO, NO > &B_in, MultiVector< SC, LO, GO, NO > &R_in)
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.
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.
ConvergenceStatus IsConverged(const Teuchos::Array< MagnitudeType > &residualNorm, const MagnitudeType convergenceTolerance) const
Decide if the multigrid iteration is converged.
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
ConvergenceStatus ComputeResidualAndPrintHistory(const Operator &A, const MultiVector &X, const MultiVector &B, const LO iteration, const LO startLevel, const ConvData &conv, MagnitudeType &previousResidualNorm)
Compute the residual norm and print it depending on the verbosity level.
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.