MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
27 namespace MueLu {
28 
29 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
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);
41  PtAP->getLocalDiagCopy(*diag);
42  MagnitudeType norm = diag->norm1();
44  return norm;
45 }
46 
47 template <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 
73 template <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 
103 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
105  BuildP(fineLevel, coarseLevel);
106 }
107 
108 template <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
void Keep(const std::string &ename, const FactoryBase *factory)
Request to keep variable &#39;ename&#39; generated by &#39;factory&#39; after the setup phase.
#define SET_VALID_ENTRY(name)
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level-&gt;Get&lt; RCP&lt;Matrix&gt; &gt;(&quot;A&quot;, factory) if factory == NULL =&gt; use default factory.
void Build(Level &fineLevel, Level &coarseLevel) const
Build method.
void setValidator(RCP< const ParameterEntryValidator > const &validator)
T & get(const std::string &name, T def_value)
Implements conjugate gradient algorithm for energy-minimization.
static T squareroot(T x)
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
Timer to be used in factories. Similar to Monitor but with additional timers.
One-liner description of what is happening.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
RCP< const CrsGraph > GetPattern() const
Print even more statistics.
RequestMode GetRequestMode() const
Implements conjugate gradient algorithm for energy-minimization.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
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)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
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)
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
static RCP< Vector > Build(const Teuchos::RCP< const Map > &map, bool zeroOut=true)
static void Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Matrix &C, bool call_FillComplete_on_result=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > &params=null)
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
Implements steepest descent algorithm for energy-minimization.
Description of what is happening (more verbose)
ParameterEntry & getEntry(const std::string &name)
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need&#39;s value has been saved.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.