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