MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_RAPFactory_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_RAPFACTORY_DEF_HPP
11#define MUELU_RAPFACTORY_DEF_HPP
12
13#include <sstream>
14
15#include <Xpetra_Matrix.hpp>
16#include <Xpetra_MatrixUtils.hpp>
17#include <stdexcept>
18
20
21#include "MueLu_Utilities.hpp"
22#include "MueLu_MasterList.hpp"
23#include "MueLu_Monitor.hpp"
24#include "MueLu_PerfUtils.hpp"
25#include "MueLu_Behavior.hpp"
26#include "Teuchos_TestForException.hpp"
27
28namespace MueLu {
29
30template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
33
34template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
36
37template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
39 RCP<ParameterList> validParamList = rcp(new ParameterList());
40
41#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
42 SET_VALID_ENTRY("transpose: use implicit");
43 SET_VALID_ENTRY("rap: triple product");
44 SET_VALID_ENTRY("rap: fix zero diagonals");
45 SET_VALID_ENTRY("rap: fix zero diagonals threshold");
46 SET_VALID_ENTRY("rap: fix zero diagonals replacement");
47 SET_VALID_ENTRY("rap: relative diagonal floor");
48#undef SET_VALID_ENTRY
49 validParamList->set<RCP<const FactoryBase> >("A", null, "Generating factory of the matrix A used during the prolongator smoothing process");
50 validParamList->set<RCP<const FactoryBase> >("P", null, "Prolongator factory");
51 validParamList->set<RCP<const FactoryBase> >("R", null, "Restrictor factory");
52
53 validParamList->set<bool>("CheckMainDiagonal", false, "Check main diagonal for zeros");
54 validParamList->set<bool>("RepairMainDiagonal", false, "Repair zeros on main diagonal");
55
56 // Make sure we don't recursively validate options for the matrixmatrix kernels
57 ParameterList norecurse;
58 norecurse.disableRecursiveValidation();
59 validParamList->set<ParameterList>("matrixmatrix: kernel params", norecurse, "MatrixMatrix kernel parameters");
60
61 return validParamList;
62}
63
64template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
66 const Teuchos::ParameterList& pL = GetParameterList();
67 if (!pL.get<bool>("transpose: use implicit"))
68 Input(coarseLevel, "R");
69
70 Input(fineLevel, "A");
71 Input(coarseLevel, "P");
72
73 // call DeclareInput of all user-given transfer factories
74 for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it)
75 (*it)->CallDeclareInput(coarseLevel);
76
77 hasDeclaredInput_ = true;
78}
79
80template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
82 RCP<Matrix> Ac;
83
84 {
85 FactoryMonitor m(*this, "Computing Ac", coarseLevel);
86
87 TEUCHOS_TEST_FOR_EXCEPTION(hasDeclaredInput_ == false, Exceptions::RuntimeError,
88 "MueLu::RAPFactory::Build(): CallDeclareInput has not been called before Build!");
89
90 RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel, "A");
91 RCP<Matrix> P = Get<RCP<Matrix> >(coarseLevel, "P"), AP, R;
92 // We don't have a valid P (e.g., # global aggregates = 0) so we bail.
93 // This level will ultimately be removed in MueLu_Hierarchy_defs.h via a resize()
94 if (P.is_null()) {
95 Ac = Teuchos::null;
96 Set(coarseLevel, "A", Ac);
97 return;
98 }
99
100 const bool computeGlobalConstantsForAc = IsPrint(Statistics1);
101 const Teuchos::ParameterList& pL = GetParameterList();
102 const bool useImplicit = pL.get<bool>("transpose: use implicit");
103 bool isGPU = Node::is_gpu;
104
105 Teuchos::RCP<Teuchos::ParameterList> APparams;
106 Teuchos::RCP<Teuchos::ParameterList> RAPparams;
107 if (coarseLevel.IsAvailable("AP reuse data", this)) {
108 GetOStream(static_cast<MsgType>(Runtime0 | Test)) << "Reusing previous AP data" << std::endl;
109 APparams = coarseLevel.Get<RCP<ParameterList> >("AP reuse data", this);
110 } else {
111 APparams = Teuchos::rcp(new Teuchos::ParameterList());
112 }
113 if (coarseLevel.IsAvailable("RAP reuse data", this)) {
114 GetOStream(static_cast<MsgType>(Runtime0 | Test)) << "Reusing previous RAP data" << std::endl;
115 RAPparams = coarseLevel.Get<RCP<ParameterList> >("RAP reuse data", this);
116 } else {
117 RAPparams = Teuchos::rcp(new Teuchos::ParameterList());
118 }
119 RAPparams->set("compute global constants", computeGlobalConstantsForAc);
120 if (!useImplicit)
121 R = Get<RCP<Matrix> >(coarseLevel, "R");
122 Utilities::TripleMatrixProduct(R, A, P, Ac, pL, *this, APparams, RAPparams, &coarseLevel);
123
124 if (!Ac.is_null()) {
125 std::ostringstream oss;
126 oss << "A_" << coarseLevel.GetLevelID();
127 Ac->setObjectLabel(oss.str());
128 }
129 Set(coarseLevel, "A", Ac);
130 if (!isGPU) {
131 if (!pL.get<bool>("rap: triple product")) {
132 TEUCHOS_TEST_FOR_EXCEPTION(!APparams->isParameter("graph"), std::runtime_error, "\"AP reuse data\" does not contain the expected reuse data.");
133 Set(coarseLevel, "AP reuse data", APparams);
134 }
135 {
136 TEUCHOS_TEST_FOR_EXCEPTION(!RAPparams->isParameter("graph"), std::runtime_error, "\"RAP reuse data\" does not contain the expected reuse data.");
137 Set(coarseLevel, "RAP reuse data", RAPparams);
138 }
139 }
140 }
141
142 if (Behavior::debug())
143 MatrixUtils::checkLocalRowMapMatchesColMap(*Ac);
144
145 if (transferFacts_.begin() != transferFacts_.end()) {
146 SubFactoryMonitor m(*this, "Projections", coarseLevel);
147
148 // call Build of all user-given transfer factories
149 for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it) {
150 RCP<const FactoryBase> fac = *it;
151 GetOStream(Runtime0) << "RAPFactory: call transfer factory: " << fac->description() << std::endl;
152 fac->CallBuild(coarseLevel);
153 // Coordinates transfer is marginally different from all other operations
154 // because it is *optional*, and not required. For instance, we may need
155 // coordinates only on level 4 if we start repartitioning from that level,
156 // but we don't need them on level 1,2,3. As our current Hierarchy setup
157 // assumes propagation of dependencies only through three levels, this
158 // means that we need to rely on other methods to propagate optional data.
159 //
160 // The method currently used is through RAP transfer factories, which are
161 // simply factories which are called at the end of RAP with a single goal:
162 // transfer some fine data to coarser level. Because these factories are
163 // kind of outside of the mainline factories, they behave different. In
164 // particular, we call their Build method explicitly, rather than through
165 // Get calls. This difference is significant, as the Get call is smart
166 // enough to know when to release all factory dependencies, and Build is
167 // dumb. This led to the following CoordinatesTransferFactory sequence:
168 // 1. Request level 0
169 // 2. Request level 1
170 // 3. Request level 0
171 // 4. Release level 0
172 // 5. Release level 1
173 //
174 // The problem is missing "6. Release level 0". Because it was missing,
175 // we had outstanding request on "Coordinates", "Aggregates" and
176 // "CoarseMap" on level 0.
177 //
178 // This was fixed by explicitly calling Release on transfer factories in
179 // RAPFactory. I am still unsure how exactly it works, but now we have
180 // clear data requests for all levels.
181 coarseLevel.Release(*fac);
182 }
183 }
184}
185
186template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
188 // check if it's a TwoLevelFactoryBase based transfer factory
189 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<const TwoLevelFactoryBase>(factory) == Teuchos::null, Exceptions::BadCast,
190 "MueLu::RAPFactory::AddTransferFactory: Transfer factory is not derived from TwoLevelFactoryBase. "
191 "This is very strange. (Note: you can remove this exception if there's a good reason for)");
192 TEUCHOS_TEST_FOR_EXCEPTION(hasDeclaredInput_, Exceptions::RuntimeError, "MueLu::RAPFactory::AddTransferFactory: Factory is being added after we have already declared input");
193 transferFacts_.push_back(factory);
194}
195
196} // namespace MueLu
197
198#define MUELU_RAPFACTORY_SHORT
199#endif // MUELU_RAPFACTORY_DEF_HPP
#define SET_VALID_ENTRY(name)
static bool debug()
Whether MueLu is in debug mode.
Exception indicating invalid cast attempted.
Exception throws to report errors in the internal logical of the program.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
void Set(Level &level, const std::string &varName, const T &data) const
Timer to be used in factories. Similar to Monitor but with additional timers.
Class that holds all level-specific information.
void Release(const FactoryBase &factory)
Decrement the storage counter for all the inputs of a factory.
virtual const Teuchos::ParameterList & GetParameterList() const
std::vector< RCP< const FactoryBase > > transferFacts_
list of user-defined transfer Factories
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
virtual ~RAPFactory()
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
void AddTransferFactory(const RCP< const FactoryBase > &factory)
Add transfer factory in the end of list of transfer factories in RepartitionAcFactory.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
static void TripleMatrixProduct(const Teuchos::RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > &R, const Teuchos::RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > &A, const Teuchos::RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > &P, Teuchos::RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > &Ac, const Teuchos::ParameterList &pL, const MueLu::BaseClass &verbObj, Teuchos::RCP< Teuchos::ParameterList > &APparams, Teuchos::RCP< Teuchos::ParameterList > &RAPparams, Level *coarseLevel=nullptr)
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
bool IsPrint(MsgType type, int thisProcRankOnly=-1) const
Find out whether we need to print out information for a specific message type.
Namespace for MueLu classes and methods.
@ Statistics1
Print more statistics.
@ Runtime0
One-liner description of what is happening.