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>
44 : maxCoarseSize_(GetDefaultMaxCoarseSize())
45 , implicitTranspose_(GetDefaultImplicitTranspose())
46 , fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate())
47 , doPRrebalance_(GetDefaultPRrebalance())
48 , doPRViaCopyrebalance_(false)
49 , isPreconditioner_(true)
50 , Cycle_(GetDefaultCycle())
51 , WCycleStartLevel_(0)
52 , scalingFactor_(
Teuchos::ScalarTraits<double>::one())
54 , isDumpingEnabled_(false)
57 , sizeOfAllocatedLevelMultiVectors_(0) {
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>
71 : maxCoarseSize_(GetDefaultMaxCoarseSize())
72 , implicitTranspose_(GetDefaultImplicitTranspose())
73 , fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate())
74 , doPRrebalance_(GetDefaultPRrebalance())
75 , doPRViaCopyrebalance_(false)
76 , isPreconditioner_(true)
77 , Cycle_(GetDefaultCycle())
78 , WCycleStartLevel_(0)
79 , scalingFactor_(
Teuchos::ScalarTraits<double>::one())
80 , isDumpingEnabled_(false)
83 , sizeOfAllocatedLevelMultiVectors_(0) {
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>
104 int levelID = LastLevelID() + 1;
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;
110 Levels_.push_back(level);
111 level->SetLevelID(levelID);
114 level->SetPreviousLevel((levelID == 0) ? Teuchos::null : Levels_[LastLevelID() - 1]);
115 level->setObjectLabel(this->getObjectLabel());
118template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
120 RCP<Level> newLevel = Levels_[LastLevelID()]->Build();
121 newLevel->setlib(lib_);
122 this->AddLevel(newLevel);
125template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
128 "MueLu::Hierarchy::GetLevel(): invalid input parameter value: LevelID = " << levelID);
129 return Levels_[levelID];
132template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
134 return Levels_.size();
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();
142 int numLevels = GetNumLevels();
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;
152 for (
int i = 0; i < GetNumLevels(); ++i) {
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();
183 if (GetNumLevels() <= 0)
return -1.0;
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());
194 for (
int i = 0; i < GetNumLevels(); ++i) {
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>
232 for (
int i = 0; i < GetNumLevels(); ++i) {
233 RCP<Level> level = Levels_[i];
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.");
283 Level& level = *Levels_[coarseLevelID];
285 bool useStackedTimer = !Teuchos::TimeMonitor::stackedTimerNameIsDefault();
289 if (!useStackedTimer)
290 m1 = rcp(
new TimeMonitor(*
this, label + this->ShortClassName() +
": " +
"Setup (total)"));
291 TimeMonitor m2(*
this, label + this->ShortClassName() +
": " +
"Setup" +
" (total, level=" + Teuchos::toString(coarseLevelID) +
")");
295 "MueLu::Hierarchy::Setup(): argument coarseLevelManager cannot be null");
300 if (levelManagers_.size() < coarseLevelID + 1)
301 levelManagers_.resize(coarseLevelID + 1);
302 levelManagers_[coarseLevelID] = coarseLevelManager;
304 bool isFinestLevel = (fineLevelManager.is_null());
305 bool isLastLevel = (nextLevelManager.is_null());
309 RCP<Operator> A = level.
Get<RCP<Operator>>(
"A");
310 RCP<const Map> domainMap = A->getDomainMap();
311 RCP<const Teuchos::Comm<int>> comm = domainMap->getComm();
318 oldRank = SetProcRankVerbose(comm->getRank());
322 lib_ = domainMap->lib();
329 Level& prevLevel = *Levels_[coarseLevelID - 1];
330 oldRank = SetProcRankVerbose(prevLevel.
GetComm()->getRank());
333 CheckLevel(level, coarseLevelID);
336 RCP<SetFactoryManager> SFMFine;
338 SFMFine = rcp(
new SetFactoryManager(Levels_[coarseLevelID - 1], fineLevelManager));
340 if (isFinestLevel && Levels_[coarseLevelID]->IsAvailable(
"Coordinates"))
341 ReplaceCoordinateMap(*Levels_[coarseLevelID]);
346 if (isDumpingEnabled_ && (dumpLevel_ == 0 || dumpLevel_ == -1) && coarseLevelID == 1)
349 RCP<TopSmootherFactory> coarseFact;
350 RCP<TopSmootherFactory> smootherFact = rcp(
new TopSmootherFactory(coarseLevelManager,
"Smoother"));
352 int nextLevelID = coarseLevelID + 1;
354 RCP<SetFactoryManager> SFMNext;
355 if (isLastLevel ==
false) {
357 if (nextLevelID > LastLevelID())
359 CheckLevel(*Levels_[nextLevelID], nextLevelID);
363 Levels_[nextLevelID]->Request(
TopRAPFactory(coarseLevelManager, nextLevelManager));
392 if (coarseFact.is_null())
401 RCP<Operator> Ac = Teuchos::null;
402 TopRAPFactory coarseRAPFactory(fineLevelManager, coarseLevelManager);
405 Ac = level.
Get<RCP<Operator>>(
"A");
406 }
else if (!isFinestLevel) {
411 bool setLastLevelviaMaxCoarseSize =
false;
413 Ac = level.
Get<RCP<Operator>>(
"A");
414 RCP<Matrix> Acm = rcp_dynamic_cast<Matrix>(Ac);
418 level.
SetComm(Ac->getDomainMap()->getComm());
421 bool isOrigLastLevel = isLastLevel;
426 }
else if (Ac.is_null()) {
433 if (!Acm.is_null() && Acm->getGlobalNumRows() <= maxCoarseSize_) {
435 GetOStream(
Runtime0) <<
"Max coarse size (<= " << maxCoarseSize_ <<
") achieved" << std::endl;
437 if (Acm->getGlobalNumRows() != 0) setLastLevelviaMaxCoarseSize =
true;
441 if (!Ac.is_null() && !isFinestLevel) {
442 RCP<Operator> A = Levels_[coarseLevelID - 1]->template Get<RCP<Operator>>(
"A");
443 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
445 const double maxCoarse2FineRatio = 0.8;
446 if (!Acm.is_null() && !Am.is_null() && Acm->getGlobalNumRows() > maxCoarse2FineRatio * Am->getGlobalNumRows()) {
454 GetOStream(
Warnings0) <<
"Aggregation stagnated. Please check your matrix and/or adjust your configuration file."
455 <<
"Possible fixes:\n"
456 <<
" - reduce the maximum number of levels\n"
457 <<
" - enable repartitioning\n"
458 <<
" - increase the minimum coarse size." << std::endl;
463 if (!isOrigLastLevel) {
467 if (coarseFact.is_null())
475 coarseFact->Build(level);
486 smootherFact->Build(level);
491 if (isLastLevel ==
true) {
492 int actualNumLevels = nextLevelID;
493 if (isOrigLastLevel ==
false) {
496 Levels_[nextLevelID]->Release(
TopRAPFactory(coarseLevelManager, nextLevelManager));
502 if (!setLastLevelviaMaxCoarseSize) {
503 if (Levels_[nextLevelID - 1]->IsAvailable(
"P")) {
504 if (Levels_[nextLevelID - 1]->
template Get<RCP<Matrix>>(
"P") == Teuchos::null) actualNumLevels = nextLevelID - 1;
506 actualNumLevels = nextLevelID - 1;
509 if (actualNumLevels == nextLevelID - 1) {
511 Levels_[nextLevelID - 2]->Release(*smootherFact);
513 if (Levels_[nextLevelID - 2]->IsAvailable(
"PreSmoother")) Levels_[nextLevelID - 2]->RemoveKeepFlag(
"PreSmoother",
NoFactory::get());
514 if (Levels_[nextLevelID - 2]->IsAvailable(
"PostSmoother")) Levels_[nextLevelID - 2]->RemoveKeepFlag(
"PostSmoother",
NoFactory::get());
515 if (coarseFact.is_null())
517 Levels_[nextLevelID - 2]->Request(*coarseFact);
518 if (!(Levels_[nextLevelID - 2]->
template Get<RCP<Matrix>>(
"A").is_null()))
519 coarseFact->Build(*(Levels_[nextLevelID - 2]));
520 Levels_[nextLevelID - 2]->Release(*coarseFact);
522 Levels_.resize(actualNumLevels);
523 levelManagers_.resize(actualNumLevels);
527 if (isDumpingEnabled_ && ((dumpLevel_ > 0 && coarseLevelID == dumpLevel_) || dumpLevel_ == -1))
528 DumpCurrentGraph(coarseLevelID);
530 if (!isFinestLevel) {
534 level.
Release(coarseRAPFactory);
538 SetProcRankVerbose(oldRank);
543template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
545 int numLevels = Levels_.size();
547 "Hierarchy::SetupRe: " << Levels_.size() <<
" levels, but " << levelManagers_.size() <<
" level factory managers");
549 const int startLevel = 0;
552#ifdef HAVE_MUELU_DEBUG
554 for (
int i = 0; i < numLevels; i++)
555 levelManagers_[i]->ResetDebugData();
560 for (levelID = startLevel; levelID < numLevels;) {
561 bool r = Setup(levelID,
562 (levelID != 0 ? levelManagers_[levelID - 1] : Teuchos::null),
563 levelManagers_[levelID],
564 (levelID + 1 != numLevels ? levelManagers_[levelID + 1] : Teuchos::null));
570 Levels_.resize(levelID);
571 levelManagers_.resize(levelID);
573 int sizeOfVecs = sizeOfAllocatedLevelMultiVectors_;
575 AllocateLevelMultiVectors(sizeOfVecs,
true);
582 CheckForEmptySmoothersAndCoarseSolve();
585template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
594 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") does not exist");
597 "Constructing non-positive (" << numDesiredLevels <<
") number of levels does not make sense.");
601 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") has no matrix A! "
602 "Set fine level matrix A using Level.Set()");
604 RCP<Operator> A = Levels_[startLevel]->template Get<RCP<Operator>>(
"A");
605 lib_ = A->getDomainMap()->lib();
608 RCP<Matrix> Amat = rcp_dynamic_cast<Matrix>(A);
610 if (!Amat.is_null()) {
611 RCP<ParameterList> params = rcp(
new ParameterList());
612 params->set(
"printLoadBalancingInfo",
true);
613 params->set(
"printCommInfo",
true);
617 GetOStream(
Warnings1) <<
"Fine level operator is not a matrix, statistics are not available" << std::endl;
621 RCP<const FactoryManagerBase> rcpmanager = rcpFromRef(manager);
623 const int lastLevel = startLevel + numDesiredLevels - 1;
624 GetOStream(
Runtime0) <<
"Setup loop: startLevel = " << startLevel <<
", lastLevel = " << lastLevel
625 <<
" (stop if numLevels = " << numDesiredLevels <<
" or Ac.size() < " << maxCoarseSize_ <<
")" << std::endl;
629 if (numDesiredLevels == 1) {
631 Setup(startLevel, Teuchos::null, rcpmanager, Teuchos::null);
634 bool bIsLastLevel = Setup(startLevel, Teuchos::null, rcpmanager, rcpmanager);
635 if (bIsLastLevel ==
false) {
636 for (iLevel = startLevel + 1; iLevel < lastLevel; iLevel++) {
637 bIsLastLevel = Setup(iLevel, rcpmanager, rcpmanager, rcpmanager);
638 if (bIsLastLevel ==
true)
641 if (bIsLastLevel ==
false)
642 Setup(lastLevel, rcpmanager, rcpmanager, Teuchos::null);
648 "MueLu::Hierarchy::Setup(): number of level");
656 CheckForEmptySmoothersAndCoarseSolve();
659template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
661 for (LO levelNo = 0; levelNo < GetNumLevels(); ++levelNo) {
662 auto level = Levels_[levelNo];
663 if ((level->IsAvailable(
"A") && !level->template Get<RCP<Operator>>(
"A").is_null()) && (!level->IsAvailable(
"PreSmoother")) && (!level->IsAvailable(
"PostSmoother"))) {
664 GetOStream(
Warnings1) <<
"No " << (levelNo == as<LO>(Levels_.size()) - 1 ?
"coarse grid solver" :
"smoother") <<
" on level " << level->GetLevelID() << std::endl;
669template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
671 if (startLevel < GetNumLevels())
672 GetOStream(
Runtime0) <<
"Clearing old data (if any)" << std::endl;
674 for (
int iLevel = startLevel; iLevel < GetNumLevels(); iLevel++)
675 Levels_[iLevel]->Clear();
678template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
680 GetOStream(
Runtime0) <<
"Clearing old data (expert)" << std::endl;
681 for (
int iLevel = 0; iLevel < GetNumLevels(); iLevel++)
682 Levels_[iLevel]->ExpertClear();
685#if defined(HAVE_MUELU_EXPERIMENTAL) && defined(HAVE_MUELU_ADDITIVE_VARIANT)
686template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
688 bool InitialGuessIsZero, LO startLevel) {
689 LO nIts = conv.maxIts_;
690 MagnitudeType tol = conv.tol_;
692 std::string prefix = this->ShortClassName() +
": ";
693 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
694 std::string levelSuffix1 =
" (level=" +
toString(startLevel + 1) +
")";
697 RCP<Time> CompTime = Teuchos::TimeMonitor::getNewCounter(prefix +
"Computational Time (total)");
698 RCP<Time> Concurrent = Teuchos::TimeMonitor::getNewCounter(prefix +
"Concurrent portion");
699 RCP<Time> ApplyR = Teuchos::TimeMonitor::getNewCounter(prefix +
"R: Computational Time");
700 RCP<Time> ApplyPbar = Teuchos::TimeMonitor::getNewCounter(prefix +
"Pbar: Computational Time");
701 RCP<Time> CompFine = Teuchos::TimeMonitor::getNewCounter(prefix +
"Fine: Computational Time");
702 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
703 RCP<Time> ApplySum = Teuchos::TimeMonitor::getNewCounter(prefix +
"Sum: Computational Time");
704 RCP<Time> Synchronize_beginning = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_beginning");
705 RCP<Time> Synchronize_center = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_center");
706 RCP<Time> Synchronize_end = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_end");
708 RCP<Level> Fine = Levels_[0];
711 RCP<Operator> A = Fine->Get<RCP<Operator>>(
"A");
712 Teuchos::RCP<const Teuchos::Comm<int>> communicator = A->getDomainMap()->getComm();
720 SC one = STS::one(), zero = STS::zero();
722 bool zeroGuess = InitialGuessIsZero;
730 RCP<MultiVector> coarseRhs, coarseX;
732 RCP<SmootherBase> preSmoo_coarse, postSmoo_coarse;
733 bool emptyCoarseSolve =
true;
734 RCP<MultiVector> coarseX_prolonged = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
736 RCP<const Import> importer;
738 if (Levels_.size() > 1) {
740 if (Coarse->IsAvailable(
"Importer"))
741 importer = Coarse->Get<RCP<const Import>>(
"Importer");
743 R = Coarse->Get<RCP<Operator>>(
"R");
744 P = Coarse->Get<RCP<Operator>>(
"P");
747 Pbar = Coarse->Get<RCP<Operator>>(
"Pbar");
749 coarseRhs = MultiVectorFactory::Build(R->getRangeMap(), B.getNumVectors(),
true);
751 Ac = Coarse->Get<RCP<Operator>>(
"A");
754 R->apply(B, *coarseRhs, Teuchos::NO_TRANS, one, zero);
758 if (doPRrebalance_ || importer.is_null()) {
759 coarseX = MultiVectorFactory::Build(coarseRhs->getMap(), X.getNumVectors(),
true);
762 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import (total)",
Timings0));
763 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
766 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getTargetMap(), coarseRhs->getNumVectors());
767 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
768 coarseRhs.swap(coarseTmp);
770 coarseX = MultiVectorFactory::Build(importer->getTargetMap(), X.getNumVectors(),
true);
773 if (Coarse->IsAvailable(
"PreSmoother"))
774 preSmoo_coarse = Coarse->Get<RCP<SmootherBase>>(
"PreSmoother");
775 if (Coarse->IsAvailable(
"PostSmoother"))
776 postSmoo_coarse = Coarse->Get<RCP<SmootherBase>>(
"PostSmoother");
781 MagnitudeType prevNorm = STS::magnitude(STS::one()), curNorm = STS::magnitude(STS::one());
785 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
786 std::ostringstream ss;
787 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
788 throw Exceptions::Incompatible(ss.str());
791 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
792 std::ostringstream ss;
793 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
794 throw Exceptions::Incompatible(ss.str());
798 bool emptyFineSolve =
true;
800 RCP<MultiVector> fineX;
801 fineX = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
810 if (Fine->IsAvailable(
"PreSmoother")) {
811 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
813 preSmoo->Apply(*fineX, B, zeroGuess);
815 emptyFineSolve =
false;
817 if (Fine->IsAvailable(
"PostSmoother")) {
818 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
820 postSmoo->Apply(*fineX, B, zeroGuess);
823 emptyFineSolve =
false;
825 if (emptyFineSolve ==
true) {
827 fineX->update(one, B, zero);
830 if (Levels_.size() > 1) {
832 if (Coarse->IsAvailable(
"PreSmoother")) {
834 preSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
836 emptyCoarseSolve =
false;
838 if (Coarse->IsAvailable(
"PostSmoother")) {
840 postSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
842 emptyCoarseSolve =
false;
844 if (emptyCoarseSolve ==
true) {
846 coarseX->update(one, *coarseRhs, zero);
853 if (!doPRrebalance_ && !importer.is_null()) {
854 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export (total)",
Timings0));
855 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
858 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getSourceMap(), coarseX->getNumVectors());
859 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
860 coarseX.swap(coarseTmp);
864 Pbar->apply(*coarseX, *coarseX_prolonged, Teuchos::NO_TRANS, one, zero);
869 X.update(1.0, *fineX, 1.0, *coarseX_prolonged, 0.0);
880template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
882 bool InitialGuessIsZero, LO startLevel) {
898 RCP<Level> Fine = Levels_[startLevel];
901 std::string prefix = label + this->ShortClassName() +
": ";
902 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
903 std::string levelSuffix1 =
" (level=" +
toString(startLevel + 1) +
")";
905 bool useStackedTimer = !Teuchos::TimeMonitor::stackedTimerNameIsDefault();
907 RCP<Monitor> iterateTime;
908 RCP<TimeMonitor> iterateTime1;
911 else if (!useStackedTimer)
914 std::string iterateLevelTimeLabel = prefix +
"Solve" + levelSuffix;
915 RCP<TimeMonitor> iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel,
Timings0));
917 bool zeroGuess = InitialGuessIsZero;
919 RCP<Operator> A = Fine->Get<RCP<Operator>>(
"A");
921 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
934 const BlockedMultiVector* Bblocked =
dynamic_cast<const BlockedMultiVector*
>(&B);
935 if (residual_.size() > startLevel &&
936 ((Bblocked && !Bblocked->isSameSize(*residual_[startLevel])) ||
937 (!Bblocked && !residual_[startLevel]->isSameSize(B))))
938 DeleteLevelMultiVectors();
939 AllocateLevelMultiVectors(X.getNumVectors());
942 typedef Teuchos::ScalarTraits<typename STS::magnitudeType> STM;
945 if (IsCalculationOfResidualRequired(startLevel, conv)) {
946 ConvergenceStatus convergenceStatus = ComputeResidualAndPrintHistory(*A, X, B, Teuchos::ScalarTraits<LO>::zero(), startLevel, conv, prevNorm);
948 return convergenceStatus;
951 SC one = STS::one(), zero = STS::zero();
952 for (LO iteration = 1; iteration <= nIts; iteration++) {
953#ifdef HAVE_MUELU_DEBUG
955 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
956 std::ostringstream ss;
957 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
961 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
962 std::ostringstream ss;
963 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
969 if (startLevel == as<LO>(Levels_.size()) - 1) {
971 RCP<TimeMonitor> CLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : coarse" + levelSuffix,
Timings0));
973 bool emptySolve =
true;
976 if (Fine->IsAvailable(
"PreSmoother")) {
977 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
979 preSmoo->Apply(X, B, zeroGuess);
984 if (Fine->IsAvailable(
"PostSmoother")) {
985 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
987 postSmoo->Apply(X, B, zeroGuess);
992 if (emptySolve ==
true) {
994 X.update(one, B, zero);
999 RCP<Level> Coarse = Levels_[startLevel + 1];
1002 RCP<TimeMonitor> STime;
1003 if (!useStackedTimer)
1005 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1007 if (Fine->IsAvailable(
"PreSmoother")) {
1008 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
1009 preSmoo->Apply(X, B, zeroGuess);
1014 RCP<MultiVector> residual;
1016 RCP<TimeMonitor> ATime;
1017 if (!useStackedTimer)
1018 ATime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : residual calculation (total)",
Timings0));
1019 RCP<TimeMonitor> ALevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : residual calculation" + levelSuffix,
Timings0));
1027 residual = residual_[startLevel];
1030 RCP<Operator> P = Coarse->Get<RCP<Operator>>(
"P");
1031 if (Coarse->IsAvailable(
"Pbar"))
1032 P = Coarse->Get<RCP<Operator>>(
"Pbar");
1034 RCP<MultiVector> coarseRhs, coarseX;
1038 RCP<TimeMonitor> RTime;
1039 if (!useStackedTimer)
1041 RCP<TimeMonitor> RLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : restriction" + levelSuffix,
Timings0));
1042 coarseRhs = coarseRhs_[startLevel];
1044 if (implicitTranspose_) {
1045 P->apply(*residual, *coarseRhs, Teuchos::TRANS, one, zero);
1048 RCP<Operator> R = Coarse->Get<RCP<Operator>>(
"R");
1049 R->apply(*residual, *coarseRhs, Teuchos::NO_TRANS, one, zero);
1053 RCP<const Import> importer;
1054 if (Coarse->IsAvailable(
"Importer"))
1055 importer = Coarse->Get<RCP<const Import>>(
"Importer");
1057 coarseX = coarseX_[startLevel];
1058 if (!doPRrebalance_ && !importer.is_null()) {
1059 RCP<TimeMonitor> ITime;
1060 if (!useStackedTimer)
1062 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
1065 RCP<MultiVector> coarseTmp = coarseImport_[startLevel];
1066 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
1067 coarseRhs.swap(coarseTmp);
1070 RCP<Operator> Ac = Coarse->Get<RCP<Operator>>(
"A");
1071 if (!Ac.is_null()) {
1072 RCP<const Map> origXMap = coarseX->getMap();
1073 RCP<const Map> origRhsMap = coarseRhs->getMap();
1076 coarseRhs->replaceMap(Ac->getRangeMap());
1077 coarseX->replaceMap(Ac->getDomainMap());
1080 iterateLevelTime = Teuchos::null;
1082 Iterate(*coarseRhs, *coarseX, 1,
true, startLevel + 1);
1084 if (Cycle_ ==
WCYCLE && WCycleStartLevel_ <= startLevel)
1085 Iterate(*coarseRhs, *coarseX, 1,
false, startLevel + 1);
1088 iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel));
1090 coarseX->replaceMap(origXMap);
1091 coarseRhs->replaceMap(origRhsMap);
1094 if (!doPRrebalance_ && !importer.is_null()) {
1095 RCP<TimeMonitor> ITime;
1096 if (!useStackedTimer)
1098 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
1101 RCP<MultiVector> coarseTmp = coarseExport_[startLevel];
1102 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
1103 coarseX.swap(coarseTmp);
1108 RCP<TimeMonitor> PTime;
1109 if (!useStackedTimer)
1111 RCP<TimeMonitor> PLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : prolongation" + levelSuffix,
Timings0));
1116 if (fuseProlongationAndUpdate_) {
1117 P->apply(*coarseX, X, Teuchos::NO_TRANS, scalingFactor_, one);
1119 RCP<MultiVector> correction = correction_[startLevel];
1120 P->apply(*coarseX, *correction, Teuchos::NO_TRANS, one, zero);
1121 X.update(scalingFactor_, *correction, one);
1127 RCP<TimeMonitor> STime;
1128 if (!useStackedTimer)
1130 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1132 if (Fine->IsAvailable(
"PostSmoother")) {
1133 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
1134 postSmoo->Apply(X, B,
false);
1140 if (IsCalculationOfResidualRequired(startLevel, conv)) {
1141 ConvergenceStatus convergenceStatus = ComputeResidualAndPrintHistory(*A, X, B, iteration, startLevel, conv, prevNorm);
1143 return convergenceStatus;
1150template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1152 LO startLevel = (start != -1 ? start : 0);
1153 LO endLevel = (end != -1 ? end : Levels_.size() - 1);
1156 "MueLu::Hierarchy::Write : startLevel must be <= endLevel");
1159 "MueLu::Hierarchy::Write bad start or end level");
1161 for (LO i = startLevel; i < endLevel + 1; i++) {
1162 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get<RCP<Operator>>(
"A")), P, R;
1164 P = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get<RCP<Operator>>(
"P"));
1165 if (!implicitTranspose_)
1166 R = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get<RCP<Operator>>(
"R"));
1169 if (!A.is_null()) Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"A_" +
toString(i) + suffix +
".m", *A);
1171 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"P_" +
toString(i) + suffix +
".m", *P);
1174 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"R_" +
toString(i) + suffix +
".m", *R);
1179template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1181 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1182 (*it)->Keep(ename, factory);
1185template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1187 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1188 (*it)->Delete(ename, factory);
1191template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1193 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1194 (*it)->AddKeepFlag(ename, factory, keep);
1197template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1199 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1200 (*it)->RemoveKeepFlag(ename, factory, keep);
1203template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1205 if (description_.empty()) {
1206 std::ostringstream out;
1208 out <<
"{#levels = " << GetGlobalNumLevels() <<
", complexity = " << GetOperatorComplexity() <<
"}";
1209 description_ = out.str();
1211 return description_;
1214template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1219template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1221 RCP<Operator> A0 = Levels_[0]->template Get<RCP<Operator>>(
"A");
1222 RCP<const Teuchos::Comm<int>> comm = A0->getDomainMap()->getComm();
1224 int numLevels = GetNumLevels();
1225 RCP<Operator> Ac = Levels_[numLevels - 1]->template Get<RCP<Operator>>(
"A");
1232 int root = comm->getRank();
1235 int smartData = numLevels * comm->getSize() + comm->getRank(), maxSmartData;
1236 reduceAll(*comm, Teuchos::REDUCE_MAX, smartData, Teuchos::ptr(&maxSmartData));
1237 root = maxSmartData % comm->getSize();
1241 double smoother_comp = -1.0;
1243 smoother_comp = GetSmootherComplexity();
1247 std::vector<Xpetra::global_size_t> nnzPerLevel;
1248 std::vector<Xpetra::global_size_t> rowsPerLevel;
1249 std::vector<int> numProcsPerLevel;
1250 bool someOpsNotMatrices =
false;
1251 const Xpetra::global_size_t OPERATOR = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1252 const Xpetra::global_size_t UNAVAILABLE = Teuchos::OrdinalTraits<Xpetra::global_size_t>::max();
1253 for (
int i = 0; i < numLevels; i++) {
1255 "Operator A is not available on level " << i);
1257 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
1259 "Operator A on level " << i <<
" is null.");
1261 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
1263 someOpsNotMatrices =
true;
1264 nnzPerLevel.push_back(OPERATOR);
1265 rowsPerLevel.push_back(A->getDomainMap()->getGlobalNumElements());
1266 numProcsPerLevel.push_back(A->getDomainMap()->getComm()->getSize());
1268 LO storageblocksize = Am->GetStorageBlockSize();
1269 if (Am->haveGlobalConstants()) {
1270 Xpetra::global_size_t nnz = Am->getGlobalNumEntries() * storageblocksize * storageblocksize;
1271 nnzPerLevel.push_back(nnz);
1273 nnzPerLevel.push_back(UNAVAILABLE);
1274 rowsPerLevel.push_back(Am->getGlobalNumRows() * storageblocksize);
1275 numProcsPerLevel.push_back(Am->getRowMap()->getComm()->getSize());
1278 if (someOpsNotMatrices)
1279 GetOStream(
Warnings0) <<
"Some level operators are not matrices, statistics calculation are incomplete" << std::endl;
1282 std::string label = Levels_[0]->getObjectLabel();
1283 std::ostringstream oss;
1284 oss << std::setfill(
' ');
1285 oss <<
"\n--------------------------------------------------------------------------------\n";
1286 oss <<
"--- Multigrid Summary " << std::setw(32) <<
"---\n";
1287 oss <<
"--------------------------------------------------------------------------------" << std::endl;
1288 if (hierarchyLabel_ !=
"") oss <<
"Label = " << hierarchyLabel_ << std::endl;
1290 oss <<
"Scalar = " << Teuchos::ScalarTraits<Scalar>::name() << std::endl;
1291 oss <<
"Number of levels = " << numLevels << std::endl;
1292 oss <<
"Operator complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1293 if (!someOpsNotMatrices)
1294 oss << GetOperatorComplexity() << std::endl;
1296 oss <<
"not available (Some operators in hierarchy are not matrices.)" << std::endl;
1298 if (smoother_comp != -1.0) {
1299 oss <<
"Smoother complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1300 << smoother_comp << std::endl;
1305 oss <<
"Cycle type = V" << std::endl;
1308 oss <<
"Cycle type = W" << std::endl;
1309 if (WCycleStartLevel_ > 0)
1310 oss <<
"Cycle start level = " << WCycleStartLevel_ << std::endl;
1317 Xpetra::global_size_t tt = rowsPerLevel[0];
1323 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1324 tt = nnzPerLevel[i];
1325 if ((tt != OPERATOR) && (tt != UNAVAILABLE))
1334 tt = numProcsPerLevel[0];
1340 oss <<
"level " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz "
1341 <<
" nnz/row" << std::setw(npspacer) <<
" c ratio"
1342 <<
" procs" << std::endl;
1343 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1344 oss <<
" " << i <<
" ";
1345 oss << std::setw(rowspacer) << rowsPerLevel[i];
1346 if ((nnzPerLevel[i] != OPERATOR) && (nnzPerLevel[i] != UNAVAILABLE)) {
1347 oss << std::setw(nnzspacer) << nnzPerLevel[i];
1348 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1349 oss << std::setw(9) << as<double>(nnzPerLevel[i]) / rowsPerLevel[i];
1351 if (nnzPerLevel[i] == OPERATOR)
1352 oss << std::setw(nnzspacer) <<
"Operator";
1354 oss << std::setw(nnzspacer) <<
"N/A";
1355 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1356 oss << std::setw(9) <<
" ";
1359 oss << std::setw(9) << as<double>(rowsPerLevel[i - 1]) / rowsPerLevel[i];
1361 oss << std::setw(9) <<
" ";
1362 oss <<
" " << std::setw(npspacer) << numProcsPerLevel[i] << std::endl;
1365 for (
int i = 0; i < GetNumLevels(); ++i) {
1366 RCP<SmootherBase> preSmoo, postSmoo;
1367 if (Levels_[i]->IsAvailable(
"PreSmoother"))
1368 preSmoo = Levels_[i]->
template Get<RCP<SmootherBase>>(
"PreSmoother");
1369 if (Levels_[i]->IsAvailable(
"PostSmoother"))
1370 postSmoo = Levels_[i]->
template Get<RCP<SmootherBase>>(
"PostSmoother");
1372 if (preSmoo != null && preSmoo == postSmoo)
1373 oss <<
"Smoother (level " << i <<
") both : " << preSmoo->description() << std::endl;
1375 oss <<
"Smoother (level " << i <<
") pre : "
1376 << (preSmoo != null ? preSmoo->description() :
"no smoother") << std::endl;
1377 oss <<
"Smoother (level " << i <<
") post : "
1378 << (postSmoo != null ? postSmoo->description() :
"no smoother") << std::endl;
1389 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
1390 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1392 int strLength = outstr.size();
1393 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1394 if (comm->getRank() != root)
1395 outstr.resize(strLength);
1396 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1403template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1405 Teuchos::OSTab tab2(out);
1406 for (
int i = 0; i < GetNumLevels(); ++i)
1407 Levels_[i]->print(out, verbLevel);
1410template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1412 isPreconditioner_ = flag;
1415template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1417 if (GetProcRankVerbose() != 0)
1419#if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
1424 dp.property(
"label", boost::get(boost::vertex_name, graph));
1425 dp.property(
"id", boost::get(boost::vertex_index, graph));
1426 dp.property(
"label", boost::get(boost::edge_name, graph));
1427 dp.property(
"color", boost::get(boost::edge_color, graph));
1430 std::map<const FactoryBase*, BoostVertex> vindices;
1431 typedef std::map<std::pair<BoostVertex, BoostVertex>, std::string> emap;
1434 static int call_id = 0;
1436 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator>>(
"A");
1437 int rank = A->getDomainMap()->getComm()->getRank();
1440 for (
int i = currLevel; i <= currLevel + 1 && i < GetNumLevels(); i++) {
1442 Levels_[i]->UpdateGraph(vindices, edges, dp, graph);
1444 for (emap::const_iterator eit = edges.begin(); eit != edges.end(); eit++) {
1445 std::pair<BoostEdge, bool> boost_edge = boost::add_edge(eit->first.first, eit->first.second, graph);
1448 if (eit->second == std::string(
"Graph"))
1449 boost::put(
"label", dp, boost_edge.first, std::string(
"Graph_"));
1451 boost::put(
"label", dp, boost_edge.first, eit->second);
1453 boost::put(
"color", dp, boost_edge.first, std::string(
"red"));
1455 boost::put(
"color", dp, boost_edge.first, std::string(
"blue"));
1459 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"));
1460 boost::write_graphviz_dp(out, graph, dp, std::string(
"id"));
1464 GetOStream(
Errors) <<
"Dependency graph output requires boost and MueLu_ENABLE_Boost_for_real" << std::endl;
1469template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1471 RCP<Operator> Ao = level.
Get<RCP<Operator>>(
"A");
1472 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Ao);
1474 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is not a matrix, skipping..." << std::endl;
1477 if (Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A) != Teuchos::null) {
1478 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is a BlockedCrsMatrix, skipping..." << std::endl;
1482 typedef Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::coordinateType, LO, GO, NO> xdMV;
1484 RCP<xdMV> coords = level.
Get<RCP<xdMV>>(
"Coordinates");
1486 if (A->getRowMap()->isSameAs(*(coords->getMap()))) {
1487 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: matrix and coordinates maps are same, skipping..." << std::endl;
1491 if (A->IsView(
"stridedMaps") && rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps")) != Teuchos::null) {
1492 RCP<const StridedMap> stridedRowMap = rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps"));
1495 TEUCHOS_TEST_FOR_EXCEPTION(stridedRowMap->getStridedBlockId() != -1 || stridedRowMap->getOffset() != 0,
1496 Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: nontrivial maps (block id = " << stridedRowMap->getStridedBlockId() <<
", offset = " << stridedRowMap->getOffset() <<
")");
1499 GetOStream(
Runtime1) <<
"Replacing coordinate map" << std::endl;
1500 TEUCHOS_TEST_FOR_EXCEPTION(A->GetFixedBlockSize() % A->GetStorageBlockSize() != 0,
Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: Storage block size does not evenly divide fixed block size");
1502 size_t blkSize = A->GetFixedBlockSize() / A->GetStorageBlockSize();
1504 RCP<const Map> nodeMap = A->getRowMap();
1507 RCP<const Map> dofMap = A->getRowMap();
1508 GO indexBase = dofMap->getIndexBase();
1509 size_t numLocalDOFs = dofMap->getLocalNumElements();
1511 "Hierarchy::ReplaceCoordinateMap: block size (" << blkSize <<
") is incompatible with the number of local dofs in a row map (" << numLocalDOFs);
1512 ArrayView<const GO> GIDs = dofMap->getLocalElementList();
1514 Array<GO> nodeGIDs(numLocalDOFs / blkSize);
1515 for (
size_t i = 0; i < numLocalDOFs; i += blkSize)
1516 nodeGIDs[i / blkSize] = (GIDs[i] - indexBase) / blkSize + indexBase;
1518 Xpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1519 nodeMap = MapFactory::Build(dofMap->lib(), INVALID, nodeGIDs(), indexBase, dofMap->getComm());
1525 if (coords->getLocalLength() != A->getRowMap()->getLocalNumElements()) {
1526 GetOStream(
Warnings) <<
"Coordinate vector does not match row map of matrix A!" << std::endl;
1531 Array<ArrayView<const typename Teuchos::ScalarTraits<Scalar>::coordinateType>> coordDataView;
1532 std::vector<ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType>> coordData;
1533 for (
size_t i = 0; i < coords->getNumVectors(); i++) {
1534 coordData.push_back(coords->getData(i));
1535 coordDataView.push_back(coordData[i]());
1538 RCP<xdMV> newCoords = Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::coordinateType, LO, GO, NO>::Build(nodeMap, coordDataView(), coords->getNumVectors());
1539 level.
Set(
"Coordinates", newCoords);
1542template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1544 int N = Levels_.size();
1545 if (((sizeOfAllocatedLevelMultiVectors_ == numvecs && residual_.size() == N) || numvecs <= 0) && !forceMapCheck)
return;
1548 if (residual_.size() != N) {
1549 DeleteLevelMultiVectors();
1551 residual_.resize(N);
1552 coarseRhs_.resize(N);
1554 coarseImport_.resize(N);
1555 coarseExport_.resize(N);
1556 correction_.resize(N);
1559 for (
int i = 0; i < N; i++) {
1560 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
1563 RCP<const BlockedCrsMatrix> A_as_blocked = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(A);
1564 RCP<const Map> Arm = A->getRangeMap();
1565 RCP<const Map> Adm = A->getDomainMap();
1566 if (!A_as_blocked.is_null()) {
1567 Adm = A_as_blocked->getFullDomainMap();
1570 if (residual_[i].is_null() || !residual_[i]->getMap()->isSameAs(*Arm))
1572 residual_[i] = MultiVectorFactory::Build(Arm, numvecs,
true);
1573 if (correction_[i].is_null() || !correction_[i]->getMap()->isSameAs(*Adm))
1574 correction_[i] = MultiVectorFactory::Build(Adm, numvecs,
false);
1579 if (implicitTranspose_) {
1580 RCP<Operator> P = Levels_[i + 1]->template Get<RCP<Operator>>(
"P");
1582 RCP<const Map> map = P->getDomainMap();
1583 if (coarseRhs_[i].is_null() || !coarseRhs_[i]->getMap()->isSameAs(*map))
1584 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1587 RCP<Operator> R = Levels_[i + 1]->template Get<RCP<Operator>>(
"R");
1589 RCP<const Map> map = R->getRangeMap();
1590 if (coarseRhs_[i].is_null() || !coarseRhs_[i]->getMap()->isSameAs(*map))
1591 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1595 RCP<const Import> importer;
1596 if (Levels_[i + 1]->IsAvailable(
"Importer"))
1597 importer = Levels_[i + 1]->
template Get<RCP<const Import>>(
"Importer");
1598 if (doPRrebalance_ || importer.is_null()) {
1599 RCP<const Map> map = coarseRhs_[i]->getMap();
1600 if (coarseX_[i].is_null() || !coarseX_[i]->getMap()->isSameAs(*map))
1601 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1604 map = importer->getTargetMap();
1605 if (coarseImport_[i].is_null() || !coarseImport_[i]->getMap()->isSameAs(*map)) {
1606 coarseImport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1607 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1609 map = importer->getSourceMap();
1610 if (coarseExport_[i].is_null() || !coarseExport_[i]->getMap()->isSameAs(*map))
1611 coarseExport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1615 sizeOfAllocatedLevelMultiVectors_ = numvecs;
1618template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1620 if (sizeOfAllocatedLevelMultiVectors_ == 0)
return;
1621 residual_.resize(0);
1622 coarseRhs_.resize(0);
1624 coarseImport_.resize(0);
1625 coarseExport_.resize(0);
1626 correction_.resize(0);
1627 sizeOfAllocatedLevelMultiVectors_ = 0;
1630template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1632 const LO startLevel,
const ConvData& conv)
const {
1633 return (startLevel == 0 && !isPreconditioner_ && (IsPrint(
Statistics1) || conv.
tol_ > 0));
1636template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1638 const Teuchos::Array<MagnitudeType>& residualNorm,
const MagnitudeType convergenceTolerance)
const {
1641 if (convergenceTolerance > Teuchos::ScalarTraits<MagnitudeType>::zero()) {
1643 for (LO k = 0; k < residualNorm.size(); k++)
1644 if (residualNorm[k] >= convergenceTolerance)
1653 return convergenceStatus;
1656template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1658 const LO iteration,
const Teuchos::Array<MagnitudeType>& residualNorm)
const {
1660 << std::setiosflags(std::ios::left)
1661 << std::setprecision(3) << std::setw(4) << iteration
1663 << std::setprecision(10) << residualNorm
1667template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1669 const Operator& A,
const MultiVector& X,
const MultiVector& B,
const LO iteration,
1671 Teuchos::Array<MagnitudeType> residualNorm;
1675 rate_ = currentResidualNorm / previousResidualNorm;
1676 previousResidualNorm = currentResidualNorm;
1679 PrintResidualHistory(iteration, residualNorm);
1681 return IsConverged(residualNorm, conv.
tol_);
static bool debug()
Whether MueLu is in debug mode.
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
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
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.
virtual ~Hierarchy()
Destructor.
void CheckLevel(Level &level, int levelID)
Helper function.
std::string description() const
Return a simple one-line description of this object.
void CheckForEmptySmoothersAndCoarseSolve()
void IsPreconditioner(const bool flag)
Array< RCP< Level > > Levels_
Container for Level objects.
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.
STS::magnitudeType MagnitudeType
void describe(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the Hierarchy with some verbosity level to a FancyOStream object.
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
void SetMatvecParams(RCP< ParameterList > matvecParams)
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.
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.
double GetOperatorComplexity() const
void PrintResidualHistory(const LO iteration, const Teuchos::Array< MagnitudeType > &residualNorm) const
Print residualNorm for this iteration to the screen.
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.
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.
void SetLabel(const std::string &hierarchyLabel)
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
Call Level::AddKeepFlag for each level of the Hierarchy.
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.
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, LocalOrdinal, GlobalOrdinal, Node > &Op, const MultiVector &X, const MultiVector &RHS)
static void SetRandomSeed(const Teuchos::Comm< int > &comm)
Set seed for random number generator.
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const MultiVector &X, const MultiVector &RHS)
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.