MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_RebalanceAcFactory_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// MueLu: A package for multigrid based preconditioning
4//
5// Copyright 2012 NTESS and the MueLu contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef MUELU_REBALANCEACFACTORY_DEF_HPP
11#define MUELU_REBALANCEACFACTORY_DEF_HPP
12
13#include <Xpetra_Matrix.hpp>
14#include <Xpetra_CrsMatrix.hpp>
15#include <Xpetra_CrsMatrixWrap.hpp>
16#include <Xpetra_MatrixFactory.hpp>
17
19
20#include "MueLu_MasterList.hpp"
21#include "MueLu_Monitor.hpp"
22#include "MueLu_PerfUtils.hpp"
23#include "MueLu_RAPFactory.hpp"
24
25namespace MueLu {
26
27template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
29
30template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
32
33template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
35 RCP<ParameterList> validParamList = rcp(new ParameterList());
36
37#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
38 SET_VALID_ENTRY("repartition: use subcommunicators");
39 SET_VALID_ENTRY("repartition: use subcommunicators in place");
40#undef SET_VALID_ENTRY
41
42 validParamList->set<std::string>("Matrix name", "A", "Name of the matrix that will be transferred on the coarse grid (level key)");
43
44 validParamList->set<RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A for rebalancing");
45 validParamList->set<RCP<const FactoryBase> >("Importer", Teuchos::null, "Generating factory of the importer");
46 validParamList->set<RCP<const FactoryBase> >("InPlaceMap", Teuchos::null, "Generating factory of the InPlaceMap");
47
48 return validParamList;
49}
50
51template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
53 const Teuchos::ParameterList &pL = GetParameterList();
54 std::string matrixName = pL.get<std::string>("Matrix name");
55 coarseLevel.DeclareInput(matrixName, GetFactory("A").get(), this);
56 if (pL.isParameter("repartition: use subcommunicators in place") && pL.get<bool>("repartition: use subcommunicators in place") == true) {
57 Input(coarseLevel, "InPlaceMap");
58 } else
59 Input(coarseLevel, "Importer");
60}
61
62template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
64 const Teuchos::ParameterList &pL = GetParameterList();
65 auto matrixName = pL.get<std::string>("Matrix name");
66 std::string coarseMatrixName;
67 if (matrixName.size() == 1)
68 coarseMatrixName = matrixName + "c";
69 else
70 coarseMatrixName = matrixName + "_coarse";
71
72 // ugly hack to fix issue with MinvA when number of max levels is small. Arises because
73 // M, Minv, or MinvA are not needed or requested/produced on last level and so we shouldn't
74 // try to rebalance them in this case. Note: Limiting the possible early return from this
75 // function only for M, Minv, or MinvA as in the reuse case data might not be available
76 // but Get() knows how to produce (or reuse it).
77
78 if (!(coarseLevel.IsAvailable(matrixName, GetFactory("A").get())) && ((matrixName == "M") || (matrixName == "Minv") || (matrixName == "MinvA"))) return;
79 FactoryMonitor m(*this, "Computing " + coarseMatrixName, coarseLevel);
80
81 RCP<Matrix> originalAc = coarseLevel.Get<RCP<Matrix> >(matrixName, GetFactory("A").get());
82
83 // This is a short-circuit for if we want to leave A where it is, but restrict its communicator
84 // to something corresponding to a given map. Maxwell1 is the prime customer for this.
85 bool inPlace = pL.get<bool>("repartition: use subcommunicators in place");
86 if (inPlace) {
87 SubFactoryMonitor subM(*this, "Rebalancing existing " + coarseMatrixName + " in-place", coarseLevel);
88 RCP<const Map> newMap = Get<RCP<const Map> >(coarseLevel, "InPlaceMap");
89
90 originalAc->removeEmptyProcessesInPlace(newMap);
91
92 // The "in place" still leaves a dummy matrix here. That needs to go
93 if (newMap.is_null()) originalAc = Teuchos::null;
94
95 Set(coarseLevel, matrixName, originalAc);
96 return;
97 }
98
99 RCP<const Import> rebalanceImporter = Get<RCP<const Import> >(coarseLevel, "Importer");
100
101 if (rebalanceImporter != Teuchos::null) {
102 RCP<Matrix> rebalancedAc;
103 {
104 SubFactoryMonitor subM(*this, "Rebalancing existing " + coarseMatrixName, coarseLevel);
105 RCP<const Map> targetMap = rebalanceImporter->getTargetMap();
106
107 ParameterList XpetraList;
108 if (pL.get<bool>("repartition: use subcommunicators") == true) {
109 GetOStream(Runtime0) << "Replacing maps with a subcommunicator" << std::endl;
110 XpetraList.set("Restrict Communicator", true);
111 }
112 XpetraList.set("compute global constants", IsPrint(Statistics1));
113 // NOTE: If the communicator is restricted away, Build returns Teuchos::null.
114 XpetraList.set("Timer Label", "MueLu::RebalanceAc-" + Teuchos::toString(coarseLevel.GetLevelID()));
115 {
116 SubFactoryMonitor subM2(*this, "Rebalancing existing " + coarseMatrixName + ": MatrixFactory::Build", coarseLevel);
117 rebalancedAc = MatrixFactory::Build(originalAc, *rebalanceImporter, *rebalanceImporter, targetMap, targetMap, rcp(&XpetraList, false));
118 }
119
120 if (!rebalancedAc.is_null()) {
121 if (originalAc->IsFixedBlockSizeSet())
122 rebalancedAc->SetFixedBlockSize(originalAc->GetFixedBlockSize());
123 std::ostringstream oss;
124 oss << "A_" << coarseLevel.GetLevelID();
125 rebalancedAc->setObjectLabel(oss.str());
126 }
127 Set(coarseLevel, matrixName, rebalancedAc);
128 }
129 if (!rebalancedAc.is_null() && IsPrint(Statistics2)) {
130 int oldRank = SetProcRankVerbose(rebalancedAc->getRowMap()->getComm()->getRank());
131
132 RCP<ParameterList> params = rcp(new ParameterList());
133 params->set("printLoadBalancingInfo", true);
134 params->set("printCommInfo", true);
135 GetOStream(Statistics2) << PerfUtils::PrintMatrixInfo(*rebalancedAc, coarseMatrixName + " (rebalanced)", params);
136
137 SetProcRankVerbose(oldRank);
138 }
139
140 } else {
141 // Ac already built by the load balancing process and no load balancing needed
142 GetOStream(Runtime1) << "No rebalancing" << std::endl;
143 Set(coarseLevel, matrixName, originalAc);
144 }
145
146 if (rebalanceFacts_.begin() != rebalanceFacts_.end()) {
147 SubFactoryMonitor m2(*this, "Rebalance additional data", coarseLevel);
148
149 // call Build of all user-given transfer factories
150 for (std::vector<RCP<const FactoryBase> >::const_iterator it = rebalanceFacts_.begin(); it != rebalanceFacts_.end(); ++it) {
151 GetOStream(Runtime0) << "RebalanceAc: call rebalance factory " << (*it).get() << ": " << (*it)->description() << std::endl;
152 (*it)->CallBuild(coarseLevel);
153 }
154 }
155} // Build()
156
157template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
159 /*TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<const TwoLevelFactoryBase>(factory) == Teuchos::null, Exceptions::BadCast,
160 "MueLu::RAPFactory::AddTransferFactory: Transfer factory is not derived from TwoLevelFactoryBase. "
161 "This is very strange. (Note: you can remove this exception if there's a good reason for)");
162 TEUCHOS_TEST_FOR_EXCEPTION(hasDeclaredInput_, Exceptions::RuntimeError, "MueLu::RAPFactory::AddTransferFactory: Factory is being added after we have already declared input");*/
163 rebalanceFacts_.push_back(factory);
164} // AddRebalanceFactory()
165
166} // namespace MueLu
167
168#endif // MUELU_REBALANCEACFACTORY_DEF_HPP
#define SET_VALID_ENTRY(name)
Timer to be used in factories. Similar to Monitor but with additional timers.
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 DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
int GetLevelID() const
Return level number.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
void AddRebalanceFactory(const RCP< const FactoryBase > &factory)
Add rebalancing factory in the end of list of rebalancing factories in RebalanceAcFactory.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
Namespace for MueLu classes and methods.
@ Statistics2
Print even more statistics.
@ Statistics1
Print more statistics.
@ Runtime0
One-liner description of what is happening.
@ Runtime1
Description of what is happening (more verbose)