MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_EminPFactory_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_EMINPFACTORY_DEF_HPP
11#define MUELU_EMINPFACTORY_DEF_HPP
12
13#include <Xpetra_Matrix.hpp>
14#include <Xpetra_StridedMapFactory.hpp>
15
17
18#include "MueLu_CGSolver.hpp"
19#include "MueLu_Constraint.hpp"
20#include "MueLu_GMRESSolver.hpp"
21#include "MueLu_MasterList.hpp"
22#include "MueLu_Monitor.hpp"
23#include "MueLu_PerfUtils.hpp"
24#include "MueLu_SolverBase.hpp"
25#include "MueLu_SteepestDescentSolver.hpp"
26
27namespace MueLu {
28
29template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
30typename Teuchos::ScalarTraits<Scalar>::magnitudeType
32 ComputeProlongatorEnergyNorm(RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& A,
33 RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& P,
34 Teuchos::FancyOStream& out) {
35 using MagnitudeType = typename Teuchos::ScalarTraits<Scalar>::magnitudeType;
36 RCP<Matrix> AP;
37 AP = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*A, false, *P, false, AP, out, true, true);
38 RCP<Matrix> PtAP;
39 PtAP = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P, true, *AP, false, PtAP, out, true, true);
40 RCP<Vector> diag = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(PtAP->getRowMap());
41 PtAP->getLocalDiagCopy(*diag);
42 MagnitudeType norm = diag->norm1();
43 norm = Teuchos::ScalarTraits<MagnitudeType>::squareroot(norm);
44 return norm;
45}
46
47template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
49 RCP<ParameterList> validParamList = rcp(new ParameterList());
50
51#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
52 SET_VALID_ENTRY("emin: num iterations");
53 SET_VALID_ENTRY("emin: num reuse iterations");
54 SET_VALID_ENTRY("emin: iterative method");
55 {
56 validParamList->getEntry("emin: iterative method").setValidator(rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("cg", "sd", "gmres"))));
57 }
58#undef SET_VALID_ENTRY
59
60 validParamList->set<RCP<const FactoryBase>>("A", Teuchos::null, "Generating factory for the matrix A used during internal iterations");
61 validParamList->set<RCP<const FactoryBase>>("P", Teuchos::null, "Generating factory for the initial guess");
62 validParamList->set<RCP<const FactoryBase>>("Constraint", Teuchos::null, "Generating factory for constraints");
63
64 validParamList->set<RCP<Matrix>>("P0", Teuchos::null, "Initial guess at P");
65 validParamList->set<bool>("Keep P0", false, "Keep an initial P0 (for reuse)");
66
67 validParamList->set<RCP<Constraint>>("Constraint0", Teuchos::null, "Initial Constraint");
68 validParamList->set<bool>("Keep Constraint0", false, "Keep an initial Constraint (for reuse)");
69
70 return validParamList;
71}
72
73template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
75 Input(fineLevel, "A");
76
77 static bool isAvailableP0 = false;
78 static bool isAvailableConstraint0 = false;
79
80 // Here is a tricky little piece of code
81 // We don't want to request (aka call Input) when we reuse and P0 is available
82 // However, we cannot run something simple like this:
83 // if (!coarseLevel.IsAvailable("P0", this))
84 // Input(coarseLevel, "P");
85 // The reason is that it works fine during the request stage, but fails
86 // in the release stage as we _construct_ P0 during Build process. Therefore,
87 // we need to understand whether we are in Request or Release mode
88 // NOTE: This is a very unique situation, please try not to propagate the
89 // mode check any further
90
91 if (coarseLevel.GetRequestMode() == Level::REQUEST) {
92 isAvailableP0 = coarseLevel.IsAvailable("P0", this);
93 isAvailableConstraint0 = coarseLevel.IsAvailable("Constraint0", this);
94 }
95
96 if (isAvailableP0 == false)
97 Input(coarseLevel, "P");
98
99 if (isAvailableConstraint0 == false)
100 Input(coarseLevel, "Constraint");
101}
102
103template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
105 BuildP(fineLevel, coarseLevel);
106}
107
108template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
110 FactoryMonitor m(*this, "Prolongator minimization", coarseLevel);
111
112 const ParameterList& pL = GetParameterList();
113
114 // Get the matrix
115 RCP<Matrix> A = Get<RCP<Matrix>>(fineLevel, "A");
116
117 if (restrictionMode_) {
118 SubFactoryMonitor m2(*this, "Transpose A", coarseLevel);
119
120 A = Utilities::Transpose(*A, true);
121 }
122
123 // Get/make initial guess
124 RCP<Matrix> P0;
125 int numIts;
126 if (coarseLevel.IsAvailable("P0", this)) {
127 // Reuse data
128 P0 = coarseLevel.Get<RCP<Matrix>>("P0", this);
129 numIts = pL.get<int>("emin: num reuse iterations");
130 GetOStream(Runtime0) << "Reusing P0" << std::endl;
131
132 } else {
133 // Construct data
134 P0 = Get<RCP<Matrix>>(coarseLevel, "P");
135 numIts = pL.get<int>("emin: num iterations");
136 }
137 // NOTE: the main assumption here that P0 satisfies both constraints:
138 // - nonzero pattern
139 // - nullspace preservation
140
141 // Get/make constraint operator
142 RCP<Constraint> X;
143 if (coarseLevel.IsAvailable("Constraint0", this)) {
144 // Reuse data
145 X = coarseLevel.Get<RCP<Constraint>>("Constraint0", this);
146 GetOStream(Runtime0) << "Reusing Constraint0" << std::endl;
147
148 } else {
149 // Construct data
150 X = Get<RCP<Constraint>>(coarseLevel, "Constraint");
151 }
152 GetOStream(Runtime0) << "Number of emin iterations = " << numIts << std::endl;
153
154 std::string solverType = pL.get<std::string>("emin: iterative method");
155 RCP<SolverBase> solver;
156 if (solverType == "cg")
157 solver = rcp(new CGSolver(numIts));
158 else if (solverType == "sd")
159 solver = rcp(new SteepestDescentSolver(numIts));
160 else if (solverType == "gmres")
161 solver = rcp(new GMRESSolver(numIts));
162
163 RCP<Matrix> P;
164 solver->Iterate(*A, *X, *P0, P);
165
166 // NOTE: EXPERIMENTAL and FRAGILE
167 if (!P->IsView("stridedMaps")) {
168 if (A->IsView("stridedMaps") == true) {
169 GetOStream(Runtime1) << "Using A to fillComplete P" << std::endl;
170
171 // FIXME: X->GetPattern() actually returns a CrsGraph.
172 // CrsGraph has no knowledge of Xpetra's sup/Matrix views. As such,
173 // it has no idea about strided maps. We create one, which is
174 // most likely incorrect for many use cases.
175 std::vector<size_t> stridingInfo(1, 1);
176 RCP<const StridedMap> dMap = StridedMapFactory::Build(X->GetPattern()->getDomainMap(), stridingInfo);
177
178 P->CreateView("stridedMaps", A->getRowMap("stridedMaps"), dMap);
179
180 } else {
181 P->CreateView("stridedMaps", P->getRangeMap(), P->getDomainMap());
182 }
183 }
184
185 // Level Set
186 if (!restrictionMode_) {
187 // The factory is in prolongation mode
188 Set(coarseLevel, "P", P);
189
190 if (pL.get<bool>("Keep P0")) {
191 // NOTE: we must do Keep _before_ set as the Needs class only sets if
192 // a) data has been requested (which is not the case here), or
193 // b) data has some keep flag
194 coarseLevel.Keep("P0", this);
195 Set(coarseLevel, "P0", P);
196 }
197 if (pL.get<bool>("Keep Constraint0")) {
198 // NOTE: we must do Keep _before_ set as the Needs class only sets if
199 // a) data has been requested (which is not the case here), or
200 // b) data has some keep flag
201 coarseLevel.Keep("Constraint0", this);
202 Set(coarseLevel, "Constraint0", X);
203 }
204
205 if (IsPrint(Statistics2)) {
206 RCP<ParameterList> params = rcp(new ParameterList());
207 params->set("printLoadBalancingInfo", true);
208 params->set("printCommInfo", true);
209 GetOStream(Statistics2) << PerfUtils::PrintMatrixInfo(*P, "P", params);
210 }
211
212 } else {
213 // The factory is in restriction mode
214 RCP<Matrix> R;
215 {
216 SubFactoryMonitor m2(*this, "Transpose P", coarseLevel);
217
218 R = Utilities::Transpose(*P, true);
219 }
220
221 Set(coarseLevel, "R", R);
222
223 if (IsPrint(Statistics2)) {
224 RCP<ParameterList> params = rcp(new ParameterList());
225 params->set("printLoadBalancingInfo", true);
226 params->set("printCommInfo", true);
227 GetOStream(Statistics2) << PerfUtils::PrintMatrixInfo(*R, "R", params);
228 }
229 }
230}
231
232} // namespace MueLu
233
234#endif // MUELU_EMINPFACTORY_DEF_HPP
#define SET_VALID_ENTRY(name)
Implements conjugate gradient algorithm for energy-minimization.
void Build(Level &fineLevel, Level &coarseLevel) const
Build method.
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
static Teuchos::ScalarTraits< Scalar >::magnitudeType ComputeProlongatorEnergyNorm(RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &A, RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &P, Teuchos::FancyOStream &out)
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 Monitor but with additional timers.
Implements conjugate gradient algorithm for energy-minimization.
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.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
RequestMode GetRequestMode() const
void Keep(const std::string &ename, const FactoryBase *factory)
Request to keep variable 'ename' generated by 'factory' after the setup phase.
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
Implements steepest descent algorithm for energy-minimization.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Transpose(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, bool optimizeTranspose=false, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Namespace for MueLu classes and methods.
@ Statistics2
Print even more statistics.
@ Runtime0
One-liner description of what is happening.
@ Runtime1
Description of what is happening (more verbose)