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.
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.
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, LocalOrdinal, GlobalOrdinal, Node > > &R, const Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &A, const Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &P, Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &Ac, const Teuchos::ParameterList &pL, const MueLu::BaseClass &verbObj, Teuchos::RCP< Teuchos::ParameterList > &APparams, Teuchos::RCP< Teuchos::ParameterList > &RAPparams, Level *coarseLevel=nullptr)
Namespace for MueLu classes and methods.
@ Statistics1
Print more statistics.
@ Runtime0
One-liner description of what is happening.