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 Teuchos::ParameterList& pL = GetParameterList();
101 const bool useImplicit = pL.get<bool>("transpose: use implicit");
102 bool isGPU = Node::is_gpu;
103
104 Teuchos::RCP<Teuchos::ParameterList> APparams;
105 Teuchos::RCP<Teuchos::ParameterList> RAPparams;
106 if (coarseLevel.IsAvailable("AP reuse data", this)) {
107 GetOStream(static_cast<MsgType>(Runtime0 | Test)) << "Reusing previous AP data" << std::endl;
108 APparams = coarseLevel.Get<RCP<ParameterList> >("AP reuse data", this);
109 } else {
110 APparams = Teuchos::rcp(new Teuchos::ParameterList());
111 }
112 if (coarseLevel.IsAvailable("RAP reuse data", this)) {
113 GetOStream(static_cast<MsgType>(Runtime0 | Test)) << "Reusing previous RAP data" << std::endl;
114 RAPparams = coarseLevel.Get<RCP<ParameterList> >("RAP reuse data", this);
115 } else {
116 RAPparams = Teuchos::rcp(new Teuchos::ParameterList());
117 }
118 if (!useImplicit)
119 R = Get<RCP<Matrix> >(coarseLevel, "R");
120 Utilities::TripleMatrixProduct(R, A, P, Ac, pL, *this, APparams, RAPparams, &coarseLevel);
121
122 if (!Ac.is_null()) {
123 std::ostringstream oss;
124 oss << "A_" << coarseLevel.GetLevelID();
125 Ac->setObjectLabel(oss.str());
126 }
127 Set(coarseLevel, "A", Ac);
128 if (!isGPU) {
129 if (!pL.get<bool>("rap: triple product")) {
130 TEUCHOS_TEST_FOR_EXCEPTION(!APparams->isParameter("graph"), std::runtime_error, "\"AP reuse data\" does not contain the expected reuse data.");
131 Set(coarseLevel, "AP reuse data", APparams);
132 }
133 {
134 TEUCHOS_TEST_FOR_EXCEPTION(!RAPparams->isParameter("graph"), std::runtime_error, "\"RAP reuse data\" does not contain the expected reuse data.");
135 Set(coarseLevel, "RAP reuse data", RAPparams);
136 }
137 }
138 }
139
140 if (Behavior::debug())
141 MatrixUtils::checkLocalRowMapMatchesColMap(*Ac);
142
143 if (transferFacts_.begin() != transferFacts_.end()) {
144 SubFactoryMonitor m(*this, "Projections", coarseLevel);
145
146 // call Build of all user-given transfer factories
147 for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it) {
148 RCP<const FactoryBase> fac = *it;
149 GetOStream(Runtime0) << "RAPFactory: call transfer factory: " << fac->description() << std::endl;
150 fac->CallBuild(coarseLevel);
151 // Coordinates transfer is marginally different from all other operations
152 // because it is *optional*, and not required. For instance, we may need
153 // coordinates only on level 4 if we start repartitioning from that level,
154 // but we don't need them on level 1,2,3. As our current Hierarchy setup
155 // assumes propagation of dependencies only through three levels, this
156 // means that we need to rely on other methods to propagate optional data.
157 //
158 // The method currently used is through RAP transfer factories, which are
159 // simply factories which are called at the end of RAP with a single goal:
160 // transfer some fine data to coarser level. Because these factories are
161 // kind of outside of the mainline factories, they behave different. In
162 // particular, we call their Build method explicitly, rather than through
163 // Get calls. This difference is significant, as the Get call is smart
164 // enough to know when to release all factory dependencies, and Build is
165 // dumb. This led to the following CoordinatesTransferFactory sequence:
166 // 1. Request level 0
167 // 2. Request level 1
168 // 3. Request level 0
169 // 4. Release level 0
170 // 5. Release level 1
171 //
172 // The problem is missing "6. Release level 0". Because it was missing,
173 // we had outstanding request on "Coordinates", "Aggregates" and
174 // "CoarseMap" on level 0.
175 //
176 // This was fixed by explicitly calling Release on transfer factories in
177 // RAPFactory. I am still unsure how exactly it works, but now we have
178 // clear data requests for all levels.
179 coarseLevel.Release(*fac);
180 }
181 }
182}
183
184template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
186 // check if it's a TwoLevelFactoryBase based transfer factory
187 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<const TwoLevelFactoryBase>(factory) == Teuchos::null, Exceptions::BadCast,
188 "MueLu::RAPFactory::AddTransferFactory: Transfer factory is not derived from TwoLevelFactoryBase. "
189 "This is very strange. (Note: you can remove this exception if there's a good reason for)");
190 TEUCHOS_TEST_FOR_EXCEPTION(hasDeclaredInput_, Exceptions::RuntimeError, "MueLu::RAPFactory::AddTransferFactory: Factory is being added after we have already declared input");
191 transferFacts_.push_back(factory);
192}
193
194} // namespace MueLu
195
196#define MUELU_RAPFACTORY_SHORT
197#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.
@ Runtime0
One-liner description of what is happening.