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);
521 if (isDumpingEnabled_ && ((dumpLevel_ > 0 && coarseLevelID == dumpLevel_) || dumpLevel_ == -1))
522 DumpCurrentGraph(coarseLevelID);
524 if (!isFinestLevel) {
528 level.
Release(coarseRAPFactory);
532 SetProcRankVerbose(oldRank);
537template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
539 int numLevels = Levels_.size();
541 "Hierarchy::SetupRe: " << Levels_.size() <<
" levels, but " << levelManagers_.size() <<
" level factory managers");
543 const int startLevel = 0;
546#ifdef HAVE_MUELU_DEBUG
548 for (
int i = 0; i < numLevels; i++)
549 levelManagers_[i]->ResetDebugData();
554 for (levelID = startLevel; levelID < numLevels;) {
555 bool r = Setup(levelID,
556 (levelID != 0 ? levelManagers_[levelID - 1] : Teuchos::null),
557 levelManagers_[levelID],
558 (levelID + 1 != numLevels ? levelManagers_[levelID + 1] : Teuchos::null));
564 Levels_.resize(levelID);
565 levelManagers_.resize(levelID);
567 int sizeOfVecs = sizeOfAllocatedLevelMultiVectors_;
569 AllocateLevelMultiVectors(sizeOfVecs,
true);
576 CheckForEmptySmoothersAndCoarseSolve();
579template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
588 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") does not exist");
591 "Constructing non-positive (" << numDesiredLevels <<
") number of levels does not make sense.");
595 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") has no matrix A! "
596 "Set fine level matrix A using Level.Set()");
598 RCP<Operator> A = Levels_[startLevel]->template Get<RCP<Operator>>(
"A");
599 lib_ = A->getDomainMap()->lib();
602 RCP<Matrix> Amat = rcp_dynamic_cast<Matrix>(A);
604 if (!Amat.is_null()) {
605 RCP<ParameterList> params = rcp(
new ParameterList());
606 params->set(
"printLoadBalancingInfo",
true);
607 params->set(
"printCommInfo",
true);
611 GetOStream(
Warnings1) <<
"Fine level operator is not a matrix, statistics are not available" << std::endl;
615 RCP<const FactoryManagerBase> rcpmanager = rcpFromRef(manager);
617 const int lastLevel = startLevel + numDesiredLevels - 1;
618 GetOStream(
Runtime0) <<
"Setup loop: startLevel = " << startLevel <<
", lastLevel = " << lastLevel
619 <<
" (stop if numLevels = " << numDesiredLevels <<
" or Ac.size() < " << maxCoarseSize_ <<
")" << std::endl;
623 if (numDesiredLevels == 1) {
625 Setup(startLevel, Teuchos::null, rcpmanager, Teuchos::null);
628 bool bIsLastLevel = Setup(startLevel, Teuchos::null, rcpmanager, rcpmanager);
629 if (bIsLastLevel ==
false) {
630 for (iLevel = startLevel + 1; iLevel < lastLevel; iLevel++) {
631 bIsLastLevel = Setup(iLevel, rcpmanager, rcpmanager, rcpmanager);
632 if (bIsLastLevel ==
true)
635 if (bIsLastLevel ==
false)
636 Setup(lastLevel, rcpmanager, rcpmanager, Teuchos::null);
642 "MueLu::Hierarchy::Setup(): number of level");
650 CheckForEmptySmoothersAndCoarseSolve();
653template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
655 for (LO levelNo = 0; levelNo < GetNumLevels(); ++levelNo) {
656 auto level = Levels_[levelNo];
657 if ((level->IsAvailable(
"A") && !level->template Get<RCP<Operator>>(
"A").is_null()) && (!level->IsAvailable(
"PreSmoother")) && (!level->IsAvailable(
"PostSmoother"))) {
658 GetOStream(
Warnings1) <<
"No " << (levelNo == as<LO>(Levels_.size()) - 1 ?
"coarse grid solver" :
"smoother") <<
" on level " << level->GetLevelID() << std::endl;
663template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
665 if (startLevel < GetNumLevels())
666 GetOStream(
Runtime0) <<
"Clearing old data (if any)" << std::endl;
668 for (
int iLevel = startLevel; iLevel < GetNumLevels(); iLevel++)
669 Levels_[iLevel]->Clear();
672template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
674 GetOStream(
Runtime0) <<
"Clearing old data (expert)" << std::endl;
675 for (
int iLevel = 0; iLevel < GetNumLevels(); iLevel++)
676 Levels_[iLevel]->ExpertClear();
679#if defined(HAVE_MUELU_EXPERIMENTAL) && defined(HAVE_MUELU_ADDITIVE_VARIANT)
680template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
682 bool InitialGuessIsZero, LO startLevel) {
683 LO nIts = conv.maxIts_;
684 MagnitudeType tol = conv.tol_;
686 std::string prefix = this->ShortClassName() +
": ";
687 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
688 std::string levelSuffix1 =
" (level=" +
toString(startLevel + 1) +
")";
691 RCP<Time> CompTime = Teuchos::TimeMonitor::getNewCounter(prefix +
"Computational Time (total)");
692 RCP<Time> Concurrent = Teuchos::TimeMonitor::getNewCounter(prefix +
"Concurrent portion");
693 RCP<Time> ApplyR = Teuchos::TimeMonitor::getNewCounter(prefix +
"R: Computational Time");
694 RCP<Time> ApplyPbar = Teuchos::TimeMonitor::getNewCounter(prefix +
"Pbar: Computational Time");
695 RCP<Time> CompFine = Teuchos::TimeMonitor::getNewCounter(prefix +
"Fine: Computational Time");
696 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
697 RCP<Time> ApplySum = Teuchos::TimeMonitor::getNewCounter(prefix +
"Sum: Computational Time");
698 RCP<Time> Synchronize_beginning = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_beginning");
699 RCP<Time> Synchronize_center = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_center");
700 RCP<Time> Synchronize_end = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_end");
702 RCP<Level> Fine = Levels_[0];
705 RCP<Operator> A = Fine->Get<RCP<Operator>>(
"A");
706 Teuchos::RCP<const Teuchos::Comm<int>> communicator = A->getDomainMap()->getComm();
714 SC one = STS::one(), zero = STS::zero();
716 bool zeroGuess = InitialGuessIsZero;
724 RCP<MultiVector> coarseRhs, coarseX;
726 RCP<SmootherBase> preSmoo_coarse, postSmoo_coarse;
727 bool emptyCoarseSolve =
true;
728 RCP<MultiVector> coarseX_prolonged = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
730 RCP<const Import> importer;
732 if (Levels_.size() > 1) {
734 if (Coarse->IsAvailable(
"Importer"))
735 importer = Coarse->Get<RCP<const Import>>(
"Importer");
737 R = Coarse->Get<RCP<Operator>>(
"R");
738 P = Coarse->Get<RCP<Operator>>(
"P");
741 Pbar = Coarse->Get<RCP<Operator>>(
"Pbar");
743 coarseRhs = MultiVectorFactory::Build(R->getRangeMap(), B.getNumVectors(),
true);
745 Ac = Coarse->Get<RCP<Operator>>(
"A");
748 R->apply(B, *coarseRhs, Teuchos::NO_TRANS, one, zero);
752 if (doPRrebalance_ || importer.is_null()) {
753 coarseX = MultiVectorFactory::Build(coarseRhs->getMap(), X.getNumVectors(),
true);
756 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import (total)",
Timings0));
757 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
760 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getTargetMap(), coarseRhs->getNumVectors());
761 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
762 coarseRhs.swap(coarseTmp);
764 coarseX = MultiVectorFactory::Build(importer->getTargetMap(), X.getNumVectors(),
true);
767 if (Coarse->IsAvailable(
"PreSmoother"))
768 preSmoo_coarse = Coarse->Get<RCP<SmootherBase>>(
"PreSmoother");
769 if (Coarse->IsAvailable(
"PostSmoother"))
770 postSmoo_coarse = Coarse->Get<RCP<SmootherBase>>(
"PostSmoother");
775 MagnitudeType prevNorm = STS::magnitude(STS::one()), curNorm = STS::magnitude(STS::one());
778 for (LO i = 1; i <= nIts; i++) {
779#ifdef HAVE_MUELU_DEBUG
780 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
781 std::ostringstream ss;
782 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
783 throw Exceptions::Incompatible(ss.str());
786 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
787 std::ostringstream ss;
788 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
789 throw Exceptions::Incompatible(ss.str());
794 bool emptyFineSolve =
true;
796 RCP<MultiVector> fineX;
797 fineX = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
806 if (Fine->IsAvailable(
"PreSmoother")) {
807 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
809 preSmoo->Apply(*fineX, B, zeroGuess);
811 emptyFineSolve =
false;
813 if (Fine->IsAvailable(
"PostSmoother")) {
814 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
816 postSmoo->Apply(*fineX, B, zeroGuess);
819 emptyFineSolve =
false;
821 if (emptyFineSolve ==
true) {
823 fineX->update(one, B, zero);
826 if (Levels_.size() > 1) {
828 if (Coarse->IsAvailable(
"PreSmoother")) {
830 preSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
832 emptyCoarseSolve =
false;
834 if (Coarse->IsAvailable(
"PostSmoother")) {
836 postSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
838 emptyCoarseSolve =
false;
840 if (emptyCoarseSolve ==
true) {
842 coarseX->update(one, *coarseRhs, zero);
849 if (!doPRrebalance_ && !importer.is_null()) {
850 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export (total)",
Timings0));
851 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
854 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getSourceMap(), coarseX->getNumVectors());
855 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
856 coarseX.swap(coarseTmp);
860 Pbar->apply(*coarseX, *coarseX_prolonged, Teuchos::NO_TRANS, one, zero);
865 X.update(1.0, *fineX, 1.0, *coarseX_prolonged, 0.0);
876template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
878 bool InitialGuessIsZero, LO startLevel) {
894 RCP<Level> Fine = Levels_[startLevel];
897 std::string prefix = label + this->ShortClassName() +
": ";
898 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
899 std::string levelSuffix1 =
" (level=" +
toString(startLevel + 1) +
")";
901 bool useStackedTimer = !Teuchos::TimeMonitor::stackedTimerNameIsDefault();
903 RCP<Monitor> iterateTime;
904 RCP<TimeMonitor> iterateTime1;
907 else if (!useStackedTimer)
910 std::string iterateLevelTimeLabel = prefix +
"Solve" + levelSuffix;
911 RCP<TimeMonitor> iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel,
Timings0));
913 bool zeroGuess = InitialGuessIsZero;
915 RCP<Operator> A = Fine->Get<RCP<Operator>>(
"A");
917 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
930 const BlockedMultiVector* Bblocked =
dynamic_cast<const BlockedMultiVector*
>(&B);
931 if (residual_.size() > startLevel &&
932 ((Bblocked && !Bblocked->isSameSize(*residual_[startLevel])) ||
933 (!Bblocked && !residual_[startLevel]->isSameSize(B))))
934 DeleteLevelMultiVectors();
935 AllocateLevelMultiVectors(X.getNumVectors());
938 typedef Teuchos::ScalarTraits<typename STS::magnitudeType> STM;
941 if (IsCalculationOfResidualRequired(startLevel, conv)) {
942 ConvergenceStatus convergenceStatus = ComputeResidualAndPrintHistory(*A, X, B, Teuchos::ScalarTraits<LO>::zero(), startLevel, conv, prevNorm);
944 return convergenceStatus;
947 SC one = STS::one(), zero = STS::zero();
948 for (LO iteration = 1; iteration <= nIts; iteration++) {
949#ifdef HAVE_MUELU_DEBUG
951 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
952 std::ostringstream ss;
953 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
957 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
958 std::ostringstream ss;
959 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
965 if (startLevel == as<LO>(Levels_.size()) - 1) {
967 RCP<TimeMonitor> CLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : coarse" + levelSuffix,
Timings0));
969 bool emptySolve =
true;
972 if (Fine->IsAvailable(
"PreSmoother")) {
973 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
975 preSmoo->Apply(X, B, zeroGuess);
980 if (Fine->IsAvailable(
"PostSmoother")) {
981 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
983 postSmoo->Apply(X, B, zeroGuess);
988 if (emptySolve ==
true) {
990 X.update(one, B, zero);
995 RCP<Level> Coarse = Levels_[startLevel + 1];
998 RCP<TimeMonitor> STime;
999 if (!useStackedTimer)
1001 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1003 if (Fine->IsAvailable(
"PreSmoother")) {
1004 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
1005 preSmoo->Apply(X, B, zeroGuess);
1010 RCP<MultiVector> residual;
1012 RCP<TimeMonitor> ATime;
1013 if (!useStackedTimer)
1014 ATime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : residual calculation (total)",
Timings0));
1015 RCP<TimeMonitor> ALevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : residual calculation" + levelSuffix,
Timings0));
1023 residual = residual_[startLevel];
1026 RCP<Operator> P = Coarse->Get<RCP<Operator>>(
"P");
1027 if (Coarse->IsAvailable(
"Pbar"))
1028 P = Coarse->Get<RCP<Operator>>(
"Pbar");
1030 RCP<MultiVector> coarseRhs, coarseX;
1034 RCP<TimeMonitor> RTime;
1035 if (!useStackedTimer)
1037 RCP<TimeMonitor> RLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : restriction" + levelSuffix,
Timings0));
1038 coarseRhs = coarseRhs_[startLevel];
1040 if (implicitTranspose_) {
1041 P->apply(*residual, *coarseRhs, Teuchos::TRANS, one, zero);
1044 RCP<Operator> R = Coarse->Get<RCP<Operator>>(
"R");
1045 R->apply(*residual, *coarseRhs, Teuchos::NO_TRANS, one, zero);
1049 RCP<const Import> importer;
1050 if (Coarse->IsAvailable(
"Importer"))
1051 importer = Coarse->Get<RCP<const Import>>(
"Importer");
1053 coarseX = coarseX_[startLevel];
1054 if (!doPRrebalance_ && !importer.is_null()) {
1055 RCP<TimeMonitor> ITime;
1056 if (!useStackedTimer)
1058 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
1061 RCP<MultiVector> coarseTmp = coarseImport_[startLevel];
1062 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
1063 coarseRhs.swap(coarseTmp);
1066 RCP<Operator> Ac = Coarse->Get<RCP<Operator>>(
"A");
1067 if (!Ac.is_null()) {
1068 RCP<const Map> origXMap = coarseX->getMap();
1069 RCP<const Map> origRhsMap = coarseRhs->getMap();
1072 coarseRhs->replaceMap(Ac->getRangeMap());
1073 coarseX->replaceMap(Ac->getDomainMap());
1076 iterateLevelTime = Teuchos::null;
1078 Iterate(*coarseRhs, *coarseX, 1,
true, startLevel + 1);
1080 if (Cycle_ ==
WCYCLE && WCycleStartLevel_ <= startLevel)
1081 Iterate(*coarseRhs, *coarseX, 1,
false, startLevel + 1);
1084 iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel));
1086 coarseX->replaceMap(origXMap);
1087 coarseRhs->replaceMap(origRhsMap);
1090 if (!doPRrebalance_ && !importer.is_null()) {
1091 RCP<TimeMonitor> ITime;
1092 if (!useStackedTimer)
1094 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
1097 RCP<MultiVector> coarseTmp = coarseExport_[startLevel];
1098 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
1099 coarseX.swap(coarseTmp);
1104 RCP<TimeMonitor> PTime;
1105 if (!useStackedTimer)
1107 RCP<TimeMonitor> PLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : prolongation" + levelSuffix,
Timings0));
1112 if (fuseProlongationAndUpdate_) {
1113 P->apply(*coarseX, X, Teuchos::NO_TRANS, scalingFactor_, one);
1115 RCP<MultiVector> correction = correction_[startLevel];
1116 P->apply(*coarseX, *correction, Teuchos::NO_TRANS, one, zero);
1117 X.update(scalingFactor_, *correction, one);
1123 RCP<TimeMonitor> STime;
1124 if (!useStackedTimer)
1126 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1128 if (Fine->IsAvailable(
"PostSmoother")) {
1129 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
1130 postSmoo->Apply(X, B,
false);
1136 if (IsCalculationOfResidualRequired(startLevel, conv)) {
1137 ConvergenceStatus convergenceStatus = ComputeResidualAndPrintHistory(*A, X, B, iteration, startLevel, conv, prevNorm);
1139 return convergenceStatus;
1146template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1148 LO startLevel = (start != -1 ? start : 0);
1149 LO endLevel = (end != -1 ? end : Levels_.size() - 1);
1152 "MueLu::Hierarchy::Write : startLevel must be <= endLevel");
1155 "MueLu::Hierarchy::Write bad start or end level");
1157 for (LO i = startLevel; i < endLevel + 1; i++) {
1158 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get<RCP<Operator>>(
"A")), P, R;
1160 P = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get<RCP<Operator>>(
"P"));
1161 if (!implicitTranspose_)
1162 R = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get<RCP<Operator>>(
"R"));
1165 if (!A.is_null()) Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"A_" +
toString(i) + suffix +
".m", *A);
1167 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"P_" +
toString(i) + suffix +
".m", *P);
1170 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"R_" +
toString(i) + suffix +
".m", *R);
1175template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1177 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1178 (*it)->Keep(ename, factory);
1181template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1183 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1184 (*it)->Delete(ename, factory);
1187template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1189 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1190 (*it)->AddKeepFlag(ename, factory, keep);
1193template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1195 for (Array<RCP<Level>>::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1196 (*it)->RemoveKeepFlag(ename, factory, keep);
1199template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1201 if (description_.empty()) {
1202 std::ostringstream out;
1204 out <<
"{#levels = " << GetGlobalNumLevels() <<
", complexity = " << GetOperatorComplexity() <<
"}";
1205 description_ = out.str();
1207 return description_;
1210template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1215template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1217 RCP<Operator> A0 = Levels_[0]->template Get<RCP<Operator>>(
"A");
1218 RCP<const Teuchos::Comm<int>> comm = A0->getDomainMap()->getComm();
1220 int numLevels = GetNumLevels();
1221 RCP<Operator> Ac = Levels_[numLevels - 1]->template Get<RCP<Operator>>(
"A");
1228 int root = comm->getRank();
1231 int smartData = numLevels * comm->getSize() + comm->getRank(), maxSmartData;
1232 reduceAll(*comm, Teuchos::REDUCE_MAX, smartData, Teuchos::ptr(&maxSmartData));
1233 root = maxSmartData % comm->getSize();
1237 double smoother_comp = -1.0;
1239 smoother_comp = GetSmootherComplexity();
1243 std::vector<Xpetra::global_size_t> nnzPerLevel;
1244 std::vector<Xpetra::global_size_t> rowsPerLevel;
1245 std::vector<int> numProcsPerLevel;
1246 bool someOpsNotMatrices =
false;
1247 const Xpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1248 for (
int i = 0; i < numLevels; i++) {
1250 "Operator A is not available on level " << i);
1252 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
1254 "Operator A on level " << i <<
" is null.");
1256 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
1258 someOpsNotMatrices =
true;
1259 nnzPerLevel.push_back(INVALID);
1260 rowsPerLevel.push_back(A->getDomainMap()->getGlobalNumElements());
1261 numProcsPerLevel.push_back(A->getDomainMap()->getComm()->getSize());
1263 LO storageblocksize = Am->GetStorageBlockSize();
1264 Xpetra::global_size_t nnz = Am->getGlobalNumEntries() * storageblocksize * storageblocksize;
1265 nnzPerLevel.push_back(nnz);
1266 rowsPerLevel.push_back(Am->getGlobalNumRows() * storageblocksize);
1267 numProcsPerLevel.push_back(Am->getRowMap()->getComm()->getSize());
1270 if (someOpsNotMatrices)
1271 GetOStream(
Warnings0) <<
"Some level operators are not matrices, statistics calculation are incomplete" << std::endl;
1274 std::string label = Levels_[0]->getObjectLabel();
1275 std::ostringstream oss;
1276 oss << std::setfill(
' ');
1277 oss <<
"\n--------------------------------------------------------------------------------\n";
1278 oss <<
"--- Multigrid Summary " << std::setw(32) <<
"---\n";
1279 oss <<
"--------------------------------------------------------------------------------" << std::endl;
1280 if (hierarchyLabel_ !=
"") oss <<
"Label = " << hierarchyLabel_ << std::endl;
1282 oss <<
"Scalar = " << Teuchos::ScalarTraits<Scalar>::name() << std::endl;
1283 oss <<
"Number of levels = " << numLevels << std::endl;
1284 oss <<
"Operator complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1285 if (!someOpsNotMatrices)
1286 oss << GetOperatorComplexity() << std::endl;
1288 oss <<
"not available (Some operators in hierarchy are not matrices.)" << std::endl;
1290 if (smoother_comp != -1.0) {
1291 oss <<
"Smoother complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1292 << smoother_comp << std::endl;
1297 oss <<
"Cycle type = V" << std::endl;
1300 oss <<
"Cycle type = W" << std::endl;
1301 if (WCycleStartLevel_ > 0)
1302 oss <<
"Cycle start level = " << WCycleStartLevel_ << std::endl;
1309 Xpetra::global_size_t tt = rowsPerLevel[0];
1315 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1316 tt = nnzPerLevel[i];
1326 tt = numProcsPerLevel[0];
1332 oss <<
"level " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz "
1333 <<
" nnz/row" << std::setw(npspacer) <<
" c ratio"
1334 <<
" procs" << std::endl;
1335 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1336 oss <<
" " << i <<
" ";
1337 oss << std::setw(rowspacer) << rowsPerLevel[i];
1338 if (nnzPerLevel[i] != INVALID) {
1339 oss << std::setw(nnzspacer) << nnzPerLevel[i];
1340 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1341 oss << std::setw(9) << as<double>(nnzPerLevel[i]) / rowsPerLevel[i];
1343 oss << std::setw(nnzspacer) <<
"Operator";
1344 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1345 oss << std::setw(9) <<
" ";
1348 oss << std::setw(9) << as<double>(rowsPerLevel[i - 1]) / rowsPerLevel[i];
1350 oss << std::setw(9) <<
" ";
1351 oss <<
" " << std::setw(npspacer) << numProcsPerLevel[i] << std::endl;
1354 for (
int i = 0; i < GetNumLevels(); ++i) {
1355 RCP<SmootherBase> preSmoo, postSmoo;
1356 if (Levels_[i]->IsAvailable(
"PreSmoother"))
1357 preSmoo = Levels_[i]->
template Get<RCP<SmootherBase>>(
"PreSmoother");
1358 if (Levels_[i]->IsAvailable(
"PostSmoother"))
1359 postSmoo = Levels_[i]->
template Get<RCP<SmootherBase>>(
"PostSmoother");
1361 if (preSmoo != null && preSmoo == postSmoo)
1362 oss <<
"Smoother (level " << i <<
") both : " << preSmoo->description() << std::endl;
1364 oss <<
"Smoother (level " << i <<
") pre : "
1365 << (preSmoo != null ? preSmoo->description() :
"no smoother") << std::endl;
1366 oss <<
"Smoother (level " << i <<
") post : "
1367 << (postSmoo != null ? postSmoo->description() :
"no smoother") << std::endl;
1378 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
1379 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1381 int strLength = outstr.size();
1382 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1383 if (comm->getRank() != root)
1384 outstr.resize(strLength);
1385 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1392template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1394 Teuchos::OSTab tab2(out);
1395 for (
int i = 0; i < GetNumLevels(); ++i)
1396 Levels_[i]->print(out, verbLevel);
1399template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1401 isPreconditioner_ = flag;
1404template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1406 if (GetProcRankVerbose() != 0)
1408#if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
1413 dp.property(
"label", boost::get(boost::vertex_name, graph));
1414 dp.property(
"id", boost::get(boost::vertex_index, graph));
1415 dp.property(
"label", boost::get(boost::edge_name, graph));
1416 dp.property(
"color", boost::get(boost::edge_color, graph));
1419 std::map<const FactoryBase*, BoostVertex> vindices;
1420 typedef std::map<std::pair<BoostVertex, BoostVertex>, std::string> emap;
1423 static int call_id = 0;
1425 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator>>(
"A");
1426 int rank = A->getDomainMap()->getComm()->getRank();
1429 for (
int i = currLevel; i <= currLevel + 1 && i < GetNumLevels(); i++) {
1431 Levels_[i]->UpdateGraph(vindices, edges, dp, graph);
1433 for (emap::const_iterator eit = edges.begin(); eit != edges.end(); eit++) {
1434 std::pair<BoostEdge, bool> boost_edge = boost::add_edge(eit->first.first, eit->first.second, graph);
1437 if (eit->second == std::string(
"Graph"))
1438 boost::put(
"label", dp, boost_edge.first, std::string(
"Graph_"));
1440 boost::put(
"label", dp, boost_edge.first, eit->second);
1442 boost::put(
"color", dp, boost_edge.first, std::string(
"red"));
1444 boost::put(
"color", dp, boost_edge.first, std::string(
"blue"));
1448 std::ofstream out(dumpFile_.c_str() + std::string(
"_") + std::to_string(currLevel) + std::string(
"_") + std::to_string(call_id) + std::string(
"_") + std::to_string(rank) + std::string(
".dot"));
1449 boost::write_graphviz_dp(out, graph, dp, std::string(
"id"));
1453 GetOStream(
Errors) <<
"Dependency graph output requires boost and MueLu_ENABLE_Boost_for_real" << std::endl;
1458template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1460 RCP<Operator> Ao = level.
Get<RCP<Operator>>(
"A");
1461 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Ao);
1463 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is not a matrix, skipping..." << std::endl;
1466 if (Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A) != Teuchos::null) {
1467 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: operator is a BlockedCrsMatrix, skipping..." << std::endl;
1471 typedef Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::coordinateType, LO, GO, NO> xdMV;
1473 RCP<xdMV> coords = level.
Get<RCP<xdMV>>(
"Coordinates");
1475 if (A->getRowMap()->isSameAs(*(coords->getMap()))) {
1476 GetOStream(
Runtime1) <<
"Hierarchy::ReplaceCoordinateMap: matrix and coordinates maps are same, skipping..." << std::endl;
1480 if (A->IsView(
"stridedMaps") && rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps")) != Teuchos::null) {
1481 RCP<const StridedMap> stridedRowMap = rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps"));
1484 TEUCHOS_TEST_FOR_EXCEPTION(stridedRowMap->getStridedBlockId() != -1 || stridedRowMap->getOffset() != 0,
1485 Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: nontrivial maps (block id = " << stridedRowMap->getStridedBlockId() <<
", offset = " << stridedRowMap->getOffset() <<
")");
1488 GetOStream(
Runtime1) <<
"Replacing coordinate map" << std::endl;
1489 TEUCHOS_TEST_FOR_EXCEPTION(A->GetFixedBlockSize() % A->GetStorageBlockSize() != 0,
Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: Storage block size does not evenly divide fixed block size");
1491 size_t blkSize = A->GetFixedBlockSize() / A->GetStorageBlockSize();
1493 RCP<const Map> nodeMap = A->getRowMap();
1496 RCP<const Map> dofMap = A->getRowMap();
1497 GO indexBase = dofMap->getIndexBase();
1498 size_t numLocalDOFs = dofMap->getLocalNumElements();
1500 "Hierarchy::ReplaceCoordinateMap: block size (" << blkSize <<
") is incompatible with the number of local dofs in a row map (" << numLocalDOFs);
1501 ArrayView<const GO> GIDs = dofMap->getLocalElementList();
1503 Array<GO> nodeGIDs(numLocalDOFs / blkSize);
1504 for (
size_t i = 0; i < numLocalDOFs; i += blkSize)
1505 nodeGIDs[i / blkSize] = (GIDs[i] - indexBase) / blkSize + indexBase;
1507 Xpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1508 nodeMap = MapFactory::Build(dofMap->lib(), INVALID, nodeGIDs(), indexBase, dofMap->getComm());
1514 if (coords->getLocalLength() != A->getRowMap()->getLocalNumElements()) {
1515 GetOStream(
Warnings) <<
"Coordinate vector does not match row map of matrix A!" << std::endl;
1520 Array<ArrayView<const typename Teuchos::ScalarTraits<Scalar>::coordinateType>> coordDataView;
1521 std::vector<ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType>> coordData;
1522 for (
size_t i = 0; i < coords->getNumVectors(); i++) {
1523 coordData.push_back(coords->getData(i));
1524 coordDataView.push_back(coordData[i]());
1527 RCP<xdMV> newCoords = Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::coordinateType, LO, GO, NO>::Build(nodeMap, coordDataView(), coords->getNumVectors());
1528 level.
Set(
"Coordinates", newCoords);
1531template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1533 int N = Levels_.size();
1534 if (((sizeOfAllocatedLevelMultiVectors_ == numvecs && residual_.size() == N) || numvecs <= 0) && !forceMapCheck)
return;
1537 if (residual_.size() != N) {
1538 DeleteLevelMultiVectors();
1540 residual_.resize(N);
1541 coarseRhs_.resize(N);
1543 coarseImport_.resize(N);
1544 coarseExport_.resize(N);
1545 correction_.resize(N);
1548 for (
int i = 0; i < N; i++) {
1549 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator>>(
"A");
1552 RCP<const BlockedCrsMatrix> A_as_blocked = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(A);
1553 RCP<const Map> Arm = A->getRangeMap();
1554 RCP<const Map> Adm = A->getDomainMap();
1555 if (!A_as_blocked.is_null()) {
1556 Adm = A_as_blocked->getFullDomainMap();
1559 if (residual_[i].is_null() || !residual_[i]->getMap()->isSameAs(*Arm))
1561 residual_[i] = MultiVectorFactory::Build(Arm, numvecs,
true);
1562 if (correction_[i].is_null() || !correction_[i]->getMap()->isSameAs(*Adm))
1563 correction_[i] = MultiVectorFactory::Build(Adm, numvecs,
false);
1568 if (implicitTranspose_) {
1569 RCP<Operator> P = Levels_[i + 1]->template Get<RCP<Operator>>(
"P");
1571 RCP<const Map> map = P->getDomainMap();
1572 if (coarseRhs_[i].is_null() || !coarseRhs_[i]->getMap()->isSameAs(*map))
1573 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1576 RCP<Operator> R = Levels_[i + 1]->template Get<RCP<Operator>>(
"R");
1578 RCP<const Map> map = R->getRangeMap();
1579 if (coarseRhs_[i].is_null() || !coarseRhs_[i]->getMap()->isSameAs(*map))
1580 coarseRhs_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1584 RCP<const Import> importer;
1585 if (Levels_[i + 1]->IsAvailable(
"Importer"))
1586 importer = Levels_[i + 1]->
template Get<RCP<const Import>>(
"Importer");
1587 if (doPRrebalance_ || importer.is_null()) {
1588 RCP<const Map> map = coarseRhs_[i]->getMap();
1589 if (coarseX_[i].is_null() || !coarseX_[i]->getMap()->isSameAs(*map))
1590 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
true);
1593 map = importer->getTargetMap();
1594 if (coarseImport_[i].is_null() || !coarseImport_[i]->getMap()->isSameAs(*map)) {
1595 coarseImport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1596 coarseX_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1598 map = importer->getSourceMap();
1599 if (coarseExport_[i].is_null() || !coarseExport_[i]->getMap()->isSameAs(*map))
1600 coarseExport_[i] = MultiVectorFactory::Build(map, numvecs,
false);
1604 sizeOfAllocatedLevelMultiVectors_ = numvecs;
1607template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1609 if (sizeOfAllocatedLevelMultiVectors_ == 0)
return;
1610 residual_.resize(0);
1611 coarseRhs_.resize(0);
1613 coarseImport_.resize(0);
1614 coarseExport_.resize(0);
1615 correction_.resize(0);
1616 sizeOfAllocatedLevelMultiVectors_ = 0;
1619template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1621 const LO startLevel,
const ConvData& conv)
const {
1622 return (startLevel == 0 && !isPreconditioner_ && (IsPrint(
Statistics1) || conv.
tol_ > 0));
1625template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1627 const Teuchos::Array<MagnitudeType>& residualNorm,
const MagnitudeType convergenceTolerance)
const {
1630 if (convergenceTolerance > Teuchos::ScalarTraits<MagnitudeType>::zero()) {
1632 for (LO k = 0; k < residualNorm.size(); k++)
1633 if (residualNorm[k] >= convergenceTolerance)
1642 return convergenceStatus;
1645template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1647 const LO iteration,
const Teuchos::Array<MagnitudeType>& residualNorm)
const {
1649 << std::setiosflags(std::ios::left)
1650 << std::setprecision(3) << std::setw(4) << iteration
1652 << std::setprecision(10) << residualNorm
1656template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1658 const Operator& A,
const MultiVector& X,
const MultiVector& B,
const LO iteration,
1660 Teuchos::Array<MagnitudeType> residualNorm;
1664 rate_ = currentResidualNorm / previousResidualNorm;
1665 previousResidualNorm = currentResidualNorm;
1668 PrintResidualHistory(iteration, residualNorm);
1670 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.