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"
81 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
83 : maxCoarseSize_(GetDefaultMaxCoarseSize()), implicitTranspose_(GetDefaultImplicitTranspose()),
84 fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate()),
85 doPRrebalance_(GetDefaultPRrebalance()), isPreconditioner_(true), Cycle_(GetDefaultCycle()),
86 scalingFactor_(
Teuchos::ScalarTraits<double>::one()), lib_(Xpetra::UseTpetra), isDumpingEnabled_(false), dumpLevel_(-1), rate_(-1),
87 sizeOfAllocatedLevelMultiVectors_(0)
92 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
96 setObjectLabel(label);
97 Levels_[0]->setObjectLabel(label);
100 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
102 : maxCoarseSize_(GetDefaultMaxCoarseSize()), implicitTranspose_(GetDefaultImplicitTranspose()),
103 fuseProlongationAndUpdate_(GetDefaultFuseProlongationAndUpdate()),
104 doPRrebalance_(GetDefaultPRrebalance()), isPreconditioner_(true), Cycle_(GetDefaultCycle()),
105 scalingFactor_(
Teuchos::ScalarTraits<double>::one()), isDumpingEnabled_(false), dumpLevel_(-1), rate_(-1),
106 sizeOfAllocatedLevelMultiVectors_(0)
108 lib_ = A->getDomainMap()->lib();
110 RCP<Level> Finest = rcp(
new Level);
116 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
120 setObjectLabel(label);
121 Levels_[0]->setObjectLabel(label);
124 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
126 int levelID = LastLevelID() + 1;
128 if (level->GetLevelID() != -1 && (level->GetLevelID() != levelID))
129 GetOStream(
Warnings1) <<
"Hierarchy::AddLevel(): Level with ID=" << level->GetLevelID() <<
130 " have been added at the end of the hierarchy\n but its ID have been redefined" <<
131 " because last level ID of the hierarchy was " << LastLevelID() <<
"." << std::endl;
133 Levels_.push_back(level);
134 level->SetLevelID(levelID);
137 level->SetPreviousLevel( (levelID == 0) ? Teuchos::null : Levels_[LastLevelID() - 1] );
138 level->setObjectLabel(this->getObjectLabel());
141 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
143 RCP<Level> newLevel = Levels_[LastLevelID()]->Build();
144 newLevel->setlib(lib_);
145 this->AddLevel(newLevel);
148 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
151 "MueLu::Hierarchy::GetLevel(): invalid input parameter value: LevelID = " << levelID);
152 return Levels_[levelID];
155 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
157 return Levels_.size();
160 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
162 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator> >(
"A");
163 RCP<const Teuchos::Comm<int> > comm = A->getDomainMap()->getComm();
165 int numLevels = GetNumLevels();
167 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, numLevels, Teuchos::ptr(&numGlobalLevels));
169 return numGlobalLevels;
172 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
174 double totalNnz = 0, lev0Nnz = 1;
175 for (
int i = 0; i < GetNumLevels(); ++i) {
177 "Operator complexity cannot be calculated because A is unavailable on level " << i);
178 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator> >(
"A");
182 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
184 GetOStream(
Warnings0) <<
"Some level operators are not matrices, operator complexity calculation aborted" << std::endl;
188 totalNnz += as<double>(Am->getGlobalNumEntries());
192 return totalNnz / lev0Nnz;
195 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
197 double node_sc = 0, global_sc=0;
199 const size_t INVALID = Teuchos::OrdinalTraits<size_t>::invalid();
201 if (GetNumLevels() <= 0)
return -1.0;
202 if (!Levels_[0]->IsAvailable(
"A"))
return -1.0;
204 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator> >(
"A");
205 if (A.is_null())
return -1.0;
206 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
207 if(Am.is_null())
return -1.0;
208 a0_nnz = as<double>(Am->getGlobalNumEntries());
211 for (
int i = 0; i < GetNumLevels(); ++i) {
213 if(!Levels_[i]->IsAvailable(
"PreSmoother"))
continue;
214 RCP<SmootherBase> S = Levels_[i]->template Get<RCP<SmootherBase> >(
"PreSmoother");
215 if (S.is_null())
continue;
216 level_sc = S->getNodeSmootherComplexity();
217 if(level_sc == INVALID) {global_sc=-1.0;
break;}
219 node_sc += as<double>(level_sc);
223 RCP<const Teuchos::Comm<int> > comm =A->getDomainMap()->getComm();
224 Teuchos::reduceAll(*comm,Teuchos::REDUCE_SUM,node_sc,Teuchos::ptr(&global_sc));
225 Teuchos::reduceAll(*comm,Teuchos::REDUCE_MIN,node_sc,Teuchos::ptr(&min_sc));
227 if(min_sc < 0.0)
return -1.0;
228 else return global_sc / a0_nnz;
235 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
238 "MueLu::Hierarchy::CheckLevel(): wrong underlying linear algebra library.");
240 "MueLu::Hierarchy::CheckLevel(): wrong level ID");
242 "MueLu::Hierarchy::Setup(): wrong level parent");
245 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
247 for (
int i = 0; i < GetNumLevels(); ++i) {
248 RCP<Level> level = Levels_[i];
249 if (level->IsAvailable(
"A")) {
250 RCP<Operator> Aop = level->Get<RCP<Operator> >(
"A");
251 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Aop);
253 RCP<const Import> xpImporter = A->getCrsGraph()->getImporter();
254 if (!xpImporter.is_null())
255 xpImporter->setDistributorParameters(matvecParams);
256 RCP<const Export> xpExporter = A->getCrsGraph()->getExporter();
257 if (!xpExporter.is_null())
258 xpExporter->setDistributorParameters(matvecParams);
261 if (level->IsAvailable(
"P")) {
262 RCP<Matrix> P = level->Get<RCP<Matrix> >(
"P");
263 RCP<const Import> xpImporter = P->getCrsGraph()->getImporter();
264 if (!xpImporter.is_null())
265 xpImporter->setDistributorParameters(matvecParams);
266 RCP<const Export> xpExporter = P->getCrsGraph()->getExporter();
267 if (!xpExporter.is_null())
268 xpExporter->setDistributorParameters(matvecParams);
270 if (level->IsAvailable(
"R")) {
271 RCP<Matrix> R = level->Get<RCP<Matrix> >(
"R");
272 RCP<const Import> xpImporter = R->getCrsGraph()->getImporter();
273 if (!xpImporter.is_null())
274 xpImporter->setDistributorParameters(matvecParams);
275 RCP<const Export> xpExporter = R->getCrsGraph()->getExporter();
276 if (!xpExporter.is_null())
277 xpExporter->setDistributorParameters(matvecParams);
279 if (level->IsAvailable(
"Importer")) {
280 RCP<const Import> xpImporter = level->Get< RCP<const Import> >(
"Importer");
281 if (!xpImporter.is_null())
282 xpImporter->setDistributorParameters(matvecParams);
289 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
291 const RCP<const FactoryManagerBase> fineLevelManager,
292 const RCP<const FactoryManagerBase> coarseLevelManager,
293 const RCP<const FactoryManagerBase> nextLevelManager) {
298 "MueLu::Hierarchy:Setup(): level " << coarseLevelID <<
" (specified by coarseLevelID argument) "
299 "must be built before calling this function.");
301 Level& level = *Levels_[coarseLevelID];
304 TimeMonitor m1(*
this, label + this->ShortClassName() +
": " +
"Setup (total)");
309 "MueLu::Hierarchy::Setup(): argument coarseLevelManager cannot be null");
314 if (levelManagers_.size() < coarseLevelID+1)
315 levelManagers_.resize(coarseLevelID+1);
316 levelManagers_[coarseLevelID] = coarseLevelManager;
318 bool isFinestLevel = (fineLevelManager.is_null());
319 bool isLastLevel = (nextLevelManager.is_null());
323 RCP<Operator> A = level.
Get< RCP<Operator> >(
"A");
324 RCP<const Map> domainMap = A->getDomainMap();
325 RCP<const Teuchos::Comm<int> > comm = domainMap->getComm();
332 oldRank = SetProcRankVerbose(comm->getRank());
336 lib_ = domainMap->lib();
343 Level& prevLevel = *Levels_[coarseLevelID-1];
344 oldRank = SetProcRankVerbose(prevLevel.
GetComm()->getRank());
347 CheckLevel(level, coarseLevelID);
350 RCP<SetFactoryManager> SFMFine;
352 SFMFine = rcp(
new SetFactoryManager(Levels_[coarseLevelID-1], fineLevelManager));
354 if (isFinestLevel && Levels_[coarseLevelID]->IsAvailable(
"Coordinates"))
355 ReplaceCoordinateMap(*Levels_[coarseLevelID]);
360 if (isDumpingEnabled_ && dumpLevel_ == 0 && coarseLevelID == 1)
363 RCP<TopSmootherFactory> coarseFact = rcp(
new TopSmootherFactory(coarseLevelManager,
"CoarseSolver"));
364 RCP<TopSmootherFactory> smootherFact = rcp(
new TopSmootherFactory(coarseLevelManager,
"Smoother"));
366 int nextLevelID = coarseLevelID + 1;
368 RCP<SetFactoryManager> SFMNext;
369 if (isLastLevel ==
false) {
371 if (nextLevelID > LastLevelID())
373 CheckLevel(*Levels_[nextLevelID], nextLevelID);
377 Levels_[nextLevelID]->Request(
TopRAPFactory(coarseLevelManager, nextLevelManager));
412 RCP<Operator> Ac = Teuchos::null;
413 TopRAPFactory coarseRAPFactory(fineLevelManager, coarseLevelManager);
416 Ac = level.
Get<RCP<Operator> >(
"A");
417 }
else if (!isFinestLevel) {
423 Ac = level.
Get<RCP<Operator> >(
"A");
424 RCP<Matrix> Acm = rcp_dynamic_cast<Matrix>(Ac);
428 level.
SetComm(Ac->getDomainMap()->getComm());
431 bool isOrigLastLevel = isLastLevel;
436 }
else if (Ac.is_null()) {
443 if (!Acm.is_null() && Acm->getGlobalNumRows() <= maxCoarseSize_) {
445 GetOStream(
Runtime0) <<
"Max coarse size (<= " << maxCoarseSize_ <<
") achieved" << std::endl;
450 if (!Ac.is_null() && !isFinestLevel) {
451 RCP<Operator> A = Levels_[coarseLevelID-1]->template Get< RCP<Operator> >(
"A");
452 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
454 const double maxCoarse2FineRatio = 0.8;
455 if (!Acm.is_null() && !Am.is_null() && Acm->getGlobalNumRows() > maxCoarse2FineRatio * Am->getGlobalNumRows()) {
463 GetOStream(
Warnings0) <<
"Aggregation stagnated. Please check your matrix and/or adjust your configuration file."
464 <<
"Possible fixes:\n"
465 <<
" - reduce the maximum number of levels\n"
466 <<
" - enable repartitioning\n"
467 <<
" - increase the minimum coarse size." << std::endl;
473 if (!isOrigLastLevel) {
483 coarseFact->Build(level);
494 smootherFact->Build(level);
499 if (isLastLevel ==
true) {
500 if (isOrigLastLevel ==
false) {
503 Levels_[nextLevelID]->Release(
TopRAPFactory(coarseLevelManager, nextLevelManager));
505 Levels_.resize(nextLevelID);
509 if (isDumpingEnabled_ && dumpLevel_ > 0 && coarseLevelID == dumpLevel_)
512 if (!isFinestLevel) {
516 level.
Release(coarseRAPFactory);
520 SetProcRankVerbose(oldRank);
525 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
527 int numLevels = Levels_.size();
529 "Hierarchy::SetupRe: " << Levels_.size() <<
" levels, but " << levelManagers_.size() <<
" level factory managers");
531 const int startLevel = 0;
534 #ifdef HAVE_MUELU_DEBUG
536 for (
int i = 0; i < numLevels; i++)
537 levelManagers_[i]->ResetDebugData();
542 for (levelID = startLevel; levelID < numLevels;) {
543 bool r = Setup(levelID,
544 (levelID != 0 ? levelManagers_[levelID-1] : Teuchos::null),
545 levelManagers_[levelID],
546 (levelID+1 != numLevels ? levelManagers_[levelID+1] : Teuchos::null));
552 Levels_ .resize(levelID);
553 levelManagers_.resize(levelID);
565 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
574 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") does not exist");
577 "Constructing non-positive (" << numDesiredLevels <<
") number of levels does not make sense.");
581 "MueLu::Hierarchy::Setup(): fine level (" << startLevel <<
") has no matrix A! "
582 "Set fine level matrix A using Level.Set()");
584 RCP<Operator> A = Levels_[startLevel]->template Get<RCP<Operator> >(
"A");
585 lib_ = A->getDomainMap()->lib();
588 RCP<Matrix> Amat = rcp_dynamic_cast<Matrix>(A);
590 if (!Amat.is_null()) {
591 RCP<ParameterList> params = rcp(
new ParameterList());
592 params->set(
"printLoadBalancingInfo",
true);
593 params->set(
"printCommInfo",
true);
597 GetOStream(
Warnings1) <<
"Fine level operator is not a matrix, statistics are not available" << std::endl;
601 RCP<const FactoryManagerBase> rcpmanager = rcpFromRef(manager);
603 const int lastLevel = startLevel + numDesiredLevels - 1;
604 GetOStream(
Runtime0) <<
"Setup loop: startLevel = " << startLevel <<
", lastLevel = " << lastLevel
605 <<
" (stop if numLevels = " << numDesiredLevels <<
" or Ac.size() < " << maxCoarseSize_ <<
")" << std::endl;
609 if (numDesiredLevels == 1) {
611 Setup(startLevel, Teuchos::null, rcpmanager, Teuchos::null);
614 bool bIsLastLevel = Setup(startLevel, Teuchos::null, rcpmanager, rcpmanager);
615 if (bIsLastLevel ==
false) {
616 for (iLevel = startLevel + 1; iLevel < lastLevel; iLevel++) {
617 bIsLastLevel = Setup(iLevel, rcpmanager, rcpmanager, rcpmanager);
618 if (bIsLastLevel ==
true)
621 if (bIsLastLevel ==
false)
622 Setup(lastLevel, rcpmanager, rcpmanager, Teuchos::null);
628 "MueLu::Hierarchy::Setup(): number of level");
637 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
639 if (startLevel < GetNumLevels())
640 GetOStream(
Runtime0) <<
"Clearing old data (if any)" << std::endl;
642 for (
int iLevel = startLevel; iLevel < GetNumLevels(); iLevel++)
643 Levels_[iLevel]->Clear();
646 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
648 GetOStream(
Runtime0) <<
"Clearing old data (expert)" << std::endl;
649 for (
int iLevel = 0; iLevel < GetNumLevels(); iLevel++)
650 Levels_[iLevel]->ExpertClear();
653 #if defined(HAVE_MUELU_EXPERIMENTAL) && defined(HAVE_MUELU_ADDITIVE_VARIANT)
654 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
656 bool InitialGuessIsZero, LO startLevel) {
657 LO nIts = conv.maxIts_;
658 MagnitudeType tol = conv.tol_;
660 std::string prefix = this->ShortClassName() +
": ";
661 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
662 std::string levelSuffix1 =
" (level=" +
toString(startLevel+1) +
")";
665 RCP<Time> CompTime = Teuchos::TimeMonitor::getNewCounter(prefix +
"Computational Time (total)");
666 RCP<Time> Concurrent = Teuchos::TimeMonitor::getNewCounter(prefix +
"Concurrent portion");
667 RCP<Time> ApplyR = Teuchos::TimeMonitor::getNewCounter(prefix +
"R: Computational Time");
668 RCP<Time> ApplyPbar = Teuchos::TimeMonitor::getNewCounter(prefix +
"Pbar: Computational Time");
669 RCP<Time> CompFine = Teuchos::TimeMonitor::getNewCounter(prefix +
"Fine: Computational Time");
670 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
671 RCP<Time> ApplySum = Teuchos::TimeMonitor::getNewCounter(prefix +
"Sum: Computational Time");
672 RCP<Time> Synchronize_beginning = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_beginning");
673 RCP<Time> Synchronize_center = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_center");
674 RCP<Time> Synchronize_end = Teuchos::TimeMonitor::getNewCounter(prefix +
"Synchronize_end");
676 RCP<Level> Fine = Levels_[0];
679 RCP<Operator> A = Fine->Get< RCP<Operator> >(
"A");
680 Teuchos::RCP< const Teuchos::Comm< int > > communicator = A->getDomainMap()->getComm();
689 SC one = STS::one(), zero = STS::zero();
691 bool zeroGuess = InitialGuessIsZero;
697 RCP< Operator > Pbar;
699 RCP< MultiVector > coarseRhs, coarseX;
701 RCP<SmootherBase> preSmoo_coarse, postSmoo_coarse;
702 bool emptyCoarseSolve =
true;
703 RCP<MultiVector> coarseX_prolonged = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
705 RCP<const Import> importer;
707 if (Levels_.size() > 1) {
709 if (Coarse->IsAvailable(
"Importer"))
710 importer = Coarse->Get< RCP<const Import> >(
"Importer");
712 R = Coarse->Get< RCP<Operator> >(
"R");
713 P = Coarse->Get< RCP<Operator> >(
"P");
717 Pbar = Coarse->Get< RCP<Operator> >(
"Pbar");
719 coarseRhs = MultiVectorFactory::Build(R->getRangeMap(), B.getNumVectors(),
true);
721 Ac = Coarse->Get< RCP< Operator > >(
"A");
724 R->apply(B, *coarseRhs, Teuchos::NO_TRANS, one, zero);
728 if (doPRrebalance_ || importer.is_null()) {
729 coarseX = MultiVectorFactory::Build(coarseRhs->getMap(), X.getNumVectors(),
true);
733 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import (total)" ,
Timings0));
734 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
737 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getTargetMap(), coarseRhs->getNumVectors());
738 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
739 coarseRhs.swap(coarseTmp);
741 coarseX = MultiVectorFactory::Build(importer->getTargetMap(), X.getNumVectors(),
true);
744 if (Coarse->IsAvailable(
"PreSmoother"))
745 preSmoo_coarse = Coarse->Get< RCP<SmootherBase> >(
"PreSmoother");
746 if (Coarse->IsAvailable(
"PostSmoother"))
747 postSmoo_coarse = Coarse->Get< RCP<SmootherBase> >(
"PostSmoother");
753 MagnitudeType prevNorm = STS::magnitude(STS::one()), curNorm = STS::magnitude(STS::one());
756 for (LO i = 1; i <= nIts; i++) {
757 #ifdef HAVE_MUELU_DEBUG
758 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
759 std::ostringstream ss;
760 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
761 throw Exceptions::Incompatible(ss.str());
764 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
765 std::ostringstream ss;
766 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
767 throw Exceptions::Incompatible(ss.str());
772 bool emptyFineSolve =
true;
774 RCP< MultiVector > fineX;
775 fineX = MultiVectorFactory::Build(X.getMap(), X.getNumVectors(),
true);
784 if (Fine->IsAvailable(
"PreSmoother")) {
785 RCP<SmootherBase> preSmoo = Fine->Get< RCP<SmootherBase> >(
"PreSmoother");
787 preSmoo->Apply(*fineX, B, zeroGuess);
789 emptyFineSolve =
false;
791 if (Fine->IsAvailable(
"PostSmoother")) {
792 RCP<SmootherBase> postSmoo = Fine->Get< RCP<SmootherBase> >(
"PostSmoother");
794 postSmoo->Apply(*fineX, B, zeroGuess);
797 emptyFineSolve =
false;
799 if (emptyFineSolve ==
true) {
800 GetOStream(
Warnings1) <<
"No fine grid smoother" << std::endl;
802 fineX->update(one, B, zero);
805 if (Levels_.size() > 1) {
807 if (Coarse->IsAvailable(
"PreSmoother")) {
809 preSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
811 emptyCoarseSolve =
false;
814 if (Coarse->IsAvailable(
"PostSmoother")) {
816 postSmoo_coarse->Apply(*coarseX, *coarseRhs, zeroGuess);
818 emptyCoarseSolve =
false;
821 if (emptyCoarseSolve ==
true) {
822 GetOStream(
Warnings1) <<
"No coarse grid solver" << std::endl;
824 coarseX->update(one, *coarseRhs, zero);
831 if (!doPRrebalance_ && !importer.is_null()) {
832 RCP<TimeMonitor> ITime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export (total)" ,
Timings0));
833 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
836 RCP<MultiVector> coarseTmp = MultiVectorFactory::Build(importer->getSourceMap(), coarseX->getNumVectors());
837 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
838 coarseX.swap(coarseTmp);
842 Pbar->apply(*coarseX, *coarseX_prolonged, Teuchos::NO_TRANS, one, zero);
847 X.update(1.0, *fineX, 1.0, *coarseX_prolonged, 0.0);
858 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
860 bool InitialGuessIsZero, LO startLevel) {
876 RCP<Level> Fine = Levels_[startLevel];
879 std::string prefix = label + this->ShortClassName() +
": ";
880 std::string levelSuffix =
" (level=" +
toString(startLevel) +
")";
881 std::string levelSuffix1 =
" (level=" +
toString(startLevel+1) +
")";
883 bool useStackedTimer = !Teuchos::TimeMonitor::getStackedTimer().is_null();
885 RCP<Monitor> iterateTime;
886 RCP<TimeMonitor> iterateTime1;
889 else if (!useStackedTimer)
892 std::string iterateLevelTimeLabel = prefix +
"Solve" + levelSuffix;
893 RCP<TimeMonitor> iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel,
Timings0));
895 bool zeroGuess = InitialGuessIsZero;
897 RCP<Operator> A = Fine->Get< RCP<Operator> >(
"A");
899 RCP<Time> CompCoarse = Teuchos::TimeMonitor::getNewCounter(prefix +
"Coarse: Computational Time");
912 const BlockedMultiVector * Bblocked =
dynamic_cast<const BlockedMultiVector*
>(&B);
913 if(residual_.size() > startLevel &&
914 ( ( Bblocked && !Bblocked->isSameSize(*residual_[startLevel])) ||
915 (!Bblocked && !residual_[startLevel]->isSameSize(B))))
916 DeleteLevelMultiVectors();
917 AllocateLevelMultiVectors(X.getNumVectors());
920 typedef Teuchos::ScalarTraits<typename STS::magnitudeType> STM;
923 if (startLevel == 0 && !isPreconditioner_ &&
927 Teuchos::Array<MagnitudeType> rn;
932 for (LO k = 0; k < rn.size(); k++)
942 << std::setiosflags(std::ios::left)
943 << std::setprecision(3) << 0
945 << std::setprecision(10) << rn
949 SC one = STS::one(), zero = STS::zero();
950 for (LO i = 1; i <= nIts; i++) {
951 #ifdef HAVE_MUELU_DEBUG
953 if (A->getDomainMap()->isCompatible(*(X.getMap())) ==
false) {
954 std::ostringstream ss;
955 ss <<
"Level " << startLevel <<
": level A's domain map is not compatible with X";
959 if (A->getRangeMap()->isCompatible(*(B.getMap())) ==
false) {
960 std::ostringstream ss;
961 ss <<
"Level " << startLevel <<
": level A's range map is not compatible with B";
967 if (startLevel == as<LO>(Levels_.size())-1) {
969 RCP<TimeMonitor> CLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : coarse" + levelSuffix,
Timings0));
971 bool emptySolve =
true;
974 if (Fine->IsAvailable(
"PreSmoother")) {
975 RCP<SmootherBase> preSmoo = Fine->Get< RCP<SmootherBase> >(
"PreSmoother");
977 preSmoo->Apply(X, B, zeroGuess);
982 if (Fine->IsAvailable(
"PostSmoother")) {
983 RCP<SmootherBase> postSmoo = Fine->Get< RCP<SmootherBase> >(
"PostSmoother");
985 postSmoo->Apply(X, B, zeroGuess);
989 if (emptySolve ==
true) {
990 GetOStream(
Warnings1) <<
"No coarse grid solver" << std::endl;
992 X.update(one, B, zero);
997 RCP<Level> Coarse = Levels_[startLevel+1];
1000 RCP<TimeMonitor> STime;
1001 if (!useStackedTimer)
1003 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1005 if (Fine->IsAvailable(
"PreSmoother")) {
1006 RCP<SmootherBase> preSmoo = Fine->Get< RCP<SmootherBase> >(
"PreSmoother");
1007 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));
1018 residual = residual_[startLevel];
1021 RCP<Operator> P = Coarse->Get< RCP<Operator> >(
"P");
1022 if (Coarse->IsAvailable(
"Pbar"))
1023 P = Coarse->Get< RCP<Operator> >(
"Pbar");
1025 RCP<MultiVector> coarseRhs, coarseX;
1029 RCP<TimeMonitor> RTime;
1030 if (!useStackedTimer)
1032 RCP<TimeMonitor> RLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : restriction" + levelSuffix,
Timings0));
1033 coarseRhs = coarseRhs_[startLevel];
1035 if (implicitTranspose_) {
1036 P->apply(*residual, *coarseRhs, Teuchos::TRANS, one, zero);
1039 RCP<Operator> R = Coarse->Get< RCP<Operator> >(
"R");
1040 R->apply(*residual, *coarseRhs, Teuchos::NO_TRANS, one, zero);
1044 RCP<const Import> importer;
1045 if (Coarse->IsAvailable(
"Importer"))
1046 importer = Coarse->Get< RCP<const Import> >(
"Importer");
1048 coarseX = coarseX_[startLevel];
1049 if (!doPRrebalance_ && !importer.is_null()) {
1050 RCP<TimeMonitor> ITime;
1051 if (!useStackedTimer)
1053 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : import" + levelSuffix1,
Timings0));
1056 RCP<MultiVector> coarseTmp = coarseImport_[startLevel];
1057 coarseTmp->doImport(*coarseRhs, *importer, Xpetra::INSERT);
1058 coarseRhs.swap(coarseTmp);
1061 RCP<Operator> Ac = Coarse->Get< RCP<Operator> >(
"A");
1062 if (!Ac.is_null()) {
1063 RCP<const Map> origXMap = coarseX->getMap();
1064 RCP<const Map> origRhsMap = coarseRhs->getMap();
1067 coarseRhs->replaceMap(Ac->getRangeMap());
1068 coarseX ->replaceMap(Ac->getDomainMap());
1071 iterateLevelTime = Teuchos::null;
1073 Iterate(*coarseRhs, *coarseX, 1,
true, startLevel+1);
1076 Iterate(*coarseRhs, *coarseX, 1,
false, startLevel+1);
1079 iterateLevelTime = rcp(
new TimeMonitor(*
this, iterateLevelTimeLabel));
1081 coarseX->replaceMap(origXMap);
1082 coarseRhs->replaceMap(origRhsMap);
1085 if (!doPRrebalance_ && !importer.is_null()) {
1086 RCP<TimeMonitor> ITime;
1087 if (!useStackedTimer)
1089 RCP<TimeMonitor> ILevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : export" + levelSuffix1,
Timings0));
1092 RCP<MultiVector> coarseTmp = coarseExport_[startLevel];
1093 coarseTmp->doExport(*coarseX, *importer, Xpetra::INSERT);
1094 coarseX.swap(coarseTmp);
1099 RCP<TimeMonitor> PTime;
1100 if (!useStackedTimer)
1102 RCP<TimeMonitor> PLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : prolongation" + levelSuffix,
Timings0));
1107 if (fuseProlongationAndUpdate_) {
1108 P->apply(*coarseX, X, Teuchos::NO_TRANS, scalingFactor_, one);
1110 RCP<MultiVector> correction = correction_[startLevel];
1111 P->apply(*coarseX, *correction, Teuchos::NO_TRANS, one, zero);
1112 X.update(scalingFactor_, *correction, one);
1118 RCP<TimeMonitor> STime;
1119 if (!useStackedTimer)
1121 RCP<TimeMonitor> SLevelTime = rcp(
new TimeMonitor(*
this, prefix +
"Solve : smoothing" + levelSuffix,
Timings0));
1123 if (Fine->IsAvailable(
"PostSmoother")) {
1124 RCP<SmootherBase> postSmoo = Fine->Get< RCP<SmootherBase> >(
"PostSmoother");
1125 postSmoo->Apply(X, B,
false);
1131 if (startLevel == 0 && !isPreconditioner_ &&
1135 Teuchos::Array<MagnitudeType> rn;
1140 rate_ = as<MagnitudeType>(curNorm / prevNorm);
1144 << std::setiosflags(std::ios::left)
1145 << std::setprecision(3) << i
1147 << std::setprecision(10) << rn
1152 for (LO k = 0; k < rn.size(); k++)
1166 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1168 LO startLevel = (start != -1 ? start : 0);
1169 LO endLevel = (end != -1 ? end : Levels_.size()-1);
1172 "MueLu::Hierarchy::Write : startLevel must be <= endLevel");
1175 "MueLu::Hierarchy::Write bad start or end level");
1177 for (LO i = startLevel; i < endLevel + 1; i++) {
1178 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get< RCP< Operator> >(
"A")), P, R;
1180 P = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get< RCP< Operator> >(
"P"));
1181 if (!implicitTranspose_)
1182 R = rcp_dynamic_cast<Matrix>(Levels_[i]->
template Get< RCP< Operator> >(
"R"));
1185 if (!A.is_null()) Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"A_" +
toString(i) + suffix +
".m", *A);
1187 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"P_" +
toString(i) + suffix +
".m", *P);
1190 Xpetra::IO<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Write(
"R_" +
toString(i) + suffix +
".m", *R);
1195 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1197 for (Array<RCP<Level> >::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1198 (*it)->Keep(ename, factory);
1201 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1203 for (Array<RCP<Level> >::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1204 (*it)->Delete(ename, factory);
1207 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1209 for (Array<RCP<Level> >::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1210 (*it)->AddKeepFlag(ename, factory, keep);
1213 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1215 for (Array<RCP<Level> >::iterator it = Levels_.begin(); it != Levels_.end(); ++it)
1216 (*it)->RemoveKeepFlag(ename, factory, keep);
1219 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1221 if ( description_.empty() )
1223 std::ostringstream out;
1225 out <<
"{#levels = " << GetGlobalNumLevels() <<
", complexity = " << GetOperatorComplexity() <<
"}";
1226 description_ = out.str();
1228 return description_;
1231 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1236 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1238 RCP<Operator> A0 = Levels_[0]->template Get<RCP<Operator> >(
"A");
1239 RCP<const Teuchos::Comm<int> > comm = A0->getDomainMap()->getComm();
1241 int numLevels = GetNumLevels();
1242 RCP<Operator> Ac = Levels_[numLevels-1]->template Get<RCP<Operator> >(
"A");
1249 int root = comm->getRank();
1252 int smartData = numLevels*comm->getSize() + comm->getRank(), maxSmartData;
1253 reduceAll(*comm, Teuchos::REDUCE_MAX, smartData, Teuchos::ptr(&maxSmartData));
1254 root = maxSmartData % comm->getSize();
1258 double smoother_comp =-1.0;
1260 smoother_comp = GetSmootherComplexity();
1264 std::vector<Xpetra::global_size_t> nnzPerLevel;
1265 std::vector<Xpetra::global_size_t> rowsPerLevel;
1266 std::vector<int> numProcsPerLevel;
1267 bool aborted =
false;
1268 for (
int i = 0; i < numLevels; i++) {
1270 "Operator A is not available on level " << i);
1272 RCP<Operator> A = Levels_[i]->template Get<RCP<Operator> >(
"A");
1274 "Operator A on level " << i <<
" is null.");
1276 RCP<Matrix> Am = rcp_dynamic_cast<Matrix>(A);
1278 GetOStream(
Warnings0) <<
"Some level operators are not matrices, statistics calculation aborted" << std::endl;
1283 Xpetra::global_size_t nnz = Am->getGlobalNumEntries();
1284 nnzPerLevel .push_back(nnz);
1285 rowsPerLevel .push_back(Am->getGlobalNumRows());
1286 numProcsPerLevel.push_back(Am->getRowMap()->getComm()->getSize());
1290 std::string label = Levels_[0]->getObjectLabel();
1291 std::ostringstream oss;
1292 oss << std::setfill(
' ');
1293 oss <<
"\n--------------------------------------------------------------------------------\n";
1294 oss <<
"--- Multigrid Summary " << std::setw(28) << std::left << label <<
"---\n";
1295 oss <<
"--------------------------------------------------------------------------------" << std::endl;
1296 oss <<
"Number of levels = " << numLevels << std::endl;
1297 oss <<
"Operator complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1298 << GetOperatorComplexity() << std::endl;
1300 if(smoother_comp!=-1.0) {
1301 oss <<
"Smoother complexity = " << std::setprecision(2) << std::setiosflags(std::ios::fixed)
1302 << smoother_comp << std::endl;
1307 oss <<
"Cycle type = V" << std::endl;
1310 oss <<
"Cycle type = W" << std::endl;
1317 Xpetra::global_size_t tt = rowsPerLevel[0];
1318 int rowspacer = 2;
while (tt != 0) { tt /= 10; rowspacer++; }
1319 tt = nnzPerLevel[0];
1320 int nnzspacer = 2;
while (tt != 0) { tt /= 10; nnzspacer++; }
1321 tt = numProcsPerLevel[0];
1322 int npspacer = 2;
while (tt != 0) { tt /= 10; npspacer++; }
1323 oss <<
"level " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " <<
" nnz/row" << std::setw(npspacer) <<
" c ratio" <<
" procs" << std::endl;
1324 for (
size_t i = 0; i < nnzPerLevel.size(); ++i) {
1325 oss <<
" " << i <<
" ";
1326 oss << std::setw(rowspacer) << rowsPerLevel[i];
1327 oss << std::setw(nnzspacer) << nnzPerLevel[i];
1328 oss << std::setprecision(2) << std::setiosflags(std::ios::fixed);
1329 oss << std::setw(9) << as<double>(nnzPerLevel[i]) / rowsPerLevel[i];
1330 if (i) oss << std::setw(9) << as<double>(rowsPerLevel[i-1])/rowsPerLevel[i];
1331 else oss << std::setw(9) <<
" ";
1332 oss <<
" " << std::setw(npspacer) << numProcsPerLevel[i] << std::endl;
1335 for (
int i = 0; i < GetNumLevels(); ++i) {
1336 RCP<SmootherBase> preSmoo, postSmoo;
1337 if (Levels_[i]->IsAvailable(
"PreSmoother"))
1338 preSmoo = Levels_[i]->
template Get< RCP<SmootherBase> >(
"PreSmoother");
1339 if (Levels_[i]->IsAvailable(
"PostSmoother"))
1340 postSmoo = Levels_[i]->
template Get< RCP<SmootherBase> >(
"PostSmoother");
1342 if (preSmoo !=
null && preSmoo == postSmoo)
1343 oss <<
"Smoother (level " << i <<
") both : " << preSmoo->description() << std::endl;
1345 oss <<
"Smoother (level " << i <<
") pre : "
1346 << (preSmoo !=
null ? preSmoo->description() :
"no smoother") << std::endl;
1347 oss <<
"Smoother (level " << i <<
") post : "
1348 << (postSmoo !=
null ? postSmoo->description() :
"no smoother") << std::endl;
1359 RCP<const Teuchos::MpiComm<int> > mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int> >(comm);
1360 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1362 int strLength = outstr.size();
1363 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1364 if (comm->getRank() != root)
1365 outstr.resize(strLength);
1366 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1373 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1375 Teuchos::OSTab tab2(out);
1376 for (
int i = 0; i < GetNumLevels(); ++i)
1377 Levels_[i]->print(out, verbLevel);
1380 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1382 isPreconditioner_ = flag;
1385 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1387 if (GetProcRankVerbose() != 0)
1389 #if defined(HAVE_MUELU_BOOST) && defined(HAVE_MUELU_BOOST_FOR_REAL) && defined(BOOST_VERSION) && (BOOST_VERSION >= 104400)
1393 dp.property(
"label", boost::get(boost::vertex_name, graph));
1394 dp.property(
"id", boost::get(boost::vertex_index, graph));
1395 dp.property(
"label", boost::get(boost::edge_name, graph));
1396 dp.property(
"color", boost::get(boost::edge_color, graph));
1399 std::map<const FactoryBase*, BoostVertex> vindices;
1400 typedef std::map<std::pair<BoostVertex,BoostVertex>, std::string> emap; emap edges;
1402 static int call_id=0;
1404 RCP<Operator> A = Levels_[0]->template Get<RCP<Operator> >(
"A");
1405 int rank = A->getDomainMap()->getComm()->getRank();
1408 for (
int i = dumpLevel_; i <= dumpLevel_+1 && i < GetNumLevels(); i++) {
1410 Levels_[i]->UpdateGraph(vindices, edges, dp, graph);
1412 for (emap::const_iterator eit = edges.begin(); eit != edges.end(); eit++) {
1413 std::pair<BoostEdge, bool> boost_edge = boost::add_edge(eit->first.first, eit->first.second, graph);
1416 if(eit->second==std::string(
"Graph")) boost::put(
"label", dp, boost_edge.first, std::string(
"Graph_"));
1417 else boost::put(
"label", dp, boost_edge.first, eit->second);
1418 if (i == dumpLevel_)
1419 boost::put(
"color", dp, boost_edge.first, std::string(
"red"));
1421 boost::put(
"color", dp, boost_edge.first, std::string(
"blue"));
1426 std::ostringstream legend;
1427 legend <<
"< <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\"> \
1428 <TR><TD COLSPAN=\"2\">Legend</TD></TR> \
1429 <TR><TD><FONT color=\"red\">Level " << dumpLevel_ <<
"</FONT></TD><TD><FONT color=\"blue\">Level " << dumpLevel_+1 <<
"</FONT></TD></TR> \
1431 BoostVertex boost_vertex = boost::add_vertex(graph);
1432 boost::put(
"label", dp, boost_vertex, legend.str());
1435 std::ofstream out(dumpFile_.c_str() +std::to_string(call_id)+std::string(
"_")+ std::to_string(rank) + std::string(
".dot"));
1436 boost::write_graphviz_dp(out, graph, dp, std::string(
"id"));
1440 GetOStream(
Errors) <<
"Dependency graph output requires boost and MueLu_ENABLE_Boost_for_real" << std::endl;
1445 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1447 RCP<Operator> Ao = level.
Get<RCP<Operator> >(
"A");
1448 RCP<Matrix> A = rcp_dynamic_cast<Matrix>(Ao);
1450 GetOStream(
Warnings1) <<
"Hierarchy::ReplaceCoordinateMap: operator is not a matrix, skipping..." << std::endl;
1453 if(Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A) != Teuchos::null) {
1454 GetOStream(
Warnings1) <<
"Hierarchy::ReplaceCoordinateMap: operator is a BlockedCrsMatrix, skipping..." << std::endl;
1458 typedef Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::coordinateType,LO,GO,NO> xdMV;
1460 RCP<xdMV> coords = level.
Get<RCP<xdMV> >(
"Coordinates");
1462 if (A->getRowMap()->isSameAs(*(coords->getMap()))) {
1463 GetOStream(
Warnings1) <<
"Hierarchy::ReplaceCoordinateMap: matrix and coordinates maps are same, skipping..." << std::endl;
1467 if (A->IsView(
"stridedMaps") && rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps")) != Teuchos::null) {
1468 RCP<const StridedMap> stridedRowMap = rcp_dynamic_cast<const StridedMap>(A->getRowMap(
"stridedMaps"));
1471 TEUCHOS_TEST_FOR_EXCEPTION(stridedRowMap->getStridedBlockId() != -1 || stridedRowMap->getOffset() != 0,
1472 Exceptions::RuntimeError,
"Hierarchy::ReplaceCoordinateMap: nontrivial maps (block id = " << stridedRowMap->getStridedBlockId()
1473 <<
", offset = " << stridedRowMap->getOffset() <<
")");
1476 GetOStream(
Runtime1) <<
"Replacing coordinate map" << std::endl;
1478 size_t blkSize = A->GetFixedBlockSize();
1480 RCP<const Map> nodeMap = A->getRowMap();
1483 RCP<const Map> dofMap = A->getRowMap();
1484 GO indexBase = dofMap->getIndexBase();
1485 size_t numLocalDOFs = dofMap->getNodeNumElements();
1487 "Hierarchy::ReplaceCoordinateMap: block size (" << blkSize <<
") is incompatible with the number of local dofs in a row map (" << numLocalDOFs);
1488 ArrayView<const GO> GIDs = dofMap->getNodeElementList();
1490 Array<GO> nodeGIDs(numLocalDOFs/blkSize);
1491 for (
size_t i = 0; i < numLocalDOFs; i += blkSize)
1492 nodeGIDs[i/blkSize] = (GIDs[i] - indexBase)/blkSize + indexBase;
1494 Xpetra::global_size_t INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
1495 nodeMap = MapFactory::Build(dofMap->lib(), INVALID, nodeGIDs(), indexBase, dofMap->getComm());
1501 if(coords->getLocalLength() != A->getRowMap()->getNodeNumElements()) {
1502 GetOStream(
Warnings) <<
"Coordinate vector does not match row map of matrix A!" << std::endl;
1507 Array<ArrayView<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> > coordDataView;
1508 std::vector<ArrayRCP<const typename Teuchos::ScalarTraits<Scalar>::coordinateType> > coordData;
1509 for (
size_t i = 0; i < coords->getNumVectors(); i++) {
1510 coordData.push_back(coords->getData(i));
1511 coordDataView.push_back(coordData[i]());
1514 RCP<xdMV> newCoords = Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::coordinateType,LO,GO,NO>::Build(nodeMap, coordDataView(), coords->getNumVectors());
1515 level.
Set(
"Coordinates", newCoords);
1518 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1520 int N = Levels_.size();
1521 if( (sizeOfAllocatedLevelMultiVectors_ == numvecs && residual_.size() == N) || numvecs<=0 )
return;
1524 if(residual_.size() != N) {
1525 DeleteLevelMultiVectors();
1527 residual_.resize(N);
1528 coarseRhs_.resize(N);
1530 coarseImport_.resize(N);
1531 coarseExport_.resize(N);
1532 correction_.resize(N);
1535 for(
int i=0; i<N; i++) {
1536 RCP<Operator> A = Levels_[i]->template Get< RCP<Operator> >(
"A");
1539 RCP<const BlockedCrsMatrix> A_as_blocked = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(A);
1540 RCP<const Map> Arm = A->getRangeMap();
1541 RCP<const Map> Adm = A->getDomainMap();
1542 if(!A_as_blocked.is_null()) {
1543 Adm = A_as_blocked->getFullDomainMap();
1547 residual_[i] = MultiVectorFactory::Build(Arm, numvecs,
true);
1548 correction_[i] = MultiVectorFactory::Build(Adm, numvecs,
false);
1553 if(implicitTranspose_) {
1554 RCP<Operator> P = Levels_[i+1]->template Get< RCP<Operator> >(
"P");
1555 if(!P.is_null()) coarseRhs_[i] = MultiVectorFactory::Build(P->getDomainMap(),numvecs,
true);
1557 RCP<Operator> R = Levels_[i+1]->template Get< RCP<Operator> >(
"R");
1558 if(!R.is_null()) coarseRhs_[i] = MultiVectorFactory::Build(R->getRangeMap(),numvecs,
true);
1562 RCP<const Import> importer;
1563 if(Levels_[i+1]->IsAvailable(
"Importer"))
1564 importer = Levels_[i+1]->
template Get< RCP<const Import> >(
"Importer");
1565 if (doPRrebalance_ || importer.is_null())
1566 coarseX_[i] = MultiVectorFactory::Build(coarseRhs_[i]->getMap(),numvecs,
false);
1568 coarseImport_[i] = MultiVectorFactory::Build(importer->getTargetMap(), numvecs,
false);
1569 coarseExport_[i] = MultiVectorFactory::Build(importer->getSourceMap(), numvecs,
false);
1570 coarseX_[i] = MultiVectorFactory::Build(importer->getTargetMap(),numvecs,
false);
1574 sizeOfAllocatedLevelMultiVectors_ = numvecs;
1578 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1580 if(sizeOfAllocatedLevelMultiVectors_==0)
return;
1581 residual_.resize(0);
1582 coarseRhs_.resize(0);
1584 coarseImport_.resize(0);
1585 coarseExport_.resize(0);
1586 correction_.resize(0);
1587 sizeOfAllocatedLevelMultiVectors_ = 0;
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.
void CheckLevel(Level &level, int levelID)
Helper function.
std::string description() const
Return a simple one-line description of this object.
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.
void DeleteLevelMultiVectors()
void SetMatvecParams(RCP< ParameterList > matvecParams)
Xpetra::UnderlyingLib lib_
void Clear(int startLevel=0)
Clear impermanent data from previous setup.
ReturnType Iterate(const MultiVector &B, MultiVector &X, ConvData conv=ConvData(), bool InitialGuessIsZero=false, LO startLevel=0)
Apply the multigrid preconditioner.
double GetOperatorComplexity() const
void print(std::ostream &out=std::cout, const VerbLevel verbLevel=(MueLu::Parameters|MueLu::Statistics0)) const
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 AllocateLevelMultiVectors(int numvecs)
void DumpCurrentGraph() const
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)
void Release(const FactoryBase &factory)
Decrement the storage counter for all the inputs of a factory.
int GetLevelID() const
Return level number.
RCP< const Teuchos::Comm< int > > GetComm() const
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()
RCP< Level > & GetPreviousLevel()
Previous level.
Timer to be used in non-factories.
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 Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &RHS)
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 void SetRandomSeed(const Teuchos::Comm< int > &comm)
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.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
VerbLevel toMueLuVerbLevel(const Teuchos::EVerbosityLevel verbLevel)
Data struct for defining stopping criteria of multigrid iteration.