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() +
": ";
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() +
": ";
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());
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);
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;
1593 #endif // MUELU_HIERARCHY_DEF_HPP