10#ifndef MUELU_HIERARCHY_DEF_HPP
11#define MUELU_HIERARCHY_DEF_HPP
18#include <Xpetra_Matrix.hpp>
19#include <Xpetra_MultiVectorFactory.hpp>
20#include <Xpetra_Operator.hpp>
21#include <Xpetra_IO.hpp>
25#include "MueLu_FactoryManager.hpp"
26#include "MueLu_HierarchyUtils.hpp"
27#include "MueLu_TopRAPFactory.hpp"
28#include "MueLu_TopSmootherFactory.hpp"
31#include "MueLu_PerfUtils.hpp"
32#include "MueLu_PFactory.hpp"
33#include "MueLu_SmootherFactory.hpp"
36#include "Teuchos_TimeMonitor.hpp"
40template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
42 : maxCoarseSize_(GetDefaultMaxCoarseSize())
43 , implicitTranspose_(GetDefaultImplicitTranspose())
44 , fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate())
45 , doPRrebalance_(GetDefaultPRrebalance())
46 , doPRViaCopyrebalance_(false)
47 , isPreconditioner_(true)
48 , Cycle_(GetDefaultCycle())
49 , WCycleStartLevel_(0)
50 , scalingFactor_(
Teuchos::ScalarTraits<double>::one())
52 , isDumpingEnabled_(false)
55 , sizeOfAllocatedLevelMultiVectors_(0) {
59template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
63 setObjectLabel(label);
64 Levels_[0]->setObjectLabel(label);
67template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
69 : maxCoarseSize_(GetDefaultMaxCoarseSize())
70 , implicitTranspose_(GetDefaultImplicitTranspose())
71 , fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate())
72 , doPRrebalance_(GetDefaultPRrebalance())
73 , doPRViaCopyrebalance_(false)
74 , isPreconditioner_(true)
75 , Cycle_(GetDefaultCycle())
76 , WCycleStartLevel_(0)
77 , scalingFactor_(
Teuchos::ScalarTraits<double>::one())
78 , isDumpingEnabled_(false)
81 , sizeOfAllocatedLevelMultiVectors_(0) {
82 lib_ = A->getDomainMap()->lib();
84 RCP<Level> Finest = rcp(
new Level);
90template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
93 setObjectLabel(label);
94 Levels_[0]->setObjectLabel(label);
97template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
100template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
102 int levelID = LastLevelID() + 1;
104 if (level->GetLevelID() != -1 && (level->GetLevelID() != levelID))
105 GetOStream(
Warnings1) <<
"Hierarchy::AddLevel(): Level with ID=" << level->GetLevelID() <<
" have been added at the end of the hierarchy\n but its ID have been redefined"
106 <<
" because last level ID of the hierarchy was " << LastLevelID() <<
"." << std::endl;
108 Levels_.push_back(level);
109 level->SetLevelID(levelID);
112 level->SetPreviousLevel((levelID == 0) ? Teuchos::null : Levels_[LastLevelID() - 1]);
113 level->setObjectLabel(this->getObjectLabel());
116template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
118 RCP<Level> newLevel = Levels_[LastLevelID()]->Build();
119 newLevel->setlib(lib_);
120 this->AddLevel(newLevel);
123template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
126 "MueLu::Hierarchy::GetLevel(): invalid input parameter value: LevelID = " << levelID);
127 return Levels_[levelID];
130template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
132 return Levels_.size();
135template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
137 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator>>(
"A");
138 RCP<const Teuchos::Comm<int>> comm = A->getDomainMap()->getComm();
140 int numLevels = GetNumLevels();
142 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, numLevels, Teuchos::ptr(&numGlobalLevels));
144 return numGlobalLevels;
147template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
149 double totalNnz = 0, lev0Nnz = 1;
150 for (
int i = 0; i < GetNumLevels(); ++i) {
152 "Operator complexity cannot be calculated because A is unavailable on level " << i);
153 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
157 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
159 GetOStream(
Warnings0) <<
"Some level operators are not matrices, operator complexity calculation aborted" << std::endl;
163 totalNnz += as<double>(Am->getGlobalNumEntries());
167 return totalNnz / lev0Nnz;
170template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
172 double node_sc = 0, global_sc = 0;
174 const size_t INVALID = Teuchos::OrdinalTraits<size_t>::invalid();
176 if (GetNumLevels() <= 0)
return -1.0;
177 if (!Levels_[0]->IsAvailable(
"A"))
return -1.0;
179 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator>>(
"A");
180 if (A.is_null())
return -1.0;
181 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
182 if (Am.is_null())
return -1.0;
183 a0_nnz = as<double>(Am->getGlobalNumEntries());
186 for (
int i = 0; i < GetNumLevels(); ++i) {
188 if (!Levels_[i]->IsAvailable(
"PreSmoother"))
continue;
189 RCP<SmootherBase> S = Levels_[i]->template Get<RCP<SmootherBase>>(
"PreSmoother");
190 if (S.is_null())
continue;
191 level_sc = S->getNodeSmootherComplexity();
192 if (level_sc == INVALID) {
197 node_sc += as<double>(level_sc);
201 RCP<const Teuchos::Comm<int>> comm = A->getDomainMap()->getComm();
202 Teuchos::reduceAll(*comm, Teuchos::REDUCE_SUM, node_sc, Teuchos::ptr(&global_sc));
203 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MIN, node_sc, Teuchos::ptr(&min_sc));
208 return global_sc / a0_nnz;
212template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
215 "MueLu::Hierarchy::CheckLevel(): wrong underlying linear algebra library.");
217 "MueLu::Hierarchy::CheckLevel(): wrong level ID");
219 "MueLu::Hierarchy::Setup(): wrong level parent");
222template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
224 for (
int i = 0; i < GetNumLevels(); ++i) {
225 RCP<Level> level = Levels_[i];
226 if (level->IsAvailable(
"A")) {
227 RCP<Operator> Aop = level->Get<RCP<Operator>>(
"A");
228 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Aop);
230 RCP<const Import> xpImporter = A->getCrsGraph()->getImporter();
231 if (!xpImporter.is_null())
232 xpImporter->setDistributorParameters(matvecParams);
233 RCP<const Export> xpExporter = A->getCrsGraph()->getExporter();
234 if (!xpExporter.is_null())
235 xpExporter->setDistributorParameters(matvecParams);
238 if (level->IsAvailable(
"P")) {
239 RCP<Matrix> P = level->Get<RCP<Matrix>>(
"P");
240 RCP<const Import> xpImporter = P->getCrsGraph()->getImporter();
241 if (!xpImporter.is_null())
242 xpImporter->setDistributorParameters(matvecParams);
243 RCP<const Export> xpExporter = P->getCrsGraph()->getExporter();
244 if (!xpExporter.is_null())
245 xpExporter->setDistributorParameters(matvecParams);
247 if (level->IsAvailable(
"R")) {
248 RCP<Matrix> R = level->Get<RCP<Matrix>>(
"R");
249 RCP<const Import> xpImporter = R->getCrsGraph()->getImporter();
250 if (!xpImporter.is_null())
251 xpImporter->setDistributorParameters(matvecParams);
252 RCP<const Export> xpExporter = R->getCrsGraph()->getExporter();
253 if (!xpExporter.is_null())
254 xpExporter->setDistributorParameters(matvecParams);
256 if (level->IsAvailable(
"Importer")) {
257 RCP<const Import> xpImporter = level->Get<RCP<const Import>>(
"Importer");
258 if (!xpImporter.is_null())
259 xpImporter->setDistributorParameters(matvecParams);
266template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
268 const RCP<const FactoryManagerBase> fineLevelManager,
269 const RCP<const FactoryManagerBase> coarseLevelManager,
270 const RCP<const FactoryManagerBase> nextLevelManager) {
275 "MueLu::Hierarchy:Setup(): level " << coarseLevelID <<
" (specified by coarseLevelID argument) "
276 "must be built before calling this function.");
278 Level& level = *Levels_[coarseLevelID];
280 bool useStackedTimer = !Teuchos::TimeMonitor::stackedTimerNameIsDefault();
284 if (!useStackedTimer)
285 m1 = rcp(
new TimeMonitor(*
this, label + this->ShortClassName() +
": " +
"Setup (total)"));
286 TimeMonitor m2(*
this, label + this->ShortClassName() +
": " +
"Setup" +
" (total, level=" + Teuchos::toString(coarseLevelID) +
")");
290 "MueLu::Hierarchy::Setup(): argument coarseLevelManager cannot be null");
295 if (levelManagers_.size() < coarseLevelID + 1)
296 levelManagers_.resize(coarseLevelID + 1);
297 levelManagers_[coarseLevelID] = coarseLevelManager;
299 bool isFinestLevel = (fineLevelManager.is_null());
300 bool isLastLevel = (nextLevelManager.is_null());
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();
313 oldRank = SetProcRankVerbose(comm->getRank());
317 lib_ = domainMap->lib();
324 Level& prevLevel = *Levels_[coarseLevelID - 1];
325 oldRank = SetProcRankVerbose(prevLevel.
GetComm()->getRank());
328 CheckLevel(level, coarseLevelID);
331 RCP<SetFactoryManager> SFMFine;
333 SFMFine = rcp(
new SetFactoryManager(Levels_[coarseLevelID - 1], fineLevelManager));
335 if (isFinestLevel && Levels_[coarseLevelID]->IsAvailable(
"Coordinates"))
336 ReplaceCoordinateMap(*Levels_[coarseLevelID]);
341 if (isDumpingEnabled_ && (dumpLevel_ == 0 || dumpLevel_ == -1) && coarseLevelID == 1)
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) {
352 if (nextLevelID > LastLevelID())
354 CheckLevel(*Levels_[nextLevelID], nextLevelID);
358 Levels_[nextLevelID]->Request(
TopRAPFactory(coarseLevelManager, nextLevelManager));
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_) {
430 GetOStream(
Runtime0) <<
"Max coarse size (<= " << maxCoarseSize_ <<
") achieved" << std::endl;
432 if (Acm->getGlobalNumRows() != 0) setLastLevelviaMaxCoarseSize =
true;
436 if (!Ac.is_null() && !isFinestLevel) {
437 RCP<Operator> A = Levels_[coarseLevelID - 1]->template Get<RCP<Operator>>(
"A");
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) {
491 Levels_[nextLevelID]->Release(
TopRAPFactory(coarseLevelManager, nextLevelManager));
497 if (!setLastLevelviaMaxCoarseSize) {
498 if (Levels_[nextLevelID - 1]->IsAvailable(
"P")) {
499 if (Levels_[nextLevelID - 1]->
template Get<RCP<Matrix>>(
"P") == Teuchos::null) actualNumLevels = nextLevelID - 1;
501 actualNumLevels = nextLevelID - 1;
504 if (actualNumLevels == nextLevelID - 1) {
506 Levels_[nextLevelID - 2]->Release(*smootherFact);
508 if (Levels_[nextLevelID - 2]->IsAvailable(
"PreSmoother")) Levels_[nextLevelID - 2]->RemoveKeepFlag(
"PreSmoother",
NoFactory::get());
509 if (Levels_[nextLevelID - 2]->IsAvailable(
"PostSmoother")) Levels_[nextLevelID - 2]->RemoveKeepFlag(
"PostSmoother",
NoFactory::get());
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);
518 levelManagers_.resize(actualNumLevels);
522 if (isDumpingEnabled_ && ((dumpLevel_ > 0 && coarseLevelID == dumpLevel_) || dumpLevel_ == -1))
523 DumpCurrentGraph(coarseLevelID);
525 if (!isFinestLevel) {
529 level.
Release(coarseRAPFactory);
533 SetProcRankVerbose(oldRank);
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++)
550 levelManagers_[i]->ResetDebugData();
555 for (levelID = startLevel; levelID < numLevels;) {
556 bool r = Setup(levelID,
557 (levelID != 0 ? levelManagers_[levelID - 1] : Teuchos::null),
558 levelManagers_[levelID],
559 (levelID + 1 != numLevels ? levelManagers_[levelID + 1] : Teuchos::null));
565 Levels_.resize(levelID);
566 levelManagers_.resize(levelID);
568 int sizeOfVecs = sizeOfAllocatedLevelMultiVectors_;
570 AllocateLevelMultiVectors(sizeOfVecs,
true);
577 CheckForEmptySmoothersAndCoarseSolve();
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");
651 CheckForEmptySmoothersAndCoarseSolve();
654template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
656 for (LO levelNo = 0; levelNo < GetNumLevels(); ++levelNo) {
657 auto level = Levels_[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>
666 if (startLevel < GetNumLevels())
667 GetOStream(
Runtime0) <<
"Clearing old data (if any)" << std::endl;
669 for (
int iLevel = startLevel; iLevel < GetNumLevels(); iLevel++)
670 Levels_[iLevel]->Clear();
673template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
675 GetOStream(
Runtime0) <<
"Clearing old data (expert)" << std::endl;
676 for (
int iLevel = 0; iLevel < GetNumLevels(); iLevel++)
677 Levels_[iLevel]->ExpertClear();
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());
779 for (LO i = 1; i <= nIts; i++) {
780#ifdef HAVE_MUELU_DEBUG
781 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
782 std::ostringstream ss;
783 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
784 throw Exceptions::Incompatible(ss.str());
787 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
788 std::ostringstream ss;
789 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
790 throw Exceptions::Incompatible(ss.str());
795 bool emptyFineSolve =
true;
797 RCP<MultiVector> fineX;
798 fineX = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
807 if (Fine->IsAvailable(
"PreSmoother")) {
808 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
810 preSmoo->Apply(*fineX, B, zeroGuess);
812 emptyFineSolve =
false;
814 if (Fine->IsAvailable(
"PostSmoother")) {
815 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
817 postSmoo->Apply(*fineX, B, zeroGuess);
820 emptyFineSolve =
false;
822 if (emptyFineSolve ==
true) {
824 fineX->update(one, B, zero);
827 if (Levels_.size() > 1) {
829 if (Coarse->IsAvailable(
"PreSmoother")) {
831 preSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
833 emptyCoarseSolve =
false;
835 if (Coarse->IsAvailable(
"PostSmoother")) {
837 postSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
839 emptyCoarseSolve =
false;
841 if (emptyCoarseSolve ==
true) {
843 coarseX->update(one, *coarseRhs, zero);
850 if (!doPRrebalance_ && !importer.is_null()) {
851 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export (total)",
Timings0));
852 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
855 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getSourceMap(), coarseX->getNumVectors());
856 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
857 coarseX.swap(coarseTmp);
861 Pbar->apply(*coarseX, *coarseX_prolonged, Teuchos::NO_TRANS, one, zero);
866 X.update(1.0, *fineX, 1.0, *coarseX_prolonged, 0.0);
877template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
879 bool InitialGuessIsZero, LO startLevel) {
895 RCP<Level> Fine = Levels_[startLevel];
898 std::string prefix = label + this->ShortClassName() +
": ";
899 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
900 std::string levelSuffix1 =
" (level=" +
toString(startLevel + 1) +
")";
902 bool useStackedTimer = !Teuchos::TimeMonitor::stackedTimerNameIsDefault();
904 RCP<Monitor> iterateTime;
905 RCP<TimeMonitor> iterateTime1;
908 else if (!useStackedTimer)
911 std::string iterateLevelTimeLabel = prefix +
"Solve" + levelSuffix;
912 RCP<TimeMonitor> iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel,
Timings0));
914 bool zeroGuess = InitialGuessIsZero;
916 RCP<Operator> A = Fine->Get<RCP<Operator>>(
"A");
918 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
931 const BlockedMultiVector* Bblocked =
dynamic_cast<const BlockedMultiVector*
>(&B);
932 if (residual_.size() > startLevel &&
933 ((Bblocked && !Bblocked->isSameSize(*residual_[startLevel])) ||
934 (!Bblocked && !residual_[startLevel]->isSameSize(B))))
935 DeleteLevelMultiVectors();
936 AllocateLevelMultiVectors(X.getNumVectors());
939 typedef Teuchos::ScalarTraits<typename STS::magnitudeType> STM;
942 if (IsCalculationOfResidualRequired(startLevel, conv)) {
943 ConvergenceStatus convergenceStatus = ComputeResidualAndPrintHistory(*A, X, B, Teuchos::ScalarTraits<LO>::zero(), startLevel, conv, prevNorm);
945 return convergenceStatus;
948 SC one = STS::one(), zero = STS::zero();
949 for (LO iteration = 1; iteration <= nIts; iteration++) {
950#ifdef HAVE_MUELU_DEBUG
952 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
953 std::ostringstream ss;
954 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
958 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
959 std::ostringstream ss;
960 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
966 if (startLevel == as<LO>(Levels_.size()) - 1) {
968 RCP<TimeMonitor> CLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : coarse" + levelSuffix,
Timings0));
970 bool emptySolve =
true;
973 if (Fine->IsAvailable(
"PreSmoother")) {
974 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
976 preSmoo->Apply(X, B, zeroGuess);
981 if (Fine->IsAvailable(
"PostSmoother")) {
982 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
984 postSmoo->Apply(X, B, zeroGuess);
989 if (emptySolve ==
true) {
991 X.update(one, B, zero);
996 RCP<Level> Coarse = Levels_[startLevel + 1];
999 RCP<TimeMonitor> STime;
1000 if (!useStackedTimer)
1002 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1004 if (Fine->IsAvailable(
"PreSmoother")) {
1005 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
1006 preSmoo->Apply(X, B, zeroGuess);
1011 RCP<MultiVector> residual;
1013 RCP<TimeMonitor> ATime;
1014 if (!useStackedTimer)
1015 ATime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : residual calculation (total)",
Timings0));
1016 RCP<TimeMonitor> ALevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : residual calculation" + levelSuffix,
Timings0));
1024 residual = residual_[startLevel];
1027 RCP<Operator> P = Coarse->Get<RCP<Operator>>(
"P");
1028 if (Coarse->IsAvailable(
"Pbar"))
1029 P = Coarse->Get<RCP<Operator>>(
"Pbar");
1031 RCP<MultiVector> coarseRhs, coarseX;
1035 RCP<TimeMonitor> RTime;
1036 if (!useStackedTimer)
1038 RCP<TimeMonitor> RLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : restriction" + levelSuffix,
Timings0));
1039 coarseRhs = coarseRhs_[startLevel];
1041 if (implicitTranspose_) {
1042 P->apply(*residual, *coarseRhs, Teuchos::TRANS, one, zero);
1045 RCP<Operator> R = Coarse->Get<RCP<Operator>>(
"R");
1046 R->apply(*residual, *coarseRhs, Teuchos::NO_TRANS, one, zero);
1050 RCP<const Import> importer;
1051 if (Coarse->IsAvailable(
"Importer"))
1052 importer = Coarse->Get<RCP<const Import>>(
"Importer");
1054 coarseX = coarseX_[startLevel];
1055 if (!doPRrebalance_ && !importer.is_null()) {
1056 RCP<TimeMonitor> ITime;
1057 if (!useStackedTimer)
1059 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
1062 RCP<MultiVector> coarseTmp = coarseImport_[startLevel];
1063 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
1064 coarseRhs.swap(coarseTmp);
1067 RCP<Operator> Ac = Coarse->Get<RCP<Operator>>(
"A");
1068 if (!Ac.is_null()) {
1069 RCP<const Map> origXMap = coarseX->getMap();
1070 RCP<const Map> origRhsMap = coarseRhs->getMap();
1073 coarseRhs->replaceMap(Ac->getRangeMap());
1074 coarseX->replaceMap(Ac->getDomainMap());
1077 iterateLevelTime = Teuchos::null;
1079 Iterate(*coarseRhs, *coarseX, 1,
true, startLevel + 1);
1081 if (Cycle_ ==
WCYCLE && WCycleStartLevel_ <= startLevel)
1082 Iterate(*coarseRhs, *coarseX, 1,
false, startLevel + 1);
1085 iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel));
1087 coarseX->replaceMap(origXMap);
1088 coarseRhs->replaceMap(origRhsMap);
1091 if (!doPRrebalance_ && !importer.is_null()) {
1092 RCP<TimeMonitor> ITime;
1093 if (!useStackedTimer)
1095 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
1098 RCP<MultiVector> coarseTmp = coarseExport_[startLevel];
1099 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
1100 coarseX.swap(coarseTmp);
1105 RCP<TimeMonitor> PTime;
1106 if (!useStackedTimer)
1108 RCP<TimeMonitor> PLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : prolongation" + levelSuffix,
Timings0));
1113 if (fuseProlongationAndUpdate_) {
1114 P->apply(*coarseX, X, Teuchos::NO_TRANS, scalingFactor_, one);
1116 RCP<MultiVector> correction = correction_[startLevel];
1117 P->apply(*coarseX, *correction, Teuchos::NO_TRANS, one, zero);
1118 X.update(scalingFactor_, *correction, one);
1124 RCP<TimeMonitor> STime;
1125 if (!useStackedTimer)
1127 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1129 if (Fine->IsAvailable(
"PostSmoother")) {
1130 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
1131 postSmoo->Apply(X, B,
false);
1137 if (IsCalculationOfResidualRequired(startLevel, conv)) {
1138 ConvergenceStatus convergenceStatus = ComputeResidualAndPrintHistory(*A, X, B, iteration, startLevel, conv, prevNorm);
1140 return convergenceStatus;
1147template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1149 LO startLevel = (start != -1 ? start : 0);
1150 LO endLevel = (end != -1 ? end : Levels_.size() - 1);
1153 "MueLu::Hierarchy::Write : startLevel must be <= endLevel");
1156 "MueLu::Hierarchy::Write bad start or end level");
1158 for (LO i = startLevel; i < endLevel + 1; i++) {
1159 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get<RCP<Operator>>(
"A")), P, R;
1161 P = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get<RCP<Operator>>(
"P"));
1162 if (!implicitTranspose_)
1163 R = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get<RCP<Operator>>(
"R"));
1166 if (!A.is_null()) Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"A_" +
toString(i) + suffix +
".m", *A);
1168 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"P_" +
toString(i) + suffix +
".m", *P);
1171 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"R_" +
toString(i) + suffix +
".m", *R);
1176template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1178 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1179 (*it)->Keep(ename, factory);
1182template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1184 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1185 (*it)->Delete(ename, factory);
1188template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1190 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1191 (*it)->AddKeepFlag(ename, factory, keep);
1194template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1196 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1197 (*it)->RemoveKeepFlag(ename, factory, keep);
1200template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1202 if (description_.empty()) {
1203 std::ostringstream out;
1205 out <<
"{#levels = " << GetGlobalNumLevels() <<
", complexity = " << GetOperatorComplexity() <<
"}";
1206 description_ = out.str();
1208 return description_;
1211template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1216template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1218 RCP<Operator> A0 = Levels_[0]->template Get<RCP<Operator>>(
"A");
1219 RCP<const Teuchos::Comm<int>> comm = A0->getDomainMap()->getComm();
1221 int numLevels = GetNumLevels();
1222 RCP<Operator> Ac = Levels_[numLevels - 1]->template Get<RCP<Operator>>(
"A");
1229 int root = comm->getRank();
1232 int smartData = numLevels * comm->getSize() + comm->getRank(), maxSmartData;
1233 reduceAll(*comm, Teuchos::REDUCE_MAX, smartData, Teuchos::ptr(&maxSmartData));
1234 root = maxSmartData % comm->getSize();
1238 double smoother_comp = -1.0;
1240 smoother_comp = GetSmootherComplexity();
1244 std::vector<Xpetra::global_size_t> nnzPerLevel;
1245 std::vector<Xpetra::global_size_t> rowsPerLevel;
1246 std::vector<int> numProcsPerLevel;
1247 bool someOpsNotMatrices =
false;
1248 const Xpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1249 for (
int i = 0; i < numLevels; i++) {
1251 "Operator A is not available on level " << i);
1253 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
1255 "Operator A on level " << i <<
" is null.");
1257 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
1259 someOpsNotMatrices =
true;
1260 nnzPerLevel.push_back(INVALID);
1261 rowsPerLevel.push_back(A->getDomainMap()->getGlobalNumElements());
1262 numProcsPerLevel.push_back(A->getDomainMap()->getComm()->getSize());
1264 LO storageblocksize = Am->GetStorageBlockSize();
1265 Xpetra::global_size_t nnz = Am->getGlobalNumEntries() * storageblocksize * storageblocksize;
1266 nnzPerLevel.push_back(nnz);
1267 rowsPerLevel.push_back(Am->getGlobalNumRows() * storageblocksize);
1268 numProcsPerLevel.push_back(Am->getRowMap()->getComm()->getSize());
1271 if (someOpsNotMatrices)
1272 GetOStream(
Warnings0) <<
"Some level operators are not matrices, statistics calculation are incomplete" << std::endl;
1275 std::string label = Levels_[0]->getObjectLabel();
1276 std::ostringstream oss;
1277 oss << std::setfill(
' ');
1278 oss <<
"\n--------------------------------------------------------------------------------\n";
1279 oss <<
"--- Multigrid Summary " << std::setw(32) <<
"---\n";
1280 oss <<
"--------------------------------------------------------------------------------" << std::endl;
1281 if (hierarchyLabel_ !=
"") oss <<
"Label = " << hierarchyLabel_ << std::endl;
1283 oss <<
"Scalar = " << Teuchos::ScalarTraits<Scalar>::name() << std::endl;
1284 oss <<
"Number of levels = " << numLevels << std::endl;
1285 oss <<
"Operator complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1286 if (!someOpsNotMatrices)
1287 oss << GetOperatorComplexity() << std::endl;
1289 oss <<
"not available (Some operators in hierarchy are not matrices.)" << std::endl;
1291 if (smoother_comp != -1.0) {
1292 oss <<
"Smoother complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1293 << smoother_comp << std::endl;
1298 oss <<
"Cycle type = V" << std::endl;
1301 oss <<
"Cycle type = W" << std::endl;
1302 if (WCycleStartLevel_ > 0)
1303 oss <<
"Cycle start level = " << WCycleStartLevel_ << std::endl;
1310 Xpetra::global_size_t tt = rowsPerLevel[0];
1316 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1317 tt = nnzPerLevel[i];
1327 tt = numProcsPerLevel[0];
1333 oss <<
"level " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz "
1334 <<
" nnz/row" << std::setw(npspacer) <<
" c ratio"
1335 <<
" procs" << std::endl;
1336 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1337 oss <<
" " << i <<
" ";
1338 oss << std::setw(rowspacer) << rowsPerLevel[i];
1339 if (nnzPerLevel[i] != INVALID) {
1340 oss << std::setw(nnzspacer) << nnzPerLevel[i];
1341 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1342 oss << std::setw(9) << as<double>(nnzPerLevel[i]) / rowsPerLevel[i];
1344 oss << std::setw(nnzspacer) <<
"Operator";
1345 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1346 oss << std::setw(9) <<
" ";
1349 oss << std::setw(9) << as<double>(rowsPerLevel[i - 1]) / rowsPerLevel[i];
1351 oss << std::setw(9) <<
" ";
1352 oss <<
" " << std::setw(npspacer) << numProcsPerLevel[i] << std::endl;
1355 for (
int i = 0; i < GetNumLevels(); ++i) {
1356 RCP<SmootherBase> preSmoo, postSmoo;
1357 if (Levels_[i]->IsAvailable(
"PreSmoother"))
1358 preSmoo = Levels_[i]->
template Get<RCP<SmootherBase>>(
"PreSmoother");
1359 if (Levels_[i]->IsAvailable(
"PostSmoother"))
1360 postSmoo = Levels_[i]->
template Get<RCP<SmootherBase>>(
"PostSmoother");
1362 if (preSmoo != null && preSmoo == postSmoo)
1363 oss <<
"Smoother (level " << i <<
") both : " << preSmoo->description() << std::endl;
1365 oss <<
"Smoother (level " << i <<
") pre : "
1366 << (preSmoo != null ? preSmoo->description() :
"no smoother") << std::endl;
1367 oss <<
"Smoother (level " << i <<
") post : "
1368 << (postSmoo != null ? postSmoo->description() :
"no smoother") << std::endl;
1379 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
1380 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1382 int strLength = outstr.size();
1383 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1384 if (comm->getRank() != root)
1385 outstr.resize(strLength);
1386 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1393template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1395 Teuchos::OSTab tab2(out);
1396 for (
int i = 0; i < GetNumLevels(); ++i)
1397 Levels_[i]->print(out, verbLevel);
1400template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1402 isPreconditioner_ = flag;
1405template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1407 if (GetProcRankVerbose() != 0)
1409#if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
1414 dp.property(
"label", boost::get(boost::vertex_name, graph));
1415 dp.property(
"id", boost::get(boost::vertex_index, graph));
1416 dp.property(
"label", boost::get(boost::edge_name, graph));
1417 dp.property(
"color", boost::get(boost::edge_color, graph));
1420 std::map<const FactoryBase*, BoostVertex> vindices;
1421 typedef std::map<std::pair<BoostVertex, BoostVertex>, std::string> emap;
1424 static int call_id = 0;
1426 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator>>(
"A");
1427 int rank = A->getDomainMap()->getComm()->getRank();
1430 for (
int i = currLevel; i <= currLevel + 1 && i < GetNumLevels(); i++) {
1432 Levels_[i]->UpdateGraph(vindices, edges, dp, graph);
1434 for (emap::const_iterator eit = edges.begin(); eit != edges.end(); eit++) {
1435 std::pair<BoostEdge, bool> boost_edge = boost::add_edge(eit->first.first, eit->first.second, graph);
1438 if (eit->second == std::string(
"Graph"))
1439 boost::put(
"label", dp, boost_edge.first, std::string(
"Graph_"));
1441 boost::put(
"label", dp, boost_edge.first, eit->second);
1443 boost::put(
"color", dp, boost_edge.first, std::string(
"red"));
1445 boost::put(
"color", dp, boost_edge.first, std::string(
"blue"));
1449 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"));
1450 boost::write_graphviz_dp(out, graph, dp, std::string(
"id"));
1454 GetOStream(
Errors) <<
"Dependency graph output requires boost and MueLu_ENABLE_Boost_for_real" << std::endl;
1459template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1461 RCP<Operator> Ao = level.
Get<RCP<Operator>>(
"A");
1462 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Ao);
1464 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is not a matrix, skipping..." << std::endl;
1467 if (Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A) != Teuchos::null) {
1468 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is a BlockedCrsMatrix, skipping..." << std::endl;
1472 typedef Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::coordinateType, LO, GO, NO> xdMV;
1474 RCP<xdMV> coords = level.
Get<RCP<xdMV>>(
"Coordinates");
1476 if (A->getRowMap()->isSameAs(*(coords->getMap()))) {
1477 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: matrix and coordinates maps are same, skipping..." << std::endl;
1481 if (A->IsView(
"stridedMaps") && rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps")) != Teuchos::null) {
1482 RCP<const StridedMap> stridedRowMap = rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps"));
1485 TEUCHOS_TEST_FOR_EXCEPTION(stridedRowMap->getStridedBlockId() != -1 || stridedRowMap->getOffset() != 0,
1486 Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: nontrivial maps (block id = " << stridedRowMap->getStridedBlockId() <<
", offset = " << stridedRowMap->getOffset() <<
")");
1489 GetOStream(
Runtime1) <<
"Replacing coordinate map" << std::endl;
1490 TEUCHOS_TEST_FOR_EXCEPTION(A->GetFixedBlockSize() % A->GetStorageBlockSize() != 0,
Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: Storage block size does not evenly divide fixed block size");
1492 size_t blkSize = A->GetFixedBlockSize() / A->GetStorageBlockSize();
1494 RCP<const Map> nodeMap = A->getRowMap();
1497 RCP<const Map> dofMap = A->getRowMap();
1498 GO indexBase = dofMap->getIndexBase();
1499 size_t numLocalDOFs = dofMap->getLocalNumElements();
1501 "Hierarchy::ReplaceCoordinateMap: block size (" << blkSize <<
") is incompatible with the number of local dofs in a row map (" << numLocalDOFs);
1502 ArrayView<const GO> GIDs = dofMap->getLocalElementList();
1504 Array<GO> nodeGIDs(numLocalDOFs / blkSize);
1505 for (
size_t i = 0; i < numLocalDOFs; i += blkSize)
1506 nodeGIDs[i / blkSize] = (GIDs[i] - indexBase) / blkSize + indexBase;
1508 Xpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1509 nodeMap = MapFactory::Build(dofMap->lib(), INVALID, nodeGIDs(), indexBase, dofMap->getComm());
1515 if (coords->getLocalLength() != A->getRowMap()->getLocalNumElements()) {
1516 GetOStream(
Warnings) <<
"Coordinate vector does not match row map of matrix A!" << std::endl;
1521 Array<ArrayView<const typename Teuchos::ScalarTraits<Scalar>::coordinateType>> coordDataView;
1522 std::vector<ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType>> coordData;
1523 for (
size_t i = 0; i < coords->getNumVectors(); i++) {
1524 coordData.push_back(coords->getData(i));
1525 coordDataView.push_back(coordData[i]());
1528 RCP<xdMV> newCoords = Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::coordinateType, LO, GO, NO>::Build(nodeMap, coordDataView(), coords->getNumVectors());
1529 level.
Set(
"Coordinates", newCoords);
1532template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1534 int N = Levels_.size();
1535 if (((sizeOfAllocatedLevelMultiVectors_ == numvecs && residual_.size() == N) || numvecs <= 0) && !forceMapCheck)
return;
1538 if (residual_.size() != N) {
1539 DeleteLevelMultiVectors();
1541 residual_.resize(N);
1542 coarseRhs_.resize(N);
1544 coarseImport_.resize(N);
1545 coarseExport_.resize(N);
1546 correction_.resize(N);
1549 for (
int i = 0; i < N; i++) {
1550 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
1553 RCP<const BlockedCrsMatrix> A_as_blocked = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(A);
1554 RCP<const Map> Arm = A->getRangeMap();
1555 RCP<const Map> Adm = A->getDomainMap();
1556 if (!A_as_blocked.is_null()) {
1557 Adm = A_as_blocked->getFullDomainMap();
1560 if (residual_[i].is_null() || !residual_[i]->getMap()->isSameAs(*Arm))
1562 residual_[i] = MultiVectorFactory::Build(Arm, numvecs,
true);
1563 if (correction_[i].is_null() || !correction_[i]->getMap()->isSameAs(*Adm))
1564 correction_[i] = MultiVectorFactory::Build(Adm, numvecs,
false);
1569 if (implicitTranspose_) {
1570 RCP<Operator> P = Levels_[i + 1]->template Get<RCP<Operator>>(
"P");
1572 RCP<const Map> map = P->getDomainMap();
1573 if (coarseRhs_[i].is_null() || !coarseRhs_[i]->getMap()->isSameAs(*map))
1574 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1577 RCP<Operator> R = Levels_[i + 1]->template Get<RCP<Operator>>(
"R");
1579 RCP<const Map> map = R->getRangeMap();
1580 if (coarseRhs_[i].is_null() || !coarseRhs_[i]->getMap()->isSameAs(*map))
1581 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1585 RCP<const Import> importer;
1586 if (Levels_[i + 1]->IsAvailable(
"Importer"))
1587 importer = Levels_[i + 1]->
template Get<RCP<const Import>>(
"Importer");
1588 if (doPRrebalance_ || importer.is_null()) {
1589 RCP<const Map> map = coarseRhs_[i]->getMap();
1590 if (coarseX_[i].is_null() || !coarseX_[i]->getMap()->isSameAs(*map))
1591 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1594 map = importer->getTargetMap();
1595 if (coarseImport_[i].is_null() || !coarseImport_[i]->getMap()->isSameAs(*map)) {
1596 coarseImport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1597 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1599 map = importer->getSourceMap();
1600 if (coarseExport_[i].is_null() || !coarseExport_[i]->getMap()->isSameAs(*map))
1601 coarseExport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1605 sizeOfAllocatedLevelMultiVectors_ = numvecs;
1608template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1610 if (sizeOfAllocatedLevelMultiVectors_ == 0)
return;
1611 residual_.resize(0);
1612 coarseRhs_.resize(0);
1614 coarseImport_.resize(0);
1615 coarseExport_.resize(0);
1616 correction_.resize(0);
1617 sizeOfAllocatedLevelMultiVectors_ = 0;
1620template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1622 const LO startLevel,
const ConvData& conv)
const {
1623 return (startLevel == 0 && !isPreconditioner_ && (IsPrint(
Statistics1) || conv.
tol_ > 0));
1626template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1628 const Teuchos::Array<MagnitudeType>& residualNorm,
const MagnitudeType convergenceTolerance)
const {
1631 if (convergenceTolerance > Teuchos::ScalarTraits<MagnitudeType>::zero()) {
1633 for (LO k = 0; k < residualNorm.size(); k++)
1634 if (residualNorm[k] >= convergenceTolerance)
1643 return convergenceStatus;
1646template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1648 const LO iteration,
const Teuchos::Array<MagnitudeType>& residualNorm)
const {
1650 << std::setiosflags(std::ios::left)
1651 << std::setprecision(3) << std::setw(4) << iteration
1653 << std::setprecision(10) << residualNorm
1657template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1659 const Operator& A,
const MultiVector& X,
const MultiVector& B,
const LO iteration,
1661 Teuchos::Array<MagnitudeType> residualNorm;
1665 rate_ = currentResidualNorm / previousResidualNorm;
1666 previousResidualNorm = currentResidualNorm;
1669 PrintResidualHistory(iteration, residualNorm);
1671 return IsConverged(residualNorm, conv.
tol_);
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.