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#include "MueLu_Behavior.hpp"
28
29namespace MueLu {
30
31template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
34
35template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
37
38template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
40 RCP<ParameterList> validParamList = rcp(new ParameterList());
41
42#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
43 SET_VALID_ENTRY("transpose: use implicit");
44 SET_VALID_ENTRY("rap: triple product");
45 SET_VALID_ENTRY("rap: fix zero diagonals");
46 SET_VALID_ENTRY("rap: fix zero diagonals threshold");
47 SET_VALID_ENTRY("rap: fix zero diagonals replacement");
48 SET_VALID_ENTRY("rap: relative diagonal floor");
49#undef SET_VALID_ENTRY
50 validParamList->set<RCP<const FactoryBase> >("A", null, "Generating factory of the matrix A used during the prolongator smoothing process");
51 validParamList->set<RCP<const FactoryBase> >("P", null, "Prolongator factory");
52 validParamList->set<RCP<const FactoryBase> >("R", null, "Restrictor factory");
53
54 validParamList->set<bool>("CheckMainDiagonal", false, "Check main diagonal for zeros");
55 validParamList->set<bool>("RepairMainDiagonal", false, "Repair zeros on main diagonal");
56
57 // Make sure we don't recursively validate options for the matrixmatrix kernels
58 ParameterList norecurse;
59 norecurse.disableRecursiveValidation();
60 validParamList->set<ParameterList>("matrixmatrix: kernel params", norecurse, "MatrixMatrix kernel parameters");
61
62 return validParamList;
63}
64
65template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
67 const Teuchos::ParameterList& pL = GetParameterList();
68 if (!pL.get<bool>("transpose: use implicit"))
69 Input(coarseLevel, "R");
70
71 Input(fineLevel, "A");
72 Input(coarseLevel, "P");
73
74 // call DeclareInput of all user-given transfer factories
75 for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it)
76 (*it)->CallDeclareInput(coarseLevel);
77
78 hasDeclaredInput_ = true;
79}
80
81template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
83 RCP<Matrix> Ac;
84
85 {
86 FactoryMonitor m(*this, "Computing Ac", coarseLevel);
87
88 TEUCHOS_TEST_FOR_EXCEPTION(hasDeclaredInput_ == false, Exceptions::RuntimeError,
89 "MueLu::RAPFactory::Build(): CallDeclareInput has not been called before Build!");
90
91 RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel, "A");
92 RCP<Matrix> P = Get<RCP<Matrix> >(coarseLevel, "P"), AP, R;
93 // We don't have a valid P (e.g., # global aggregates = 0) so we bail.
94 // This level will ultimately be removed in MueLu_Hierarchy_defs.h via a resize()
95 if (P.is_null()) {
96 Ac = Teuchos::null;
97 Set(coarseLevel, "A", Ac);
98 return;
99 }
100
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 if (!useImplicit)
120 R = Get<RCP<Matrix> >(coarseLevel, "R");
121 Utilities::TripleMatrixProduct(R, A, P, Ac, pL, *this, APparams, RAPparams, &coarseLevel);
122
123 if (!Ac.is_null()) {
124 std::ostringstream oss;
125 oss << "A_" << coarseLevel.GetLevelID();
126 Ac->setObjectLabel(oss.str());
127 }
128 Set(coarseLevel, "A", Ac);
129 if (!isGPU) {
130 if (!pL.get<bool>("rap: triple product")) {
131 TEUCHOS_TEST_FOR_EXCEPTION(!APparams->isParameter("graph"), std::runtime_error, "\"AP reuse data\" does not contain the expected reuse data.");
132 Set(coarseLevel, "AP reuse data", APparams);
133 }
134 {
135 TEUCHOS_TEST_FOR_EXCEPTION(!RAPparams->isParameter("graph"), std::runtime_error, "\"RAP reuse data\" does not contain the expected reuse data.");
136 Set(coarseLevel, "RAP reuse data", RAPparams);
137 }
138 }
139 }
140
141 if (Behavior::debug())
142 MatrixUtils::checkLocalRowMapMatchesColMap(*Ac);
143
144 if (transferFacts_.begin() != transferFacts_.end()) {
145 SubFactoryMonitor m(*this, "Projections", coarseLevel);
146
147 // call Build of all user-given transfer factories
148 for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it) {
149 RCP<const FactoryBase> fac = *it;
150 GetOStream(Runtime0) << "RAPFactory: call transfer factory: " << fac->description() << std::endl;
151 fac->CallBuild(coarseLevel);
152 // Coordinates transfer is marginally different from all other operations
153 // because it is *optional*, and not required. For instance, we may need
154 // coordinates only on level 4 if we start repartitioning from that level,
155 // but we don't need them on level 1,2,3. As our current Hierarchy setup
156 // assumes propagation of dependencies only through three levels, this
157 // means that we need to rely on other methods to propagate optional data.
158 //
159 // The method currently used is through RAP transfer factories, which are
160 // simply factories which are called at the end of RAP with a single goal:
161 // transfer some fine data to coarser level. Because these factories are
162 // kind of outside of the mainline factories, they behave different. In
163 // particular, we call their Build method explicitly, rather than through
164 // Get calls. This difference is significant, as the Get call is smart
165 // enough to know when to release all factory dependencies, and Build is
166 // dumb. This led to the following CoordinatesTransferFactory sequence:
167 // 1. Request level 0
168 // 2. Request level 1
169 // 3. Request level 0
170 // 4. Release level 0
171 // 5. Release level 1
172 //
173 // The problem is missing "6. Release level 0". Because it was missing,
174 // we had outstanding request on "Coordinates", "Aggregates" and
175 // "CoarseMap" on level 0.
176 //
177 // This was fixed by explicitly calling Release on transfer factories in
178 // RAPFactory. I am still unsure how exactly it works, but now we have
179 // clear data requests for all levels.
180 coarseLevel.Release(*fac);
181 }
182 }
183}
184
185template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
187 // check if it's a TwoLevelFactoryBase based transfer factory
188 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<const TwoLevelFactoryBase>(factory) == Teuchos::null, Exceptions::BadCast,
189 "MueLu::RAPFactory::AddTransferFactory: Transfer factory is not derived from TwoLevelFactoryBase. "
190 "This is very strange. (Note: you can remove this exception if there's a good reason for)");
191 TEUCHOS_TEST_FOR_EXCEPTION(hasDeclaredInput_, Exceptions::RuntimeError, "MueLu::RAPFactory::AddTransferFactory: Factory is being added after we have already declared input");
192 transferFacts_.push_back(factory);
193}
194
195} // namespace MueLu
196
197#define MUELU_RAPFACTORY_SHORT
198#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.