10#ifndef MUELU_HIERARCHY_DEF_HPP
11#define MUELU_HIERARCHY_DEF_HPP
19#include <Xpetra_Matrix.hpp>
20#include <Xpetra_MultiVectorFactory.hpp>
21#include <Xpetra_Operator.hpp>
22#include <Xpetra_IO.hpp>
26#include "MueLu_FactoryManager.hpp"
27#include "MueLu_HierarchyUtils.hpp"
28#include "MueLu_TopRAPFactory.hpp"
29#include "MueLu_TopSmootherFactory.hpp"
32#include "MueLu_PerfUtils.hpp"
33#include "MueLu_PFactory.hpp"
34#include "MueLu_SmootherFactory.hpp"
38#include "Teuchos_TimeMonitor.hpp"
42template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
61template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
65 setObjectLabel(label);
66 Levels_[0]->setObjectLabel(label);
69template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
84 lib_ = A->getDomainMap()->
lib();
86 RCP<Level> Finest = rcp(
new Level);
92template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
95 setObjectLabel(label);
96 Levels_[0]->setObjectLabel(label);
99template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
102template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
106 if (level->GetLevelID() != -1 && (level->GetLevelID() != levelID))
107 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"
108 <<
" because last level ID of the hierarchy was " <<
LastLevelID() <<
"." << std::endl;
111 level->SetLevelID(levelID);
115 level->setObjectLabel(this->getObjectLabel());
118template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
121 newLevel->setlib(
lib_);
125template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
128 "MueLu::Hierarchy::GetLevel(): invalid input parameter value: LevelID = " << levelID);
132template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
137template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
139 RCP<Operator> A =
Levels_[0]->template Get<RCP<Operator>>(
"A");
140 RCP<const Teuchos::Comm<int>> comm = A->getDomainMap()->getComm();
144 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, numLevels, Teuchos::ptr(&numGlobalLevels));
146 return numGlobalLevels;
149template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
151 double totalNnz = 0, lev0Nnz = 1;
154 "Operator complexity cannot be calculated because A is unavailable on level " << i);
155 RCP<Operator> A =
Levels_[i]->template Get<RCP<Operator>>(
"A");
159 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
161 GetOStream(
Warnings0) <<
"Some level operators are not matrices, operator complexity calculation aborted" << std::endl;
165 if (!Am->haveGlobalConstants()) {
166 GetOStream(
Warnings0) <<
"Some level operators are do not have global constants computed, operator complexity calculation aborted" << std::endl;
170 totalNnz += as<double>(Am->getGlobalNumEntries());
174 return totalNnz / lev0Nnz;
177template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
179 double node_sc = 0, global_sc = 0;
181 const size_t INVALID = Teuchos::OrdinalTraits<size_t>::invalid();
184 if (!
Levels_[0]->IsAvailable(
"A"))
return -1.0;
186 RCP<Operator> A =
Levels_[0]->template Get<RCP<Operator>>(
"A");
187 if (A.is_null())
return -1.0;
188 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
189 if (Am.is_null())
return -1.0;
190 if (!Am->haveGlobalConstants())
return -1.0;
191 a0_nnz = as<double>(Am->getGlobalNumEntries());
196 if (!
Levels_[i]->IsAvailable(
"PreSmoother"))
continue;
197 RCP<SmootherBase> S =
Levels_[i]->template Get<RCP<SmootherBase>>(
"PreSmoother");
198 if (S.is_null())
continue;
199 level_sc = S->getNodeSmootherComplexity();
200 if (level_sc == INVALID) {
205 node_sc += as<double>(level_sc);
209 RCP<const Teuchos::Comm<int>> comm = A->getDomainMap()->getComm();
210 Teuchos::reduceAll(*comm, Teuchos::REDUCE_SUM, node_sc, Teuchos::ptr(&global_sc));
211 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MIN, node_sc, Teuchos::ptr(&min_sc));
216 return global_sc / a0_nnz;
220template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
223 "MueLu::Hierarchy::CheckLevel(): wrong underlying linear algebra library.");
225 "MueLu::Hierarchy::CheckLevel(): wrong level ID");
227 "MueLu::Hierarchy::Setup(): wrong level parent");
230template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
234 if (level->IsAvailable(
"A")) {
235 RCP<Operator> Aop = level->Get<RCP<Operator>>(
"A");
236 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Aop);
238 RCP<const Import> xpImporter = A->getCrsGraph()->getImporter();
239 if (!xpImporter.is_null())
240 xpImporter->setDistributorParameters(matvecParams);
241 RCP<const Export> xpExporter = A->getCrsGraph()->getExporter();
242 if (!xpExporter.is_null())
243 xpExporter->setDistributorParameters(matvecParams);
246 const std::list<std::string> matrices = {
"P",
"R",
"D0",
"NodeMatrix"};
247 for (
auto it = matrices.begin(); it != matrices.end(); ++it) {
248 if (level->IsAvailable(*it)) {
249 RCP<Matrix> mat = level->Get<RCP<Matrix>>(*it);
250 if (!mat.is_null()) {
251 RCP<const Import> xpImporter = mat->getCrsGraph()->getImporter();
252 if (!xpImporter.is_null()) {
253 xpImporter->setDistributorParameters(matvecParams);
255 RCP<const Export> xpExporter = mat->getCrsGraph()->getExporter();
256 if (!xpExporter.is_null())
257 xpExporter->setDistributorParameters(matvecParams);
261 if (level->IsAvailable(
"Importer")) {
262 RCP<const Import> xpImporter = level->Get<RCP<const Import>>(
"Importer");
263 if (!xpImporter.is_null())
264 xpImporter->setDistributorParameters(matvecParams);
271template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
273 const RCP<const FactoryManagerBase> fineLevelManager,
274 const RCP<const FactoryManagerBase> coarseLevelManager,
275 const RCP<const FactoryManagerBase> nextLevelManager) {
280 "MueLu::Hierarchy:Setup(): level " << coarseLevelID <<
" (specified by coarseLevelID argument) "
281 "must be built before calling this function.");
286 TimeMonitor m2(*
this, label + this->
ShortClassName() +
": " +
"Setup" +
" (total, level=" + Teuchos::toString(coarseLevelID) +
")");
290 "MueLu::Hierarchy::Setup(): argument coarseLevelManager cannot be null");
299 bool isFinestLevel = (fineLevelManager.is_null());
300 bool isLastLevel = (nextLevelManager.is_null());
304 RCP<Operator> A = level.
Get<RCP<Operator>>(
"A");
305 RCP<const Map> domainMap = A->getDomainMap();
306 RCP<const Teuchos::Comm<int>> comm = domainMap->getComm();
317 lib_ = domainMap->lib();
331 RCP<SetFactoryManager> SFMFine;
335 if (isFinestLevel &&
Levels_[coarseLevelID]->IsAvailable(
"Coordinates"))
344 RCP<TopSmootherFactory> coarseFact;
345 RCP<TopSmootherFactory> smootherFact = rcp(
new TopSmootherFactory(coarseLevelManager,
"Smoother"));
347 int nextLevelID = coarseLevelID + 1;
349 RCP<SetFactoryManager> SFMNext;
350 if (isLastLevel ==
false) {
387 if (coarseFact.is_null())
396 RCP<Operator> Ac = Teuchos::null;
397 TopRAPFactory coarseRAPFactory(fineLevelManager, coarseLevelManager);
400 Ac = level.
Get<RCP<Operator>>(
"A");
401 }
else if (!isFinestLevel) {
406 bool setLastLevelviaMaxCoarseSize =
false;
408 Ac = level.
Get<RCP<Operator>>(
"A");
409 RCP<Matrix> Acm = rcp_dynamic_cast<Matrix>(Ac);
413 level.
SetComm(Ac->getDomainMap()->getComm());
416 bool isOrigLastLevel = isLastLevel;
421 }
else if (Ac.is_null()) {
428 if (!Acm.is_null() && Acm->getGlobalNumRows() <=
maxCoarseSize_) {
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");
438 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(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) {
462 if (coarseFact.is_null())
470 coarseFact->Build(level);
481 smootherFact->Build(level);
486 if (isLastLevel ==
true) {
487 int actualNumLevels = nextLevelID;
488 if (isOrigLastLevel ==
false) {
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);
510 if (coarseFact.is_null())
512 Levels_[nextLevelID - 2]->Request(*coarseFact);
513 if (!(
Levels_[nextLevelID - 2]->
template Get<RCP<Matrix>>(
"A").is_null()))
514 coarseFact->Build(*(
Levels_[nextLevelID - 2]));
515 Levels_[nextLevelID - 2]->Release(*coarseFact);
517 Levels_.resize(actualNumLevels);
525 if (!isFinestLevel) {
529 level.
Release(coarseRAPFactory);
538template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
540 int numLevels =
Levels_.size();
542 "Hierarchy::SetupRe: " <<
Levels_.size() <<
" levels, but " <<
levelManagers_.size() <<
" level factory managers");
544 const int startLevel = 0;
547#ifdef HAVE_MUELU_DEBUG
549 for (
int i = 0; i < numLevels; i++)
555 for (levelID = startLevel; levelID < numLevels;) {
556 bool r =
Setup(levelID,
559 (levelID + 1 != numLevels ?
levelManagers_[levelID + 1] : Teuchos::null));
580template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
589 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") does not exist");
592 "Constructing non-positive (" << numDesiredLevels <<
") number of levels does not make sense.");
596 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") has no matrix A! "
597 "Set fine level matrix A using Level.Set()");
599 RCP<Operator> A =
Levels_[startLevel]->template Get<RCP<Operator>>(
"A");
600 lib_ = A->getDomainMap()->lib();
603 RCP<Matrix> Amat = rcp_dynamic_cast<Matrix>(A);
605 if (!Amat.is_null()) {
606 RCP<ParameterList> params = rcp(
new ParameterList());
607 params->set(
"printLoadBalancingInfo",
true);
608 params->set(
"printCommInfo",
true);
612 GetOStream(
Warnings1) <<
"Fine level operator is not a matrix, statistics are not available" << std::endl;
616 RCP<const FactoryManagerBase> rcpmanager = rcpFromRef(manager);
618 const int lastLevel = startLevel + numDesiredLevels - 1;
619 GetOStream(
Runtime0) <<
"Setup loop: startLevel = " << startLevel <<
", lastLevel = " << lastLevel
620 <<
" (stop if numLevels = " << numDesiredLevels <<
" or Ac.size() < " <<
maxCoarseSize_ <<
")" << std::endl;
624 if (numDesiredLevels == 1) {
626 Setup(startLevel, Teuchos::null, rcpmanager, Teuchos::null);
629 bool bIsLastLevel =
Setup(startLevel, Teuchos::null, rcpmanager, rcpmanager);
630 if (bIsLastLevel ==
false) {
631 for (iLevel = startLevel + 1; iLevel < lastLevel; iLevel++) {
632 bIsLastLevel =
Setup(iLevel, rcpmanager, rcpmanager, rcpmanager);
633 if (bIsLastLevel ==
true)
636 if (bIsLastLevel ==
false)
637 Setup(lastLevel, rcpmanager, rcpmanager, Teuchos::null);
643 "MueLu::Hierarchy::Setup(): number of level");
654template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
656 for (LO levelNo = 0; levelNo <
GetNumLevels(); ++levelNo) {
658 if ((level->IsAvailable(
"A") && !level->template Get<RCP<Operator>>(
"A").is_null()) && (!level->IsAvailable(
"PreSmoother")) && (!level->IsAvailable(
"PostSmoother"))) {
659 GetOStream(
Warnings1) <<
"No " << (levelNo == as<LO>(
Levels_.size()) - 1 ?
"coarse grid solver" :
"smoother") <<
" on level " << level->GetLevelID() << std::endl;
664template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
669 for (
int iLevel = startLevel; iLevel <
GetNumLevels(); iLevel++)
673template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
680#if defined(HAVE_MUELU_EXPERIMENTAL) && defined(HAVE_MUELU_ADDITIVE_VARIANT)
681template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
683 bool InitialGuessIsZero, LO startLevel) {
684 LO nIts = conv.maxIts_;
685 MagnitudeType tol = conv.tol_;
687 std::string prefix = this->ShortClassName() +
": ";
688 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
689 std::string levelSuffix1 =
" (level=" +
toString(startLevel + 1) +
")";
692 RCP<Time> CompTime = Teuchos::TimeMonitor::getNewCounter(prefix +
"Computational Time (total)");
693 RCP<Time> Concurrent = Teuchos::TimeMonitor::getNewCounter(prefix +
"Concurrent portion");
694 RCP<Time> ApplyR = Teuchos::TimeMonitor::getNewCounter(prefix +
"R: Computational Time");
695 RCP<Time> ApplyPbar = Teuchos::TimeMonitor::getNewCounter(prefix +
"Pbar: Computational Time");
696 RCP<Time> CompFine = Teuchos::TimeMonitor::getNewCounter(prefix +
"Fine: Computational Time");
697 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
698 RCP<Time> ApplySum = Teuchos::TimeMonitor::getNewCounter(prefix +
"Sum: Computational Time");
699 RCP<Time> Synchronize_beginning = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_beginning");
700 RCP<Time> Synchronize_center = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_center");
701 RCP<Time> Synchronize_end = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_end");
703 RCP<Level> Fine = Levels_[0];
706 RCP<Operator> A = Fine->Get<RCP<Operator>>(
"A");
707 Teuchos::RCP<const Teuchos::Comm<int>> communicator = A->getDomainMap()->getComm();
715 SC one = STS::one(), zero = STS::zero();
717 bool zeroGuess = InitialGuessIsZero;
725 RCP<MultiVector> coarseRhs, coarseX;
727 RCP<SmootherBase> preSmoo_coarse, postSmoo_coarse;
728 bool emptyCoarseSolve =
true;
729 RCP<MultiVector> coarseX_prolonged = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
731 RCP<const Import> importer;
733 if (Levels_.size() > 1) {
735 if (Coarse->IsAvailable(
"Importer"))
736 importer = Coarse->Get<RCP<const Import>>(
"Importer");
738 R = Coarse->Get<RCP<Operator>>(
"R");
739 P = Coarse->Get<RCP<Operator>>(
"P");
742 Pbar = Coarse->Get<RCP<Operator>>(
"Pbar");
744 coarseRhs = MultiVectorFactory::Build(R->getRangeMap(), B.getNumVectors(),
true);
746 Ac = Coarse->Get<RCP<Operator>>(
"A");
749 R->apply(B, *coarseRhs, Teuchos::NO_TRANS, one, zero);
753 if (doPRrebalance_ || importer.is_null()) {
754 coarseX = MultiVectorFactory::Build(coarseRhs->getMap(), X.getNumVectors(),
true);
757 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import (total)",
Timings0));
758 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
761 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getTargetMap(), coarseRhs->getNumVectors());
762 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
763 coarseRhs.swap(coarseTmp);
765 coarseX = MultiVectorFactory::Build(importer->getTargetMap(), X.getNumVectors(),
true);
768 if (Coarse->IsAvailable(
"PreSmoother"))
769 preSmoo_coarse = Coarse->Get<RCP<SmootherBase>>(
"PreSmoother");
770 if (Coarse->IsAvailable(
"PostSmoother"))
771 postSmoo_coarse = Coarse->Get<RCP<SmootherBase>>(
"PostSmoother");
776 MagnitudeType prevNorm = STS::magnitude(STS::one()), curNorm = STS::magnitude(STS::one());
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";
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";
793 bool emptyFineSolve =
true;
795 RCP<MultiVector> fineX;
796 fineX = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
805 if (Fine->IsAvailable(
"PreSmoother")) {
806 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
808 preSmoo->Apply(*fineX, B, zeroGuess);
810 emptyFineSolve =
false;
812 if (Fine->IsAvailable(
"PostSmoother")) {
813 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
815 postSmoo->Apply(*fineX, B, zeroGuess);
818 emptyFineSolve =
false;
820 if (emptyFineSolve ==
true) {
822 fineX->update(one, B, zero);
825 if (Levels_.size() > 1) {
827 if (Coarse->IsAvailable(
"PreSmoother")) {
829 preSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
831 emptyCoarseSolve =
false;
833 if (Coarse->IsAvailable(
"PostSmoother")) {
835 postSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
837 emptyCoarseSolve =
false;
839 if (emptyCoarseSolve ==
true) {
841 coarseX->update(one, *coarseRhs, zero);
848 if (!doPRrebalance_ && !importer.is_null()) {
849 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export (total)",
Timings0));
850 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
853 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getSourceMap(), coarseX->getNumVectors());
854 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
855 coarseX.swap(coarseTmp);
859 Pbar->apply(*coarseX, *coarseX_prolonged, Teuchos::NO_TRANS, one, zero);
864 X.update(1.0, *fineX, 1.0, *coarseX_prolonged, 0.0);
875template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
877 bool InitialGuessIsZero, LO startLevel) {
893 RCP<Level> Fine =
Levels_[startLevel];
897 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
898 std::string levelSuffix1 =
" (level=" +
toString(startLevel + 1) +
")";
900 RCP<Monitor> iterateTime;
901 RCP<TimeMonitor> iterateTime1;
905 std::string iterateLevelTimeLabel = prefix +
"Solve" + levelSuffix;
906 RCP<TimeMonitor> iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel,
Timings0));
908 bool zeroGuess = InitialGuessIsZero;
910 RCP<Operator> A = Fine->Get<RCP<Operator>>(
"A");
912 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
925 const BlockedMultiVector* Bblocked =
dynamic_cast<const BlockedMultiVector*
>(&B);
927 ((Bblocked && !Bblocked->isSameSize(*
residual_[startLevel])) ||
928 (!Bblocked && !
residual_[startLevel]->isSameSize(B))))
933 typedef Teuchos::ScalarTraits<typename STS::magnitudeType> STM;
939 return convergenceStatus;
942 SC one = STS::one(), zero = STS::zero();
943 for (LO iteration = 1; iteration <= nIts; iteration++) {
944#ifdef HAVE_MUELU_DEBUG
946 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
947 std::ostringstream ss;
948 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
952 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
953 std::ostringstream ss;
954 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
960 if (startLevel == as<LO>(
Levels_.size()) - 1) {
962 RCP<TimeMonitor> CLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : coarse" + levelSuffix,
Timings0));
964 bool emptySolve =
true;
967 if (Fine->IsAvailable(
"PreSmoother")) {
968 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
970 preSmoo->Apply(X, B, zeroGuess);
975 if (Fine->IsAvailable(
"PostSmoother")) {
976 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
978 postSmoo->Apply(X, B, zeroGuess);
983 if (emptySolve ==
true) {
985 X.update(one, B, zero);
990 RCP<Level> Coarse =
Levels_[startLevel + 1];
993 RCP<TimeMonitor> STime;
994 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
996 if (Fine->IsAvailable(
"PreSmoother")) {
997 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
998 preSmoo->Apply(X, B, zeroGuess);
1003 RCP<MultiVector> residual;
1005 RCP<TimeMonitor> ATime;
1006 RCP<TimeMonitor> ALevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : residual calculation" + levelSuffix,
Timings0));
1017 RCP<Operator> P = Coarse->Get<RCP<Operator>>(
"P");
1018 if (Coarse->IsAvailable(
"Pbar"))
1019 P = Coarse->Get<RCP<Operator>>(
"Pbar");
1021 RCP<MultiVector> coarseRhs, coarseX;
1025 RCP<TimeMonitor> RTime;
1026 RCP<TimeMonitor> RLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : restriction" + levelSuffix,
Timings0));
1030 P->apply(*residual, *coarseRhs, Teuchos::TRANS, one, zero);
1033 RCP<Operator> R = Coarse->Get<RCP<Operator>>(
"R");
1034 R->apply(*residual, *coarseRhs, Teuchos::NO_TRANS, one, zero);
1038 RCP<const Import> importer;
1039 if (Coarse->IsAvailable(
"Importer"))
1040 importer = Coarse->Get<RCP<const Import>>(
"Importer");
1044 RCP<TimeMonitor> ITime;
1045 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
1049 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
1050 coarseRhs.swap(coarseTmp);
1053 RCP<Operator> Ac = Coarse->Get<RCP<Operator>>(
"A");
1054 if (!Ac.is_null()) {
1055 RCP<const Map> origXMap = coarseX->getMap();
1056 RCP<const Map> origRhsMap = coarseRhs->getMap();
1059 coarseRhs->replaceMap(Ac->getRangeMap());
1060 coarseX->replaceMap(Ac->getDomainMap());
1063 iterateLevelTime = Teuchos::null;
1065 Iterate(*coarseRhs, *coarseX, 1,
true, startLevel + 1);
1068 Iterate(*coarseRhs, *coarseX, 1,
false, startLevel + 1);
1071 iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel));
1073 coarseX->replaceMap(origXMap);
1074 coarseRhs->replaceMap(origRhsMap);
1078 RCP<TimeMonitor> ITime;
1079 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
1083 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
1084 coarseX.swap(coarseTmp);
1089 RCP<TimeMonitor> PTime;
1090 RCP<TimeMonitor> PLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : prolongation" + levelSuffix,
Timings0));
1098 RCP<MultiVector> correction =
correction_[startLevel];
1099 P->apply(*coarseX, *correction, Teuchos::NO_TRANS, one, zero);
1106 RCP<TimeMonitor> STime;
1107 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1109 if (Fine->IsAvailable(
"PostSmoother")) {
1110 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
1111 postSmoo->Apply(X, B,
false);
1120 return convergenceStatus;
1127template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1129 LO startLevel = (start != -1 ? start : 0);
1130 LO endLevel = (end != -1 ? end :
Levels_.size() - 1);
1133 "MueLu::Hierarchy::Write : startLevel must be <= endLevel");
1136 "MueLu::Hierarchy::Write bad start or end level");
1138 for (LO i = startLevel; i < endLevel + 1; i++) {
1139 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(
Levels_[i]->
template Get<RCP<Operator>>(
"A")), P, R;
1141 P = rcp_dynamic_cast<Matrix>(
Levels_[i]->
template Get<RCP<Operator>>(
"P"));
1143 R = rcp_dynamic_cast<Matrix>(
Levels_[i]->
template Get<RCP<Operator>>(
"R"));
1146 if (!A.is_null()) Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"A_" +
toString(i) + suffix +
".m", *A);
1148 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"P_" +
toString(i) + suffix +
".m", *P);
1151 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"R_" +
toString(i) + suffix +
".m", *R);
1156template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1158 for (Array<RCP<Level>>::iterator it =
Levels_.begin(); it !=
Levels_.end(); ++it)
1159 (*it)->Keep(ename, factory);
1162template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1164 for (Array<RCP<Level>>::iterator it =
Levels_.begin(); it !=
Levels_.end(); ++it)
1165 (*it)->Delete(ename, factory);
1168template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1170 for (Array<RCP<Level>>::iterator it =
Levels_.begin(); it !=
Levels_.end(); ++it)
1171 (*it)->AddKeepFlag(ename, factory, keep);
1174template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1176 for (Array<RCP<Level>>::iterator it =
Levels_.begin(); it !=
Levels_.end(); ++it)
1177 (*it)->RemoveKeepFlag(ename, factory, keep);
1180template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1183 std::ostringstream out;
1191template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1196template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1198 RCP<Operator> A0 =
Levels_[0]->template Get<RCP<Operator>>(
"A");
1199 RCP<const Teuchos::Comm<int>> comm = A0->getDomainMap()->getComm();
1202 RCP<Operator> Ac =
Levels_[numLevels - 1]->template Get<RCP<Operator>>(
"A");
1209 int root = comm->getRank();
1212 int smartData = numLevels * comm->getSize() + comm->getRank(), maxSmartData;
1213 reduceAll(*comm, Teuchos::REDUCE_MAX, smartData, Teuchos::ptr(&maxSmartData));
1214 root = maxSmartData % comm->getSize();
1218 double smoother_comp = -1.0;
1224 std::vector<Xpetra::global_size_t> nnzPerLevel;
1225 std::vector<Xpetra::global_size_t> rowsPerLevel;
1226 std::vector<int> numProcsPerLevel;
1227 bool someOpsNotMatrices =
false;
1228 const Xpetra::global_size_t OPERATOR = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1229 const Xpetra::global_size_t UNAVAILABLE = Teuchos::OrdinalTraits<Xpetra::global_size_t>::max();
1230 for (
int i = 0; i < numLevels; i++) {
1232 "Operator A is not available on level " << i);
1234 RCP<Operator> A =
Levels_[i]->template Get<RCP<Operator>>(
"A");
1236 "Operator A on level " << i <<
" is null.");
1238 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
1240 someOpsNotMatrices =
true;
1241 nnzPerLevel.push_back(OPERATOR);
1242 rowsPerLevel.push_back(A->getDomainMap()->getGlobalNumElements());
1243 numProcsPerLevel.push_back(A->getDomainMap()->getComm()->getSize());
1245 LO storageblocksize = Am->GetStorageBlockSize();
1246 if (Am->haveGlobalConstants()) {
1247 Xpetra::global_size_t nnz = Am->getGlobalNumEntries() * storageblocksize * storageblocksize;
1248 nnzPerLevel.push_back(nnz);
1250 nnzPerLevel.push_back(UNAVAILABLE);
1251 rowsPerLevel.push_back(Am->getGlobalNumRows() * storageblocksize);
1252 numProcsPerLevel.push_back(Am->getRowMap()->getComm()->getSize());
1255 if (someOpsNotMatrices)
1256 GetOStream(
Warnings0) <<
"Some level operators are not matrices, statistics calculation are incomplete" << std::endl;
1259 std::string label =
Levels_[0]->getObjectLabel();
1260 std::ostringstream oss;
1261 oss << std::setfill(
' ');
1262 oss <<
"\n--------------------------------------------------------------------------------\n";
1263 oss <<
"--- Multigrid Summary " << std::setw(32) <<
"---\n";
1264 oss <<
"--------------------------------------------------------------------------------" << std::endl;
1267 oss <<
"Scalar = " << Teuchos::ScalarTraits<Scalar>::name() << std::endl;
1268 oss <<
"Number of levels = " << numLevels << std::endl;
1269 oss <<
"Operator complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1270 if (!someOpsNotMatrices)
1273 oss <<
"not available (Some operators in hierarchy are not matrices.)" << std::endl;
1275 if (smoother_comp != -1.0) {
1276 oss <<
"Smoother complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1277 << smoother_comp << std::endl;
1282 oss <<
"Cycle type = V" << std::endl;
1285 oss <<
"Cycle type = W" << std::endl;
1294 Xpetra::global_size_t tt = rowsPerLevel[0];
1300 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1301 tt = nnzPerLevel[i];
1302 if ((tt != OPERATOR) && (tt != UNAVAILABLE))
1311 tt = numProcsPerLevel[0];
1317 oss <<
"level " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz "
1318 <<
" nnz/row" << std::setw(npspacer) <<
" c ratio"
1319 <<
" procs" << std::endl;
1320 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1321 oss <<
" " << i <<
" ";
1322 oss << std::setw(rowspacer) << rowsPerLevel[i];
1323 if ((nnzPerLevel[i] != OPERATOR) && (nnzPerLevel[i] != UNAVAILABLE)) {
1324 oss << std::setw(nnzspacer) << nnzPerLevel[i];
1325 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1326 oss << std::setw(9) << as<double>(nnzPerLevel[i]) / rowsPerLevel[i];
1328 if (nnzPerLevel[i] == OPERATOR)
1329 oss << std::setw(nnzspacer) <<
"Operator";
1331 oss << std::setw(nnzspacer) <<
"N/A";
1332 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1333 oss << std::setw(9) <<
" ";
1336 oss << std::setw(9) << as<double>(rowsPerLevel[i - 1]) / rowsPerLevel[i];
1338 oss << std::setw(9) <<
" ";
1339 oss <<
" " << std::setw(npspacer) << numProcsPerLevel[i] << std::endl;
1343 RCP<SmootherBase> preSmoo, postSmoo;
1344 if (
Levels_[i]->IsAvailable(
"PreSmoother"))
1345 preSmoo =
Levels_[i]->template Get<RCP<SmootherBase>>(
"PreSmoother");
1346 if (
Levels_[i]->IsAvailable(
"PostSmoother"))
1347 postSmoo =
Levels_[i]->template Get<RCP<SmootherBase>>(
"PostSmoother");
1349 if (preSmoo != null && preSmoo == postSmoo)
1350 oss <<
"Smoother (level " << i <<
") both : " << preSmoo->description() << std::endl;
1352 oss <<
"Smoother (level " << i <<
") pre : "
1353 << (preSmoo != null ? preSmoo->description() :
"no smoother") << std::endl;
1354 oss <<
"Smoother (level " << i <<
") post : "
1355 << (postSmoo != null ? postSmoo->description() :
"no smoother") << std::endl;
1366 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
1367 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1369 int strLength = outstr.size();
1370 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1371 if (comm->getRank() != root)
1372 outstr.resize(strLength);
1373 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1380template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1382 Teuchos::OSTab tab2(out);
1387template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1392template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1396#if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
1401 dp.property(
"label", boost::get(boost::vertex_name, graph));
1402 dp.property(
"id", boost::get(boost::vertex_index, graph));
1403 dp.property(
"label", boost::get(boost::edge_name, graph));
1404 dp.property(
"color", boost::get(boost::edge_color, graph));
1407 std::map<const FactoryBase*, BoostVertex> vindices;
1408 typedef std::map<std::pair<BoostVertex, BoostVertex>, std::string> emap;
1411 static int call_id = 0;
1413 RCP<Operator> A =
Levels_[0]->template Get<RCP<Operator>>(
"A");
1414 int rank = A->getDomainMap()->getComm()->getRank();
1417 for (
int i = currLevel; i <= currLevel + 1 && i <
GetNumLevels(); i++) {
1419 Levels_[i]->UpdateGraph(vindices, edges, dp, graph);
1421 for (emap::const_iterator eit = edges.begin(); eit != edges.end(); eit++) {
1422 std::pair<BoostEdge, bool> boost_edge = boost::add_edge(eit->first.first, eit->first.second, graph);
1425 if (eit->second == std::string(
"Graph"))
1426 boost::put(
"label", dp, boost_edge.first, std::string(
"Graph_"));
1428 boost::put(
"label", dp, boost_edge.first, eit->second);
1430 boost::put(
"color", dp, boost_edge.first, std::string(
"red"));
1432 boost::put(
"color", dp, boost_edge.first, std::string(
"blue"));
1436 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"));
1437 boost::write_graphviz_dp(out, graph, dp, std::string(
"id"));
1441 GetOStream(
Errors) <<
"Dependency graph output requires boost and MueLu_ENABLE_Boost_for_real" << std::endl;
1446template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1448 RCP<Operator> Ao = level.
Get<RCP<Operator>>(
"A");
1449 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Ao);
1451 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is not a matrix, skipping..." << std::endl;
1454 if (Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A) != Teuchos::null) {
1455 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is a BlockedCrsMatrix, skipping..." << std::endl;
1459 typedef Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::coordinateType, LO, GO, NO> xdMV;
1461 RCP<xdMV> coords = level.
Get<RCP<xdMV>>(
"Coordinates");
1463 if (A->getRowMap()->isSameAs(*(coords->getMap()))) {
1464 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: matrix and coordinates maps are same, skipping..." << std::endl;
1468 if (A->IsView(
"stridedMaps") && rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps")) != Teuchos::null) {
1469 RCP<const StridedMap> stridedRowMap = rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps"));
1472 TEUCHOS_TEST_FOR_EXCEPTION(stridedRowMap->getStridedBlockId() != -1 || stridedRowMap->getOffset() != 0,
1473 Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: nontrivial maps (block id = " << stridedRowMap->getStridedBlockId() <<
", offset = " << stridedRowMap->getOffset() <<
")");
1477 TEUCHOS_TEST_FOR_EXCEPTION(A->GetFixedBlockSize() % A->GetStorageBlockSize() != 0,
Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: Storage block size does not evenly divide fixed block size");
1479 size_t blkSize = A->GetFixedBlockSize() / A->GetStorageBlockSize();
1481 RCP<const Map> nodeMap = A->getRowMap();
1484 RCP<const Map> dofMap = A->getRowMap();
1485 GO indexBase = dofMap->getIndexBase();
1486 size_t numLocalDOFs = dofMap->getLocalNumElements();
1488 "Hierarchy::ReplaceCoordinateMap: block size (" << blkSize <<
") is incompatible with the number of local dofs in a row map (" << numLocalDOFs);
1489 ArrayView<const GO> GIDs = dofMap->getLocalElementList();
1491 Array<GO> nodeGIDs(numLocalDOFs / blkSize);
1492 for (
size_t i = 0; i < numLocalDOFs; i += blkSize)
1493 nodeGIDs[i / blkSize] = (GIDs[i] - indexBase) / blkSize + indexBase;
1495 Xpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1496 nodeMap = MapFactory::Build(dofMap->lib(), INVALID, nodeGIDs(), indexBase, dofMap->getComm());
1502 if (coords->getLocalLength() != A->getRowMap()->getLocalNumElements()) {
1503 GetOStream(
Warnings) <<
"Coordinate vector does not match row map of matrix A!" << std::endl;
1508 Array<ArrayView<const typename Teuchos::ScalarTraits<Scalar>::coordinateType>> coordDataView;
1509 std::vector<ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType>> coordData;
1510 for (
size_t i = 0; i < coords->getNumVectors(); i++) {
1511 coordData.push_back(coords->getData(i));
1512 coordDataView.push_back(coordData[i]());
1515 RCP<xdMV> newCoords = Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::coordinateType, LO, GO, NO>::Build(nodeMap, coordDataView(), coords->getNumVectors());
1516 level.
Set(
"Coordinates", newCoords);
1519template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1536 for (
int i = 0; i < N; i++) {
1537 RCP<Operator> A =
Levels_[i]->template Get<RCP<Operator>>(
"A");
1540 RCP<const BlockedCrsMatrix> A_as_blocked = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(A);
1541 RCP<const Map> Arm = A->getRangeMap();
1542 RCP<const Map> Adm = A->getDomainMap();
1543 if (!A_as_blocked.is_null()) {
1544 Adm = A_as_blocked->getFullDomainMap();
1549 residual_[i] = MultiVectorFactory::Build(Arm, numvecs,
true);
1551 correction_[i] = MultiVectorFactory::Build(Adm, numvecs,
false);
1557 RCP<Operator> P =
Levels_[i + 1]->template Get<RCP<Operator>>(
"P");
1559 RCP<const Map> map = P->getDomainMap();
1561 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1564 RCP<Operator> R =
Levels_[i + 1]->template Get<RCP<Operator>>(
"R");
1566 RCP<const Map> map = R->getRangeMap();
1568 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1572 RCP<const Import> importer;
1573 if (
Levels_[i + 1]->IsAvailable(
"Importer"))
1574 importer =
Levels_[i + 1]->template Get<RCP<const Import>>(
"Importer");
1576 RCP<const Map> map =
coarseRhs_[i]->getMap();
1578 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1581 map = importer->getTargetMap();
1583 coarseImport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1584 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1586 map = importer->getSourceMap();
1588 coarseExport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1595template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1607template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1609 const LO startLevel,
const ConvData& conv)
const {
1613template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1615 const Teuchos::Array<MagnitudeType>& residualNorm,
const MagnitudeType convergenceTolerance)
const {
1618 if (convergenceTolerance > Teuchos::ScalarTraits<MagnitudeType>::zero()) {
1620 for (LO k = 0; k < residualNorm.size(); k++)
1621 if (residualNorm[k] >= convergenceTolerance)
1630 return convergenceStatus;
1633template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1635 const LO iteration,
const Teuchos::Array<MagnitudeType>& residualNorm)
const {
1637 << std::setiosflags(std::ios::left)
1638 << std::setprecision(3) << std::setw(4) << iteration
1640 << std::setprecision(10) << residualNorm
1644template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1646 const Operator& A,
const MultiVector& X,
const MultiVector& B,
const LO iteration,
1648 Teuchos::Array<MagnitudeType> residualNorm;
1652 rate_ = currentResidualNorm / previousResidualNorm;
1653 previousResidualNorm = currentResidualNorm;
static bool debug()
Whether MueLu is in debug mode.
virtual std::string ShortClassName() const
Return the class name of the object, without template parameters and without namespace.
virtual std::string description() const
Return a simple one-line description of this object.
Exception throws to report incompatible objects (like maps).
Exception throws to report errors in the internal logical of the program.
Base class for factories (e.g., R, P, and A_coarse).
Class that provides default factories within Needs class.
virtual void Clean() const
void AddLevel(const RCP< Level > &level)
Add a level at the end of the hierarchy.
double GetSmootherComplexity() const
void Write(const LO &start=-1, const LO &end=-1, const std::string &suffix="")
Print matrices in the multigrid hierarchy to file.
RCP< Level > & GetLevel(const int levelID=0)
Retrieve a certain level from hierarchy.
Array< RCP< MultiVector > > residual_
virtual ~Hierarchy()
Destructor.
void CheckLevel(Level &level, int levelID)
Helper function.
int WCycleStartLevel_
Level at which to start W-cycle.
std::string description() const
Return a simple one-line description of this object.
void CheckForEmptySmoothersAndCoarseSolve()
std::string description_
cache description to avoid recreating in each call to description() - use ResetDescription() to force...
void IsPreconditioner(const bool flag)
static CycleType GetDefaultCycle()
Array< RCP< Level > > Levels_
Container for Level objects.
static bool GetDefaultPRrebalance()
Array< RCP< MultiVector > > coarseRhs_
Array< RCP< MultiVector > > coarseExport_
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.
void ResetDescription()
force recreation of cached description_ next time description() is called:
STS::magnitudeType MagnitudeType
void describe(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the Hierarchy with some verbosity level to a FancyOStream object.
bool isPreconditioner_
Hierarchy may be used in a standalone mode, or as a preconditioner.
ConvergenceStatus IsConverged(const Teuchos::Array< MagnitudeType > &residualNorm, const MagnitudeType convergenceTolerance) const
Decide if the multigrid iteration is converged.
void DeleteLevelMultiVectors()
ConvergenceStatus Iterate(const MultiVector &B, MultiVector &X, ConvData conv=ConvData(), bool InitialGuessIsZero=false, LO startLevel=0)
Apply the multigrid preconditioner.
void DumpCurrentGraph(int level) const
int sizeOfAllocatedLevelMultiVectors_
Caching (Multi)Vectors used in Hierarchy::Iterate().
static bool GetDefaultImplicitTranspose()
void SetMatvecParams(RCP< ParameterList > matvecParams)
static Xpetra::global_size_t GetDefaultMaxCoarseSize()
Xpetra::UnderlyingLib lib_
Epetra/Tpetra mode.
void Clear(int startLevel=0)
Clear impermanent data from previous setup.
bool IsCalculationOfResidualRequired(const LO startLevel, const ConvData &conv) const
Decide if the residual needs to be computed.
CycleType Cycle_
V- or W-cycle.
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.
std::string hierarchyLabel_
Optional name for this hierarchy.
double GetOperatorComplexity() const
MagnitudeType rate_
Convergece rate.
void PrintResidualHistory(const LO iteration, const Teuchos::Array< MagnitudeType > &residualNorm) const
Print residualNorm for this iteration to the screen.
Array< RCP< MultiVector > > coarseX_
void AllocateLevelMultiVectors(int numvecs, bool forceMapCheck=false)
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 scalingFactor_
Scaling factor to be applied to coarse grid correction.
void Delete(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Call Level::Delete(ename, factory) for each level of the Hierarchy.
int GetGlobalNumLevels() const
void Keep(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Call Level::Keep(ename, factory) for each level of the Hierarchy.
Xpetra::UnderlyingLib lib()
static bool GetDefaultFuseProlongationAndUpdate()
void SetLabel(const std::string &hierarchyLabel)
bool doPRViaCopyrebalance_
Array< RCP< MultiVector > > coarseImport_
bool isDumpingEnabled_
Graph dumping.
Xpetra::global_size_t maxCoarseSize_
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
Call Level::AddKeepFlag for each level of the Hierarchy.
Array< RCP< MultiVector > > correction_
void AddNewLevel()
Add a new level at the end of the hierarchy.
void RemoveKeepFlag(const std::string &ename, const FactoryBase *factory, KeepType keep=MueLu::All)
Call Level::RemoveKeepFlag for each level of the Hierarchy.
bool fuseProlongationAndUpdate_
Array< RCP< const FactoryManagerBase > > levelManagers_
Level managers used during the Setup.
void ReplaceCoordinateMap(Level &level)
Class that holds all level-specific information.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void SetComm(RCP< const Teuchos::Comm< int > > const &comm)
void setlib(Xpetra::UnderlyingLib lib2)
RCP< Level > & GetPreviousLevel()
Previous level.
void Release(const FactoryBase &factory)
Decrement the storage counter for all the inputs of a factory.
RCP< const Teuchos::Comm< int > > GetComm() const
int GetLevelID() const
Return level number.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
void Request(const FactoryBase &factory)
Increment the storage counter for all the inputs of a factory.
Xpetra::UnderlyingLib lib()
Timer to be used in non-factories.
static const NoFactory * get()
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
An exception safe way to call the method 'Level::SetFactoryManager()'.
Integrates Teuchos::TimeMonitor with MueLu verbosity system.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
static Teuchos::Array< Magnitude > ResidualNorm(const Xpetra::Operator< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > &Op, const MultiVector &X, const MultiVector &RHS)
static void SetRandomSeed(const Teuchos::Comm< int > &comm)
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > &Op, const MultiVector &X, const MultiVector &RHS)
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
VerbLevel GetVerbLevel() const
Get the verbosity level.
int SetProcRankVerbose(int procRank) const
Set proc rank used for printing.
bool IsPrint(MsgType type, int thisProcRankOnly=-1) const
Find out whether we need to print out information for a specific message type.
int GetProcRankVerbose() const
Get proc rank used for printing. Do not use this information for any other purpose....
Namespace for MueLu classes and methods.
@ Warnings0
Important warning messages (one line).
@ Statistics2
Print even more statistics.
@ Warnings
Print all warning messages.
@ Statistics1
Print more statistics.
@ Timings0
High level timing information (use Teuchos::TimeMonitor::summarize() to print).
@ Runtime0
One-liner description of what is happening.
@ Runtime1
Description of what is happening (more verbose).
@ Warnings1
Additional warnings.
@ Statistics0
Print statistics that do not involve significant additional computation.
@ Parameters1
Print class parameters (more parameters, more verbose).
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
VerbLevel toMueLuVerbLevel(const Teuchos::EVerbosityLevel verbLevel)
Translate Teuchos verbosity level to MueLu verbosity level.
Data struct for defining stopping criteria of multigrid iteration.