MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_TrilinosSmoother_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_TRILINOSSMOOTHER_DEF_HPP
11 #define MUELU_TRILINOSSMOOTHER_DEF_HPP
12 
13 #include <Xpetra_Map.hpp>
14 #include <Xpetra_Matrix.hpp>
15 
17 
18 #include "MueLu_Level.hpp"
19 #include "MueLu_IfpackSmoother.hpp"
20 #include "MueLu_Ifpack2Smoother.hpp"
21 #include "MueLu_BelosSmoother.hpp"
22 #include "MueLu_StratimikosSmoother.hpp"
23 #include "MueLu_Exceptions.hpp"
24 
25 namespace MueLu {
26 
27 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
29  : type_(type)
30  , overlap_(overlap) {
31  // The original idea behind all smoothers was to use prototype pattern. However, it does not fully work of the dependencies
32  // calculation. Particularly, we need to propagate DeclareInput to proper prototypes. Therefore, both TrilinosSmoother and
33  // DirectSolver do not follow the pattern exactly.
34  // The difference is that in order to propagate the calculation of dependencies, we need to call a DeclareInput on a
35  // constructed object (or objects, as we have two different code branches for Epetra and Tpetra). The only place where we
36  // could construct these objects is the constructor. Thus, we need to store RCPs, and both TrilinosSmoother and DirectSolver
37  // obtain a state: they contain RCP to smoother prototypes.
38  sEpetra_ = Teuchos::null;
39  sTpetra_ = Teuchos::null;
40  sBelos_ = Teuchos::null;
41  sStratimikos_ = Teuchos::null;
42 
43  TEUCHOS_TEST_FOR_EXCEPTION(overlap_ < 0, Exceptions::RuntimeError, "Overlap parameter is negative (" << overlap << ")");
44 
45  // paramList contains only parameters which are understood by Ifpack/Ifpack2
46  ParameterList paramList = paramListIn;
47 
48  // We want TrilinosSmoother to be able to work with both Epetra and Tpetra objects, therefore we try to construct both
49  // Ifpack and Ifpack2 smoother prototypes. The construction really depends on configuration options.
51 #if defined(HAVE_MUELU_IFPACK2)
52  try {
53  sTpetra_ = rcp(new Ifpack2Smoother(type_, paramList, overlap_));
54  if (sTpetra_.is_null())
55  errorTpetra_ = "Unable to construct Ifpack2 smoother";
56  else if (!sTpetra_->constructionSuccessful()) {
57  errorTpetra_ = sTpetra_->constructionErrorMsg();
58  sTpetra_ = Teuchos::null;
59  }
60  } catch (Exceptions::RuntimeError& e) {
61  errorTpetra_ = e.what();
62  } catch (Exceptions::BadCast& e) {
63  errorTpetra_ = e.what();
65  errorTpetra_ = e.what();
66  }
67  triedTpetra_ = true;
68 #endif
69 #if defined(HAVE_MUELU_EPETRA) && defined(HAVE_MUELU_IFPACK)
70  try {
71  // GetIfpackSmoother masks the template argument matching, and simply throws if template arguments are incompatible with Epetra
73  if (sEpetra_.is_null())
74  errorEpetra_ = "Unable to construct Ifpack smoother";
75  else if (!sEpetra_->constructionSuccessful()) {
76  errorEpetra_ = sEpetra_->constructionErrorMsg();
77  sEpetra_ = Teuchos::null;
78  }
79  } catch (Exceptions::RuntimeError& e) {
80  // IfpackSmoother throws if Scalar != double, LocalOrdinal != int, GlobalOrdinal != int
81  errorEpetra_ = e.what();
82  }
83  triedEpetra_ = true;
84 #endif
85 #if defined(HAVE_MUELU_BELOS)
86  try {
87  sBelos_ = rcp(new BelosSmoother(type_, paramList));
88  if (sBelos_.is_null())
89  errorBelos_ = "Unable to construct Belos smoother";
90  else if (!sBelos_->constructionSuccessful()) {
91  errorBelos_ = sBelos_->constructionErrorMsg();
92  sBelos_ = Teuchos::null;
93  }
94  } catch (Exceptions::RuntimeError& e) {
95  errorBelos_ = e.what();
96  } catch (Exceptions::BadCast& e) {
97  errorBelos_ = e.what();
98  }
99  triedBelos_ = true;
100 #endif
101 #if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
102  try {
103  sStratimikos_ = rcp(new StratimikosSmoother(type_, paramList));
104  if (sStratimikos_.is_null())
105  errorStratimikos_ = "Unable to construct Stratimikos smoother";
106  else if (!sStratimikos_->constructionSuccessful()) {
107  errorStratimikos_ = sStratimikos_->constructionErrorMsg();
108  sStratimikos_ = Teuchos::null;
109  }
110  } catch (Exceptions::RuntimeError& e) {
111  errorStratimikos_ = e.what();
112  }
113  triedStratimikos_ = true;
114 #endif
115 
116  // Check if we were able to construct at least one smoother. In many cases that's all we need, for instance if a user
117  // simply wants to use Tpetra only stack, never enables Ifpack, and always runs Tpetra objects.
119  "Unable to construct any smoother."
120  "Please enable (TPETRA and IFPACK2) or (EPETRA and IFPACK) or (BELOS) or (STRATIMIKOS)");
121 
122  TEUCHOS_TEST_FOR_EXCEPTION(sEpetra_.is_null() && sTpetra_.is_null() && sBelos_.is_null() && sStratimikos_.is_null(), Exceptions::RuntimeError,
123  "Could not construct any smoother:\n"
124  << (triedEpetra_ ? "=> Failed to build an Epetra smoother due to the following exception:\n" : "=> Epetra and/or Ifpack are not enabled.\n")
125  << (triedEpetra_ ? errorEpetra_ + "\n" : "")
126  << (triedTpetra_ ? "=> Failed to build a Tpetra smoother due to the following exception:\n" : "=> Tpetra and/or Ifpack2 are not enabled.\n")
127  << (triedTpetra_ ? errorTpetra_ + "\n" : "")
128  << (triedBelos_ ? "=> Failed to build a Belos smoother due to the following exception:\n" : "=> Belos not enabled.\n")
129  << (triedBelos_ ? errorBelos_ + "\n" : "")
130  << (triedStratimikos_ ? "=> Failed to build a Stratimikos smoother due to the following exception:\n" : "=> Stratimikos not enabled.\n")
131  << (triedStratimikos_ ? errorStratimikos_ + "\n" : ""));
132 
133  this->SetParameterList(paramList);
134 }
135 
136 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
138  // We need to propagate SetFactory to proper place
139  if (!sEpetra_.is_null()) sEpetra_->SetFactory(varName, factory);
140  if (!sTpetra_.is_null()) sTpetra_->SetFactory(varName, factory);
141  if (!sBelos_.is_null()) sBelos_->SetFactory(varName, factory);
142  if (!sStratimikos_.is_null()) sStratimikos_->SetFactory(varName, factory);
143 }
144 
145 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
147  if (!sBelos_.is_null())
148  s_ = sBelos_;
149  else if (!sStratimikos_.is_null())
150  s_ = sStratimikos_;
151  else {
152  // Decide whether we are running in Epetra or Tpetra mode
153  //
154  // Theoretically, we could make this decision in the constructor, and create only
155  // one of the smoothers. But we want to be able to reuse, so one can imagine a scenario
156  // where one first runs hierarchy with tpetra matrix, and then with epetra.
157 
158  bool useTpetra = (currentLevel.lib() == Xpetra::UseTpetra);
159  s_ = (useTpetra ? sTpetra_ : sEpetra_);
160  if (s_.is_null()) {
161  if (useTpetra) {
162 #if not defined(HAVE_MUELU_IFPACK2)
164  "Error: running in Tpetra mode, but MueLu with Ifpack2 was disabled during the configure stage.\n"
165  "Please make sure that:\n"
166  " - Ifpack2 is enabled (Trilinos_ENABLE_Ifpack2=ON),\n"
167  " - Ifpack2 is available for MueLu to use (MueLu_ENABLE_Ifpack2=ON)\n");
168 #else
169  if (triedTpetra_)
170  this->GetOStream(Errors) << "Tpetra mode was disabled due to an error:\n"
171  << errorTpetra_ << std::endl;
172 #endif
173  }
174  if (!useTpetra) {
175 #if not defined(HAVE_MUELU_IFPACK)
177  "Error: running in Epetra mode, but MueLu with Ifpack was disabled during the configure stage.\n"
178  "Please make sure that:\n"
179  " - Ifpack is enabled (you can do that with Trilinos_ENABLE_Ifpack=ON),\n"
180  " - Ifpack is available for MueLu to use (MueLu_ENABLE_Ifpack=ON)\n");
181 #else
182  if (triedEpetra_)
183  this->GetOStream(Errors) << "Epetra mode was disabled due to an error:\n"
184  << errorEpetra_ << std::endl;
185 #endif
186  }
188  "Smoother for " << (useTpetra ? "Tpetra" : "Epetra") << " was not constructed");
189  }
190  }
191 
192  s_->DeclareInput(currentLevel);
193 }
194 
195 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
197  if (SmootherPrototype::IsSetup() == true)
198  this->GetOStream(Warnings0) << "MueLu::TrilinosSmoother::Setup(): Setup() has already been called" << std::endl;
199 
200  int oldRank = s_->SetProcRankVerbose(this->GetProcRankVerbose());
201 
202  s_->Setup(currentLevel);
203 
204  s_->SetProcRankVerbose(oldRank);
205 
207 
208  this->SetParameterList(s_->GetParameterList());
209 }
210 
211 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
212 void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector& X, const MultiVector& B, bool InitialGuessIsZero) const {
213  TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::TrilinosSmoother::Apply(): Setup() has not been called");
214 
215  s_->Apply(X, B, InitialGuessIsZero);
216 }
217 
218 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
221  RCP<TrilinosSmoother> newSmoo = rcp(new TrilinosSmoother(type_, this->GetParameterList(), overlap_));
222 
223  // We need to be quite careful with Copy
224  // We still want TrilinosSmoother to follow Prototype Pattern, so we need to hide the fact that we do have some state
225  if (!sEpetra_.is_null())
226  newSmoo->sEpetra_ = sEpetra_->Copy();
227  if (!sTpetra_.is_null())
228  newSmoo->sTpetra_ = sTpetra_->Copy();
229  if (!sBelos_.is_null())
230  newSmoo->sBelos_ = sBelos_->Copy();
231  if (!sStratimikos_.is_null())
232  newSmoo->sStratimikos_ = sStratimikos_->Copy();
233 
234  // Copy the default mode
235  if (s_.get() == sBelos_.get())
236  newSmoo->s_ = newSmoo->sBelos_;
237  else if (s_.get() == sStratimikos_.get())
238  newSmoo->s_ = newSmoo->sStratimikos_;
239  else if (s_.get() == sTpetra_.get())
240  newSmoo->s_ = newSmoo->sTpetra_;
241  else
242  newSmoo->s_ = newSmoo->sEpetra_;
243  newSmoo->SetParameterList(this->GetParameterList());
244 
245  return newSmoo;
246 }
247 
248 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
250  if (type == "RELAXATION") {
251  return "point relaxation stand-alone";
252  }
253  if (type == "CHEBYSHEV") {
254  return "Chebyshev";
255  }
256  if (type == "ILUT") {
257  return "ILUT";
258  }
259  if (type == "RILUK") {
260  return "ILU";
261  }
262  if (type == "ILU") {
263  return "ILU";
264  }
265  if (type == "Amesos") {
266  return "Amesos";
267  }
268 
269  // special types
270 
271  // Note: for Ifpack there is no distinction between block and banded relaxation as there is no
272  // BandedContainer or TridiagonalContainer.
273  if (type == "LINESMOOTHING_BLOCKRELAXATION") {
274  return "LINESMOOTHING_BLOCKRELAXATION";
275  }
276  if (type == "LINESMOOTHING_BLOCK RELAXATION") {
277  return "LINESMOOTHING_BLOCKRELAXATION";
278  }
279  if (type == "LINESMOOTHING_BLOCK_RELAXATION") {
280  return "LINESMOOTHING_BLOCKRELAXATION";
281  }
282  if (type == "LINESMOOTHING_BANDEDRELAXATION") {
283  return "LINESMOOTHING_BLOCKRELAXATION";
284  }
285  if (type == "LINESMOOTHING_BANDED RELAXATION") {
286  return "LINESMOOTHING_BLOCKRELAXATION";
287  }
288  if (type == "LINESMOOTHING_BANDED_RELAXATION") {
289  return "LINESMOOTHING_BLOCKRELAXATION";
290  }
291  if (type == "LINESMOOTHING_TRIDIRELAXATION") {
292  return "LINESMOOTHING_BLOCKRELAXATION";
293  }
294  if (type == "LINESMOOTHING_TRIDI RELAXATION") {
295  return "LINESMOOTHING_BLOCKRELAXATION";
296  }
297  if (type == "LINESMOOTHING_TRIDI_RELAXATION") {
298  return "LINESMOOTHING_BLOCKRELAXATION";
299  }
300  if (type == "LINESMOOTHING_TRIDIAGONALRELAXATION") {
301  return "LINESMOOTHING_BLOCKRELAXATION";
302  }
303  if (type == "LINESMOOTHING_TRIDIAGONAL RELAXATION") {
304  return "LINESMOOTHING_BLOCKRELAXATION";
305  }
306  if (type == "LINESMOOTHING_TRIDIAGONAL_RELAXATION") {
307  return "LINESMOOTHING_BLOCKRELAXATION";
308  }
309  if (type == "AGGREGATE") {
310  return "AGGREGATE";
311  }
312  if (type == "BLOCK_RELAXATION" ||
313  type == "BLOCK RELAXATION" ||
314  type == "BLOCKRELAXATION" ||
315  // Banded
316  type == "BANDED_RELAXATION" ||
317  type == "BANDED RELAXATION" ||
318  type == "BANDEDRELAXATION" ||
319  // Tridiagonal
320  type == "TRIDI_RELAXATION" ||
321  type == "TRIDI RELAXATION" ||
322  type == "TRIDIRELAXATION" ||
323  type == "TRIDIAGONAL_RELAXATION" ||
324  type == "TRIDIAGONAL RELAXATION" ||
325  type == "TRIDIAGONALRELAXATION") {
326  return "block relaxation stand-alone";
327  }
328 
329  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Cannot convert Ifpack2 preconditioner name to Ifpack: unknown type: \"" + type + "\"");
330 }
331 
332 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
334  Teuchos::ParameterList ifpack1List = ifpack2List;
335 
336  if (ifpack2List.isParameter("relaxation: type") && ifpack2List.get<std::string>("relaxation: type") == "Symmetric Gauss-Seidel")
337  ifpack1List.set("relaxation: type", "symmetric Gauss-Seidel");
338 
339  if (ifpack2List.isParameter("fact: iluk level-of-fill")) {
340  ifpack1List.remove("fact: iluk level-of-fill");
341  ifpack1List.set("fact: level-of-fill", ifpack2List.get<int>("fact: iluk level-of-fill"));
342  }
343 
344  return ifpack1List;
345 }
346 
347 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
349  std::ostringstream out;
350  if (s_ != Teuchos::null) {
351  out << s_->description();
352  } else {
354  out << "{type = " << type_ << "}";
355  }
356  return out.str();
357 }
358 
359 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
362 
363  if (verbLevel & Parameters0)
364  out0 << "Prec. type: " << type_ << std::endl;
365 
366  if (verbLevel & Parameters1) {
367  out0 << "PrecType: " << type_ << std::endl;
368  out0 << "Parameter list: " << std::endl;
369  Teuchos::OSTab tab2(out);
370  out << this->GetParameterList();
371  out0 << "Overlap: " << overlap_ << std::endl;
372  }
373 
374  if (verbLevel & Debug) {
375  out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl
376  << "-" << std::endl
377  << "Epetra PrecType: " << Ifpack2ToIfpack1Type(type_) << std::endl
378  << "Epetra Parameter list: " << std::endl;
379  Teuchos::OSTab tab2(out);
380  out << Ifpack2ToIfpack1Param(this->GetParameterList());
381  ;
382  }
383 }
384 
385 } // namespace MueLu
386 
387 #endif // MUELU_TRILINOSSMOOTHER_DEF_HPP
Important warning messages (one line)
Exception indicating invalid cast attempted.
std::string description() const
Return a simple one-line description of this object.
RCP< SmootherPrototype > sStratimikos_
T & get(const std::string &name, T def_value)
Class that encapsulates external library smoothers.
static std::string Ifpack2ToIfpack1Type(const std::string &type)
Convert an Ifpack2 preconditioner name to Ifpack.
static Teuchos::ParameterList Ifpack2ToIfpack1Param(const Teuchos::ParameterList &ifpack2List)
Convert an Ifpack2 parameter list to Ifpack.
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the object with some verbosity level to an FancyOStream object.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Class that encapsulates Belos smoothers.
Print additional debugging information.
LocalOrdinal LO
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
void Apply(MultiVector &X, const MultiVector &B, bool InitialGuessIsZero=false) const
TrilinosSmoother cannot be applied. Apply() always returns a RuntimeError exception.
void Setup(Level &currentLevel)
TrilinosSmoother cannot be turned into a smoother using Setup(). Setup() always returns a RuntimeErro...
friend class TrilinosSmoother
Friend declaration required for clone() functionality.
bool isParameter(const std::string &name) const
bool remove(std::string const &name, bool throwIfNotExists=true)
virtual void SetParameterList(const Teuchos::ParameterList &paramList)
Set parameters from a parameter list and return with default values.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
std::string type_
ifpack1/2-specific key phrase that denote smoother type
bool IsSetup() const
Get the state of a smoother prototype.
Xpetra::UnderlyingLib lib()
RCP< SmootherPrototype > Copy() const
When this prototype is cloned using Copy(), the clone is an Ifpack or an Ifpack2 smoother.
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
Print class parameters.
void DeclareInput(Level &currentLevel) const
Input.
RCP< SmootherPrototype > sEpetra_
Smoother.
Print class parameters (more parameters, more verbose)
Exception throws to report errors in the internal logical of the program.
LO overlap_
overlap when using the smoother in additive Schwarz mode
Class that encapsulates Ifpack2 smoothers.
virtual std::string description() const
Return a simple one-line description of this object.
std::string toString(const T &t)
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Custom SetFactory.