47 #ifndef MUELU_HIERARCHY_DEF_HPP 48 #define MUELU_HIERARCHY_DEF_HPP 55 #include <Xpetra_Matrix.hpp> 56 #include <Xpetra_MultiVectorFactory.hpp> 57 #include <Xpetra_Operator.hpp> 58 #include <Xpetra_IO.hpp> 63 #include "MueLu_FactoryManager.hpp" 64 #include "MueLu_HierarchyUtils.hpp" 65 #include "MueLu_TopRAPFactory.hpp" 66 #include "MueLu_TopSmootherFactory.hpp" 69 #include "MueLu_PerfUtils.hpp" 70 #include "MueLu_PFactory.hpp" 72 #include "MueLu_SmootherFactory.hpp" 75 #include "Teuchos_TimeMonitor.hpp" 79 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
81 : maxCoarseSize_(GetDefaultMaxCoarseSize()), implicitTranspose_(GetDefaultImplicitTranspose()),
82 doPRrebalance_(GetDefaultPRrebalance()), isPreconditioner_(true), Cycle_(GetDefaultCycle()),
83 scalingFactor_(
Teuchos::ScalarTraits<double>::one()), lib_(Xpetra::UseTpetra), isDumpingEnabled_(false), dumpLevel_(-1), rate_(-1)
88 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
94 lib_ = A->getDomainMap()->lib();
96 RCP<Level> Finest = rcp(
new Level);
102 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
106 if (level->GetLevelID() != -1 && (level->GetLevelID() != levelID))
108 " have been added at the end of the hierarchy\n but its ID have been redefined" <<
109 " because last level ID of the hierarchy was " <<
LastLevelID() <<
"." << std::endl;
112 level->SetLevelID(levelID);
115 level->SetPreviousLevel( (levelID == 0) ? Teuchos::null :
Levels_[
LastLevelID() - 1] );
118 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
121 newLevel->setlib(
lib_);
125 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
128 "MueLu::Hierarchy::GetLevel(): invalid input parameter value: LevelID = " << levelID);
132 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
137 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
139 RCP<Operator> A =
Levels_[0]->template Get<RCP<Operator> >(
"A");
140 RCP<const Teuchos::Comm<int> > comm = A->getDomainMap()->getComm();
144 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, numLevels, Teuchos::ptr(&numGlobalLevels));
146 return numGlobalLevels;
149 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
151 double totalNnz = 0, lev0Nnz = 1;
154 "Operator complexity cannot be calculated because A is unavailable on level " << i);
155 RCP<Operator> A =
Levels_[i]->template Get<RCP<Operator> >(
"A");
159 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
161 GetOStream(
Warnings0) <<
"Some level operators are not matrices, operator complexity calculation aborted" << std::endl;
165 totalNnz += as<double>(Am->getGlobalNumEntries());
169 return totalNnz / lev0Nnz;
172 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
174 double node_sc = 0, global_sc=0;
176 const size_t INVALID = Teuchos::OrdinalTraits<size_t>::invalid();
179 if (!
Levels_[0]->IsAvailable(
"A"))
return -1.0;
181 RCP<Operator> A =
Levels_[0]->template Get<RCP<Operator> >(
"A");
182 if (A.is_null())
return -1.0;
183 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
184 if(Am.is_null())
return -1.0;
185 a0_nnz = as<double>(Am->getGlobalNumEntries());
190 if(!
Levels_[i]->IsAvailable(
"PreSmoother"))
continue;
191 RCP<SmootherBase> S =
Levels_[i]->template Get<RCP<SmootherBase> >(
"PreSmoother");
192 if (S.is_null())
continue;
193 level_sc = S->getNodeSmootherComplexity();
194 if(level_sc == INVALID) {global_sc=-1.0;
break;}
196 node_sc += as<double>(level_sc);
200 RCP<const Teuchos::Comm<int> > comm =A->getDomainMap()->getComm();
201 Teuchos::reduceAll(*comm,Teuchos::REDUCE_SUM,node_sc,Teuchos::ptr(&global_sc));
202 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MIN,node_sc,Teuchos::ptr(&min_sc));
204 if(min_sc < 0.0)
return -1.0;
205 else return global_sc / a0_nnz;
212 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
215 "MueLu::Hierarchy::CheckLevel(): wrong underlying linear algebra library.");
216 TEUCHOS_TEST_FOR_EXCEPTION(level.
GetLevelID() != levelID, Exceptions::RuntimeError,
217 "MueLu::Hierarchy::CheckLevel(): wrong level ID");
218 TEUCHOS_TEST_FOR_EXCEPTION(levelID != 0 && level.
GetPreviousLevel() !=
Levels_[levelID-1], Exceptions::RuntimeError,
219 "MueLu::Hierarchy::Setup(): wrong level parent");
224 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
226 const RCP<const FactoryManagerBase> fineLevelManager,
227 const RCP<const FactoryManagerBase> coarseLevelManager,
228 const RCP<const FactoryManagerBase> nextLevelManager) {
236 "MueLu::Hierarchy::Setup(): argument coarseLevelManager cannot be null");
242 "MueLu::Hierarchy:Setup(): level " << coarseLevelID <<
" (specified by coarseLevelID argument) " 243 "must be built before calling this function.");
251 bool isFinestLevel = (fineLevelManager.is_null());
252 bool isLastLevel = (nextLevelManager.is_null());
256 RCP<Operator> A = level.
Get< RCP<Operator> >(
"A");
257 RCP<const Map> domainMap = A->getDomainMap();
258 RCP<const Teuchos::Comm<int> > comm = domainMap->getComm();
269 lib_ = domainMap->lib();
283 RCP<SetFactoryManager> SFMFine;
287 if (isFinestLevel &&
Levels_[coarseLevelID]->IsAvailable(
"Coordinates"))
296 RCP<TopSmootherFactory> coarseFact = rcp(
new TopSmootherFactory(coarseLevelManager,
"CoarseSolver"));
297 RCP<TopSmootherFactory> smootherFact = rcp(
new TopSmootherFactory(coarseLevelManager,
"Smoother"));
299 int nextLevelID = coarseLevelID + 1;
301 RCP<SetFactoryManager> SFMNext;
302 if (isLastLevel ==
false) {
310 Levels_[nextLevelID]->Request(TopRAPFactory(coarseLevelManager, nextLevelManager));
345 RCP<Operator> Ac = Teuchos::null;
346 TopRAPFactory coarseRAPFactory(fineLevelManager, coarseLevelManager);
349 Ac = level.
Get<RCP<Operator> >(
"A");
350 }
else if (!isFinestLevel) {
356 Ac = level.
Get<RCP<Operator> >(
"A");
357 RCP<Matrix> Acm = rcp_dynamic_cast<Matrix>(Ac);
361 level.
SetComm(Ac->getDomainMap()->getComm());
364 bool isOrigLastLevel = isLastLevel;
369 }
else if (Ac.is_null()) {
376 if (!Acm.is_null() && Acm->getGlobalNumRows() <=
maxCoarseSize_) {
383 if (!Ac.is_null() && !isFinestLevel) {
384 RCP<Operator> A =
Levels_[coarseLevelID-1]->template Get< RCP<Operator> >(
"A");
385 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
387 const double maxCoarse2FineRatio = 0.8;
388 if (!Acm.is_null() && !Am.is_null() && Acm->getGlobalNumRows() > maxCoarse2FineRatio * Am->getGlobalNumRows()) {
396 GetOStream(
Warnings0) <<
"Aggregation stagnated. Please check your matrix and/or adjust your configuration file." 397 <<
"Possible fixes:\n" 398 <<
" - reduce the maximum number of levels\n" 399 <<
" - enable repartitioning\n" 400 <<
" - increase the minimum coarse size." << std::endl;
406 if (!isOrigLastLevel) {
416 coarseFact->Build(level);
427 smootherFact->Build(level);
432 if (isLastLevel ==
true) {
433 if (isOrigLastLevel ==
false) {
436 Levels_[nextLevelID]->Release(TopRAPFactory(coarseLevelManager, nextLevelManager));
445 if (!isFinestLevel) {
449 level.
Release(coarseRAPFactory);
458 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
460 int numLevels =
Levels_.size();
462 "Hierarchy::SetupRe: " <<
Levels_.size() <<
" levels, but " <<
levelManagers_.size() <<
" level factory managers");
464 const int startLevel = 0;
467 #ifdef HAVE_MUELU_DEBUG 469 for (
int i = 0; i < numLevels; i++)
475 for (levelID = startLevel; levelID < numLevels;) {
476 bool r =
Setup(levelID,
479 (levelID+1 != numLevels ?
levelManagers_[levelID+1] : Teuchos::null));
494 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
503 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") does not exist");
505 TEUCHOS_TEST_FOR_EXCEPTION(numDesiredLevels <= 0, Exceptions::RuntimeError,
506 "Constructing non-positive (" << numDesiredLevels <<
") number of levels does not make sense.");
509 TEUCHOS_TEST_FOR_EXCEPTION(!
Levels_[startLevel]->IsAvailable(
"A"), Exceptions::RuntimeError,
510 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") has no matrix A! " 511 "Set fine level matrix A using Level.Set()");
513 RCP<Operator> A =
Levels_[startLevel]->template Get<RCP<Operator> >(
"A");
514 lib_ = A->getDomainMap()->lib();
517 RCP<Matrix> Amat = rcp_dynamic_cast<Matrix>(A);
519 if (!Amat.is_null()) {
520 RCP<ParameterList> params = rcp(
new ParameterList());
521 params->set(
"printLoadBalancingInfo",
true);
522 params->set(
"printCommInfo",
true);
526 GetOStream(
Warnings1) <<
"Fine level operator is not a matrix, statistics are not available" << std::endl;
530 RCP<const FactoryManagerBase> rcpmanager = rcpFromRef(manager);
532 const int lastLevel = startLevel + numDesiredLevels - 1;
533 GetOStream(
Runtime0) <<
"Setup loop: startLevel = " << startLevel <<
", lastLevel = " << lastLevel
534 <<
" (stop if numLevels = " << numDesiredLevels <<
" or Ac.size() < " <<
maxCoarseSize_ <<
")" << std::endl;
538 if (numDesiredLevels == 1) {
540 Setup(startLevel, Teuchos::null, rcpmanager, Teuchos::null);
543 bool bIsLastLevel =
Setup(startLevel, Teuchos::null, rcpmanager, rcpmanager);
544 if (bIsLastLevel ==
false) {
545 for (iLevel = startLevel + 1; iLevel < lastLevel; iLevel++) {
546 bIsLastLevel =
Setup(iLevel, rcpmanager, rcpmanager, rcpmanager);
547 if (bIsLastLevel ==
true)
550 if (bIsLastLevel ==
false)
551 Setup(lastLevel, rcpmanager, rcpmanager, Teuchos::null);
556 TEUCHOS_TEST_FOR_EXCEPTION(iLevel !=
Levels_.size() - 1, Exceptions::RuntimeError,
557 "MueLu::Hierarchy::Setup(): number of level");
566 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
571 for (
int iLevel = startLevel; iLevel <
GetNumLevels(); iLevel++)
575 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
582 #if defined(HAVE_MUELU_EXPERIMENTAL) && defined(HAVE_MUELU_ADDITIVE_VARIANT) 583 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
585 bool InitialGuessIsZero, LO startLevel) {
590 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
591 std::string levelSuffix1 =
" (level=" +
toString(startLevel+1) +
")";
594 RCP<Time> CompTime = Teuchos::TimeMonitor::getNewCounter(prefix +
"Computational Time (total)");
595 RCP<Time> Concurrent = Teuchos::TimeMonitor::getNewCounter(prefix +
"Concurrent portion");
596 RCP<Time> ApplyR = Teuchos::TimeMonitor::getNewCounter(prefix +
"R: Computational Time");
597 RCP<Time> ApplyPbar = Teuchos::TimeMonitor::getNewCounter(prefix +
"Pbar: Computational Time");
598 RCP<Time> CompFine = Teuchos::TimeMonitor::getNewCounter(prefix +
"Fine: Computational Time");
599 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
600 RCP<Time> ApplySum = Teuchos::TimeMonitor::getNewCounter(prefix +
"Sum: Computational Time");
601 RCP<Time> Synchronize_beginning = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_beginning");
602 RCP<Time> Synchronize_center = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_center");
603 RCP<Time> Synchronize_end = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_end");
608 RCP<Operator> A = Fine->Get< RCP<Operator> >(
"A");
609 Teuchos::RCP< const Teuchos::Comm< int > > communicator = A->getDomainMap()->getComm();
617 SC one = STS::one(), zero = STS::zero();
619 bool zeroGuess = InitialGuessIsZero;
625 RCP< Operator > Pbar;
627 RCP< MultiVector > coarseRhs, coarseX;
629 RCP<SmootherBase> preSmoo_coarse, postSmoo_coarse;
630 bool emptyCoarseSolve =
true;
631 RCP<MultiVector> coarseX_prolonged = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
633 RCP<const Import> importer;
637 if (Coarse->IsAvailable(
"Importer"))
638 importer = Coarse->Get< RCP<const Import> >(
"Importer");
640 R = Coarse->Get< RCP<Operator> >(
"R");
641 P = Coarse->Get< RCP<Operator> >(
"P");
645 Pbar = Coarse->Get< RCP<Operator> >(
"Pbar");
647 coarseRhs = MultiVectorFactory::Build(R->getRangeMap(), B.getNumVectors(),
true);
649 Ac = Coarse->Get< RCP< Operator > >(
"A");
652 R->apply(B, *coarseRhs, Teuchos::NO_TRANS, one, zero);
657 coarseX = MultiVectorFactory::Build(coarseRhs->getMap(), X.getNumVectors(),
true);
661 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import (total)" ,
Timings0));
662 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
665 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getTargetMap(), coarseRhs->getNumVectors());
666 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
667 coarseRhs.swap(coarseTmp);
669 coarseX = MultiVectorFactory::Build(importer->getTargetMap(), X.getNumVectors(),
true);
672 if (Coarse->IsAvailable(
"PreSmoother"))
673 preSmoo_coarse = Coarse->Get< RCP<SmootherBase> >(
"PreSmoother");
674 if (Coarse->IsAvailable(
"PostSmoother"))
675 postSmoo_coarse = Coarse->Get< RCP<SmootherBase> >(
"PostSmoother");
681 MagnitudeType prevNorm = STS::magnitude(STS::one()), curNorm = STS::magnitude(STS::one());
684 for (LO i = 1; i <= nIts; i++) {
685 #ifdef HAVE_MUELU_DEBUG 686 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
687 std::ostringstream ss;
688 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
692 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
693 std::ostringstream ss;
694 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
700 bool emptyFineSolve =
true;
702 RCP< MultiVector > fineX;
703 fineX = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
712 if (Fine->IsAvailable(
"PreSmoother")) {
713 RCP<SmootherBase> preSmoo = Fine->Get< RCP<SmootherBase> >(
"PreSmoother");
715 preSmoo->Apply(*fineX, B, zeroGuess);
717 emptyFineSolve =
false;
719 if (Fine->IsAvailable(
"PostSmoother")) {
720 RCP<SmootherBase> postSmoo = Fine->Get< RCP<SmootherBase> >(
"PostSmoother");
722 postSmoo->Apply(*fineX, B, zeroGuess);
725 emptyFineSolve =
false;
727 if (emptyFineSolve ==
true) {
730 fineX->update(one, B, zero);
735 if (Coarse->IsAvailable(
"PreSmoother")) {
737 preSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
739 emptyCoarseSolve =
false;
742 if (Coarse->IsAvailable(
"PostSmoother")) {
744 postSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
746 emptyCoarseSolve =
false;
749 if (emptyCoarseSolve ==
true) {
752 coarseX->update(one, *coarseRhs, zero);
760 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export (total)" ,
Timings0));
761 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
764 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getSourceMap(), coarseX->getNumVectors());
765 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
766 coarseX.swap(coarseTmp);
770 Pbar->apply(*coarseX, *coarseX_prolonged, Teuchos::NO_TRANS, one, zero);
775 X.update(1.0, *fineX, 1.0, *coarseX_prolonged, 0.0);
786 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
788 bool InitialGuessIsZero, LO startLevel) {
804 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
805 std::string levelSuffix1 =
" (level=" +
toString(startLevel+1) +
")";
807 RCP<Monitor> iterateTime;
808 RCP<TimeMonitor> iterateTime1;
814 std::string iterateLevelTimeLabel = prefix +
"Solve" + levelSuffix;
815 RCP<TimeMonitor> iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel,
Timings0));
817 bool zeroGuess = InitialGuessIsZero;
819 RCP<Level> Fine =
Levels_[startLevel];
820 RCP<Operator> A = Fine->Get< RCP<Operator> >(
"A");
822 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
832 MagnitudeType prevNorm = STS::magnitude(STS::one()), curNorm = STS::magnitude(STS::one());
838 Teuchos::Array<MagnitudeType> rn;
843 for (LO k = 0; k < rn.size(); k++)
853 << std::setiosflags(std::ios::left)
854 << std::setprecision(3) << 0
856 << std::setprecision(10) << rn
860 SC one = STS::one(), zero = STS::zero();
861 for (LO i = 1; i <= nIts; i++) {
862 #ifdef HAVE_MUELU_DEBUG 864 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
865 std::ostringstream ss;
866 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
870 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
871 std::ostringstream ss;
872 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
878 if (startLevel == as<LO>(
Levels_.size())-1) {
880 RCP<TimeMonitor> CLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : coarse" + levelSuffix,
Timings0));
882 bool emptySolve =
true;
885 if (Fine->IsAvailable(
"PreSmoother")) {
886 RCP<SmootherBase> preSmoo = Fine->Get< RCP<SmootherBase> >(
"PreSmoother");
888 preSmoo->Apply(X, B, zeroGuess);
893 if (Fine->IsAvailable(
"PostSmoother")) {
894 RCP<SmootherBase> postSmoo = Fine->Get< RCP<SmootherBase> >(
"PostSmoother");
896 postSmoo->Apply(X, B, zeroGuess);
900 if (emptySolve ==
true) {
903 X.update(one, B, zero);
908 RCP<Level> Coarse =
Levels_[startLevel+1];
911 RCP<TimeMonitor> STime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing (total)" ,
Timings0));
912 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
914 if (Fine->IsAvailable(
"PreSmoother")) {
915 RCP<SmootherBase> preSmoo = Fine->Get< RCP<SmootherBase> >(
"PreSmoother");
916 preSmoo->Apply(X, B, zeroGuess);
922 RCP<MultiVector> residual;
924 RCP<TimeMonitor> ATime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : residual calculation (total)" ,
Timings0));
925 RCP<TimeMonitor> ALevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : residual calculation" + levelSuffix,
Timings0));
929 RCP<Operator> P = Coarse->Get< RCP<Operator> >(
"P");
930 if (Coarse->IsAvailable(
"Pbar"))
931 P = Coarse->Get< RCP<Operator> >(
"Pbar");
933 RCP<MultiVector> coarseRhs, coarseX;
934 const bool initializeWithZeros =
true;
937 RCP<TimeMonitor> RTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : restriction (total)" ,
Timings0));
938 RCP<TimeMonitor> RLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : restriction" + levelSuffix,
Timings0));
941 coarseRhs = MultiVectorFactory::Build(P->getDomainMap(), X.getNumVectors(), !initializeWithZeros);
942 P->apply(*residual, *coarseRhs, Teuchos::TRANS, one, zero);
945 RCP<Operator> R = Coarse->Get< RCP<Operator> >(
"R");
946 coarseRhs = MultiVectorFactory::Build(R->getRangeMap(), X.getNumVectors(), !initializeWithZeros);
947 R->apply(*residual, *coarseRhs, Teuchos::NO_TRANS, one, zero);
951 RCP<const Import> importer;
952 if (Coarse->IsAvailable(
"Importer"))
953 importer = Coarse->Get< RCP<const Import> >(
"Importer");
956 coarseX = MultiVectorFactory::Build(coarseRhs->getMap(), X.getNumVectors(), initializeWithZeros);
959 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import (total)" ,
Timings0));
960 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
963 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getTargetMap(), coarseRhs->getNumVectors());
964 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
965 coarseRhs.swap(coarseTmp);
967 coarseX = MultiVectorFactory::Build(importer->getTargetMap(), X.getNumVectors(), initializeWithZeros);
970 RCP<Operator> Ac = Coarse->Get< RCP<Operator> >(
"A");
972 RCP<const Map> origXMap = coarseX->getMap();
975 coarseRhs->replaceMap(Ac->getRangeMap());
976 coarseX ->replaceMap(Ac->getDomainMap());
979 iterateLevelTime = Teuchos::null;
981 Iterate(*coarseRhs, *coarseX, 1,
true, startLevel+1);
984 Iterate(*coarseRhs, *coarseX, 1,
false, startLevel+1);
987 iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel));
989 coarseX->replaceMap(origXMap);
993 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export (total)" ,
Timings0));
994 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
997 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getSourceMap(), coarseX->getNumVectors());
998 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
999 coarseX.swap(coarseTmp);
1006 RCP<MultiVector> correction = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
false);
1009 RCP<TimeMonitor> PTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : prolongation (total)" ,
Timings0));
1010 RCP<TimeMonitor> PLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : prolongation" + levelSuffix,
Timings0));
1011 P->apply(*coarseX, *correction, Teuchos::NO_TRANS, one, zero);
1017 RCP<TimeMonitor> STime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing (total)" ,
Timings0));
1018 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1020 if (Fine->IsAvailable(
"PostSmoother")) {
1021 RCP<SmootherBase> postSmoo = Fine->Get< RCP<SmootherBase> >(
"PostSmoother");
1022 postSmoo->Apply(X, B,
false);
1035 Teuchos::Array<MagnitudeType> rn;
1040 rate_ = as<MagnitudeType>(curNorm / prevNorm);
1044 for (LO k = 0; k < rn.size(); k++)
1054 << std::setiosflags(std::ios::left)
1055 << std::setprecision(3) << i
1057 << std::setprecision(10) << rn
1066 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1068 LO startLevel = (start != -1 ? start : 0);
1069 LO endLevel = (end != -1 ? end :
Levels_.size()-1);
1072 "MueLu::Hierarchy::Write : startLevel must be <= endLevel");
1075 "MueLu::Hierarchy::Write bad start or end level");
1077 for (LO i = startLevel; i < endLevel + 1; i++) {
1078 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(
Levels_[i]->
template Get< RCP< Operator> >(
"A")), P, R;
1080 P = rcp_dynamic_cast<Matrix>(
Levels_[i]->
template Get< RCP< Operator> >(
"P"));
1082 R = rcp_dynamic_cast<Matrix>(
Levels_[i]->
template Get< RCP< Operator> >(
"R"));
1085 if (!A.is_null()) Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"A_" +
toString(i) + suffix +
".m", *A);
1087 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"P_" +
toString(i) + suffix +
".m", *P);
1090 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"R_" +
toString(i) + suffix +
".m", *R);
1095 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1097 for (Array<RCP<Level> >::iterator it =
Levels_.begin(); it !=
Levels_.end(); ++it)
1098 (*it)->Keep(ename, factory);
1101 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1103 for (Array<RCP<Level> >::iterator it =
Levels_.begin(); it !=
Levels_.end(); ++it)
1104 (*it)->Delete(ename, factory);
1107 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1109 for (Array<RCP<Level> >::iterator it =
Levels_.begin(); it !=
Levels_.end(); ++it)
1110 (*it)->AddKeepFlag(ename, factory, keep);
1113 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1115 for (Array<RCP<Level> >::iterator it =
Levels_.begin(); it !=
Levels_.end(); ++it)
1116 (*it)->RemoveKeepFlag(ename, factory, keep);
1119 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1123 std::ostringstream out;
1131 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1136 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1138 RCP<Operator> A0 =
Levels_[0]->template Get<RCP<Operator> >(
"A");
1139 RCP<const Teuchos::Comm<int> > comm = A0->getDomainMap()->getComm();
1142 RCP<Operator> Ac =
Levels_[numLevels-1]->template Get<RCP<Operator> >(
"A");
1149 int root = comm->getRank();
1152 int smartData = numLevels*comm->getSize() + comm->getRank(), maxSmartData;
1153 reduceAll(*comm, Teuchos::REDUCE_MAX, smartData, Teuchos::ptr(&maxSmartData));
1154 root = maxSmartData % comm->getSize();
1158 double smoother_comp =-1.0;
1164 std::vector<Xpetra::global_size_t> nnzPerLevel;
1165 std::vector<Xpetra::global_size_t> rowsPerLevel;
1166 std::vector<int> numProcsPerLevel;
1167 bool aborted =
false;
1168 for (
int i = 0; i < numLevels; i++) {
1170 "Operator A is not available on level " << i);
1172 RCP<Operator> A =
Levels_[i]->template Get<RCP<Operator> >(
"A");
1174 "Operator A on level " << i <<
" is null.");
1176 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
1178 GetOStream(
Warnings0) <<
"Some level operators are not matrices, statistics calculation aborted" << std::endl;
1183 Xpetra::global_size_t nnz = Am->getGlobalNumEntries();
1184 nnzPerLevel .push_back(nnz);
1185 rowsPerLevel .push_back(Am->getGlobalNumRows());
1186 numProcsPerLevel.push_back(Am->getRowMap()->getComm()->getSize());
1190 std::ostringstream oss;
1191 oss <<
"\n--------------------------------------------------------------------------------\n" <<
1192 "--- Multigrid Summary ---\n" 1193 "--------------------------------------------------------------------------------" << std::endl;
1194 oss <<
"Number of levels = " << numLevels << std::endl;
1195 oss <<
"Operator complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1198 if(smoother_comp!=-1.0) {
1199 oss <<
"Smoother complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1200 << smoother_comp << std::endl;
1205 oss <<
"Cycle type = V" << std::endl;
1208 oss <<
"Cycle type = W" << std::endl;
1215 Xpetra::global_size_t tt = rowsPerLevel[0];
1216 int rowspacer = 2;
while (tt != 0) { tt /= 10; rowspacer++; }
1217 tt = nnzPerLevel[0];
1218 int nnzspacer = 2;
while (tt != 0) { tt /= 10; nnzspacer++; }
1219 tt = numProcsPerLevel[0];
1220 int npspacer = 2;
while (tt != 0) { tt /= 10; npspacer++; }
1221 oss <<
"level " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " <<
" nnz/row" << std::setw(npspacer) <<
" c ratio" <<
" procs" << std::endl;
1222 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1223 oss <<
" " << i <<
" ";
1224 oss << std::setw(rowspacer) << rowsPerLevel[i];
1225 oss << std::setw(nnzspacer) << nnzPerLevel[i];
1226 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1227 oss << std::setw(9) << as<double>(nnzPerLevel[i]) / rowsPerLevel[i];
1228 if (i) oss << std::setw(9) << as<double>(rowsPerLevel[i-1])/rowsPerLevel[i];
1229 else oss << std::setw(9) <<
" ";
1230 oss <<
" " << std::setw(npspacer) << numProcsPerLevel[i] << std::endl;
1234 RCP<SmootherBase> preSmoo, postSmoo;
1235 if (
Levels_[i]->IsAvailable(
"PreSmoother"))
1236 preSmoo =
Levels_[i]->
template Get< RCP<SmootherBase> >(
"PreSmoother");
1237 if (
Levels_[i]->IsAvailable(
"PostSmoother"))
1238 postSmoo =
Levels_[i]->
template Get< RCP<SmootherBase> >(
"PostSmoother");
1240 if (preSmoo != null && preSmoo == postSmoo)
1241 oss <<
"Smoother (level " << i <<
") both : " << preSmoo->description() << std::endl;
1243 oss <<
"Smoother (level " << i <<
") pre : " 1244 << (preSmoo != null ? preSmoo->description() :
"no smoother") << std::endl;
1245 oss <<
"Smoother (level " << i <<
") post : " 1246 << (postSmoo != null ? postSmoo->description() :
"no smoother") << std::endl;
1257 RCP<const Teuchos::MpiComm<int> > mpiComm = rcp_dynamic_cast<
const Teuchos::MpiComm<int> >(comm);
1258 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1260 int strLength = outstr.size();
1261 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1262 if (comm->getRank() != root)
1263 outstr.resize(strLength);
1264 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1271 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1273 Teuchos::OSTab tab2(out);
1278 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1283 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1287 #if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400) 1291 dp.property(
"label", boost::get(boost::vertex_name, graph));
1292 dp.property(
"id", boost::get(boost::vertex_index, graph));
1293 dp.property(
"label", boost::get(boost::edge_name, graph));
1294 dp.property(
"color", boost::get(boost::edge_color, graph));
1297 std::map<const FactoryBase*, BoostVertex> vindices;
1298 typedef std::map<std::pair<BoostVertex,BoostVertex>, std::string> emap; emap edges;
1302 Levels_[i]->UpdateGraph(vindices, edges, dp, graph);
1304 for (emap::const_iterator eit = edges.begin(); eit != edges.end(); eit++) {
1305 std::pair<BoostEdge, bool> boost_edge = boost::add_edge(eit->first.first, eit->first.second, graph);
1306 boost::put(
"label", dp, boost_edge.first, eit->second);
1308 boost::put(
"color", dp, boost_edge.first, std::string(
"red"));
1310 boost::put(
"color", dp, boost_edge.first, std::string(
"blue"));
1315 std::ostringstream legend;
1316 legend <<
"< <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\"> \ 1317 <TR><TD COLSPAN=\"2\">Legend</TD></TR> \ 1318 <TR><TD><FONT color=\"red\">Level " <<
dumpLevel_ <<
"</FONT></TD><TD><FONT color=\"blue\">Level " <<
dumpLevel_+1 <<
"</FONT></TD></TR> \ 1320 BoostVertex boost_vertex = boost::add_vertex(graph);
1321 boost::put(
"label", dp, boost_vertex, legend.str());
1324 boost::write_graphviz_dp(out, graph, dp, std::string(
"id"));
1326 GetOStream(
Errors) <<
"Dependency graph output requires boost and MueLu_ENABLE_Boost_for_real" << std::endl;
1331 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1333 RCP<Operator> Ao = level.
Get<RCP<Operator> >(
"A");
1334 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Ao);
1336 GetOStream(
Warnings1) <<
"Hierarchy::ReplaceCoordinateMap: operator is not a matrix, skipping..." << std::endl;
1339 if(Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A) != Teuchos::null) {
1340 GetOStream(
Warnings1) <<
"Hierarchy::ReplaceCoordinateMap: operator is a BlockedCrsMatrix, skipping..." << std::endl;
1344 typedef Xpetra::MultiVector<double,LO,GO,NO> xdMV;
1346 RCP<xdMV> coords = level.
Get<RCP<xdMV> >(
"Coordinates");
1348 if (A->getRowMap()->isSameAs(*(coords->getMap()))) {
1349 GetOStream(
Warnings1) <<
"Hierarchy::ReplaceCoordinateMap: matrix and coordinates maps are same, skipping..." << std::endl;
1353 if (A->IsView(
"stridedMaps") && rcp_dynamic_cast<
const StridedMap>(A->getRowMap(
"stridedMaps")) != Teuchos::null) {
1354 RCP<const StridedMap> stridedRowMap = rcp_dynamic_cast<
const StridedMap>(A->getRowMap(
"stridedMaps"));
1357 TEUCHOS_TEST_FOR_EXCEPTION(stridedRowMap->getStridedBlockId() != -1 || stridedRowMap->getOffset() != 0,
1358 Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: nontrivial maps (block id = " << stridedRowMap->getStridedBlockId()
1359 <<
", offset = " << stridedRowMap->getOffset() <<
")");
1364 size_t blkSize = A->GetFixedBlockSize();
1366 RCP<const Map> nodeMap = A->getRowMap();
1369 RCP<const Map> dofMap = A->getRowMap();
1370 GO indexBase = dofMap->getIndexBase();
1371 size_t numLocalDOFs = dofMap->getNodeNumElements();
1373 "Hierarchy::ReplaceCoordinateMap: block size (" << blkSize <<
") is incompatible with the number of local dofs in a row map (" << numLocalDOFs);
1374 ArrayView<const GO> GIDs = dofMap->getNodeElementList();
1376 Array<GO> nodeGIDs(numLocalDOFs/blkSize);
1377 for (
size_t i = 0; i < numLocalDOFs; i += blkSize)
1378 nodeGIDs[i/blkSize] = (GIDs[i] - indexBase)/blkSize + indexBase;
1380 Xpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1381 nodeMap = MapFactory::Build(dofMap->lib(), INVALID, nodeGIDs(), indexBase, dofMap->getComm());
1387 if(coords->getLocalLength() != A->getRowMap()->getNodeNumElements()) {
1388 GetOStream(
Warnings) <<
"Coordinate vector does not match row map of matrix A!" << std::endl;
1393 Array<ArrayView<const double> > coordDataView;
1394 std::vector<ArrayRCP<const double> > coordData;
1395 for (
size_t i = 0; i < coords->getNumVectors(); i++) {
1396 coordData.push_back(coords->getData(i));
1397 coordDataView.push_back(coordData[i]());
1400 RCP<xdMV> newCoords = Xpetra::MultiVectorFactory<double,LO,GO,NO>::Build(nodeMap, coordDataView(), coords->getNumVectors());
1401 level.
Set(
"Coordinates", newCoords);
1406 #endif // MUELU_HIERARCHY_DEF_HPP Important warning messages (one line)
void IsPreconditioner(const bool flag)
RCP< Level > & GetPreviousLevel()
Previous level.
static void SetRandomSeed(const Teuchos::Comm< int > &comm)
High level timing information (use Teuchos::TimeMonitor::summarize() to print)
double GetSmootherComplexity() const
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level->Get< RCP<Matrix> >("A", factory) if factory == NULL => use default factory.
RCP< Level > & GetLevel(const int levelID=0)
Retrieve a certain level from hierarchy.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Hierarchy()
Default constructor.
virtual std::string ShortClassName() const
Return the class name of the object, without template parameters and without namespace.
void Release(const FactoryBase &factory)
Decrement the storage counter for all the inputs of a factory.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
void AddLevel(const RCP< Level > &level)
Add a level at the end of the hierarchy.
void AddNewLevel()
Add a new level at the end of the hierarchy.
VerbLevel toMueLuVerbLevel(const Teuchos::EVerbosityLevel verbLevel)
One-liner description of what is happening.
static Xpetra::global_size_t GetDefaultMaxCoarseSize()
void Clear(int startLevel=0)
Clear impermanent data from previous setup.
Namespace for MueLu classes and methods.
Exception throws to report incompatible objects (like maps).
bool IsPrint(MsgType type, int thisProcRankOnly=-1) const
Find out whether we need to print out information for a specific message type.
Integrates Teuchos::TimeMonitor with MueLu verbosity system.
Print skeleton for the run, i.e. factory calls and used parameters.
int SetProcRankVerbose(int procRank) const
Set proc rank used for printing.
MagnitudeType rate_
Convergece rate.
void ReplaceCoordinateMap(Level &level)
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
Call Level::AddKeepFlag for each level of the Hierarchy.
Print even more statistics.
void setlib(Xpetra::UnderlyingLib lib2)
int GetLevelID() const
Return level number.
void print(std::ostream &out=std::cout, const VerbLevel verbLevel=(MueLu::Parameters|MueLu::Statistics0)) const
Base class for factories (e.g., R, P, and A_coarse).
Print statistics that do not involve significant additional computation.
Xpetra::UnderlyingLib lib_
static RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Residual(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &RHS)
static CycleType GetDefaultCycle()
void Write(const LO &start=-1, const LO &end=-1, const std::string &suffix="")
Print matrices in the multigrid hierarchy to file.
Class that holds all level-specific information.
Class that provides default factories within Needs class.
RCP< const Teuchos::Comm< int > > GetComm() const
int GetProcRankVerbose() const
Get proc rank used for printing. Do not use this information for any other purpose.
void RemoveKeepFlag(const std::string &ename, const FactoryBase *factory, KeepType keep=MueLu::All)
Call Level::RemoveKeepFlag for each level of the Hierarchy.
int GetGlobalNumLevels() const
void CheckLevel(Level &level, int levelID)
Helper function.
Xpetra::UnderlyingLib lib()
static bool GetDefaultImplicitTranspose()
void describe(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the Hierarchy with some verbosity level to a FancyOStream object.
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
double GetOperatorComplexity() const
Data struct for defining stopping criteria of multigrid iteration.
static Teuchos::Array< Magnitude > ResidualNorm(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &RHS)
STS::magnitudeType MagnitudeType
void Delete(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Call Level::Delete(ename, factory) for each level of the Hierarchy.
Timer to be used in non-factories.
Array< RCP< Level > > Levels_
Container for Level objects.
void DumpCurrentGraph() const
static bool GetDefaultPRrebalance()
VerbLevel GetVerbLevel() const
Get the verbosity level.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
Exception throws to report errors in the internal logical of the program.
An exception safe way to call the method 'Level::SetFactoryManager()'.
void SetComm(RCP< const Teuchos::Comm< int > > const &comm)
Print all warning messages.
ReturnType Iterate(const MultiVector &B, MultiVector &X, ConvData conv=ConvData(), bool InitialGuessIsZero=false, LO startLevel=0)
Apply the multigrid preconditioner.
Description of what is happening (more verbose)
void Keep(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Call Level::Keep(ename, factory) for each level of the Hierarchy.
bool isDumpingEnabled_
Graph dumping.
std::string description() const
Return a simple one-line description of this object.
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.
virtual void Clean() const
virtual std::string description() const
Return a simple one-line description of this object.
Array< RCP< const FactoryManagerBase > > levelManagers_
Xpetra::global_size_t maxCoarseSize_
void Request(const FactoryBase &factory)
Increment the storage counter for all the inputs of a factory.