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 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_TRILINOSSMOOTHER_DEF_HPP
47 #define MUELU_TRILINOSSMOOTHER_DEF_HPP
48 
49 #include <Xpetra_Map.hpp>
50 #include <Xpetra_Matrix.hpp>
51 
53 
54 #include "MueLu_Level.hpp"
55 #include "MueLu_IfpackSmoother.hpp"
56 #include "MueLu_Ifpack2Smoother.hpp"
57 #include "MueLu_BelosSmoother.hpp"
58 #include "MueLu_StratimikosSmoother.hpp"
59 #include "MueLu_Exceptions.hpp"
60 
61 namespace MueLu {
62 
63 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
65  : type_(type)
66  , overlap_(overlap) {
67  // The original idea behind all smoothers was to use prototype pattern. However, it does not fully work of the dependencies
68  // calculation. Particularly, we need to propagate DeclareInput to proper prototypes. Therefore, both TrilinosSmoother and
69  // DirectSolver do not follow the pattern exactly.
70  // The difference is that in order to propagate the calculation of dependencies, we need to call a DeclareInput on a
71  // constructed object (or objects, as we have two different code branches for Epetra and Tpetra). The only place where we
72  // could construct these objects is the constructor. Thus, we need to store RCPs, and both TrilinosSmoother and DirectSolver
73  // obtain a state: they contain RCP to smoother prototypes.
74  sEpetra_ = Teuchos::null;
75  sTpetra_ = Teuchos::null;
76  sBelos_ = Teuchos::null;
77  sStratimikos_ = Teuchos::null;
78 
79  TEUCHOS_TEST_FOR_EXCEPTION(overlap_ < 0, Exceptions::RuntimeError, "Overlap parameter is negative (" << overlap << ")");
80 
81  // paramList contains only parameters which are understood by Ifpack/Ifpack2
82  ParameterList paramList = paramListIn;
83 
84  // We want TrilinosSmoother to be able to work with both Epetra and Tpetra objects, therefore we try to construct both
85  // Ifpack and Ifpack2 smoother prototypes. The construction really depends on configuration options.
87 #if defined(HAVE_MUELU_IFPACK2)
88  try {
89  sTpetra_ = rcp(new Ifpack2Smoother(type_, paramList, overlap_));
90  if (sTpetra_.is_null())
91  errorTpetra_ = "Unable to construct Ifpack2 smoother";
92  else if (!sTpetra_->constructionSuccessful()) {
93  errorTpetra_ = sTpetra_->constructionErrorMsg();
94  sTpetra_ = Teuchos::null;
95  }
96  } catch (Exceptions::RuntimeError& e) {
97  errorTpetra_ = e.what();
98  } catch (Exceptions::BadCast& e) {
99  errorTpetra_ = e.what();
101  errorTpetra_ = e.what();
102  }
103  triedTpetra_ = true;
104 #endif
105 #if defined(HAVE_MUELU_EPETRA) && defined(HAVE_MUELU_IFPACK)
106  try {
107  // GetIfpackSmoother masks the template argument matching, and simply throws if template arguments are incompatible with Epetra
109  if (sEpetra_.is_null())
110  errorEpetra_ = "Unable to construct Ifpack smoother";
111  else if (!sEpetra_->constructionSuccessful()) {
112  errorEpetra_ = sEpetra_->constructionErrorMsg();
113  sEpetra_ = Teuchos::null;
114  }
115  } catch (Exceptions::RuntimeError& e) {
116  // IfpackSmoother throws if Scalar != double, LocalOrdinal != int, GlobalOrdinal != int
117  errorEpetra_ = e.what();
118  }
119  triedEpetra_ = true;
120 #endif
121 #if defined(HAVE_MUELU_BELOS)
122  try {
123  sBelos_ = rcp(new BelosSmoother(type_, paramList));
124  if (sBelos_.is_null())
125  errorBelos_ = "Unable to construct Belos smoother";
126  else if (!sBelos_->constructionSuccessful()) {
127  errorBelos_ = sBelos_->constructionErrorMsg();
128  sBelos_ = Teuchos::null;
129  }
130  } catch (Exceptions::RuntimeError& e) {
131  errorBelos_ = e.what();
132  } catch (Exceptions::BadCast& e) {
133  errorBelos_ = e.what();
134  }
135  triedBelos_ = true;
136 #endif
137 #if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
138  try {
139  sStratimikos_ = rcp(new StratimikosSmoother(type_, paramList));
140  if (sStratimikos_.is_null())
141  errorStratimikos_ = "Unable to construct Stratimikos smoother";
142  else if (!sStratimikos_->constructionSuccessful()) {
143  errorStratimikos_ = sStratimikos_->constructionErrorMsg();
144  sStratimikos_ = Teuchos::null;
145  }
146  } catch (Exceptions::RuntimeError& e) {
147  errorStratimikos_ = e.what();
148  }
149  triedStratimikos_ = true;
150 #endif
151 
152  // Check if we were able to construct at least one smoother. In many cases that's all we need, for instance if a user
153  // simply wants to use Tpetra only stack, never enables Ifpack, and always runs Tpetra objects.
155  "Unable to construct any smoother."
156  "Please enable (TPETRA and IFPACK2) or (EPETRA and IFPACK) or (BELOS) or (STRATIMIKOS)");
157 
158  TEUCHOS_TEST_FOR_EXCEPTION(sEpetra_.is_null() && sTpetra_.is_null() && sBelos_.is_null() && sStratimikos_.is_null(), Exceptions::RuntimeError,
159  "Could not construct any smoother:\n"
160  << (triedEpetra_ ? "=> Failed to build an Epetra smoother due to the following exception:\n" : "=> Epetra and/or Ifpack are not enabled.\n")
161  << (triedEpetra_ ? errorEpetra_ + "\n" : "")
162  << (triedTpetra_ ? "=> Failed to build a Tpetra smoother due to the following exception:\n" : "=> Tpetra and/or Ifpack2 are not enabled.\n")
163  << (triedTpetra_ ? errorTpetra_ + "\n" : "")
164  << (triedBelos_ ? "=> Failed to build a Belos smoother due to the following exception:\n" : "=> Belos not enabled.\n")
165  << (triedBelos_ ? errorBelos_ + "\n" : "")
166  << (triedStratimikos_ ? "=> Failed to build a Stratimikos smoother due to the following exception:\n" : "=> Stratimikos not enabled.\n")
167  << (triedStratimikos_ ? errorStratimikos_ + "\n" : ""));
168 
169  this->SetParameterList(paramList);
170 }
171 
172 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
174  // We need to propagate SetFactory to proper place
175  if (!sEpetra_.is_null()) sEpetra_->SetFactory(varName, factory);
176  if (!sTpetra_.is_null()) sTpetra_->SetFactory(varName, factory);
177  if (!sBelos_.is_null()) sBelos_->SetFactory(varName, factory);
178  if (!sStratimikos_.is_null()) sStratimikos_->SetFactory(varName, factory);
179 }
180 
181 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
183  if (!sBelos_.is_null())
184  s_ = sBelos_;
185  else if (!sStratimikos_.is_null())
186  s_ = sStratimikos_;
187  else {
188  // Decide whether we are running in Epetra or Tpetra mode
189  //
190  // Theoretically, we could make this decision in the constructor, and create only
191  // one of the smoothers. But we want to be able to reuse, so one can imagine a scenario
192  // where one first runs hierarchy with tpetra matrix, and then with epetra.
193 
194  bool useTpetra = (currentLevel.lib() == Xpetra::UseTpetra);
195  s_ = (useTpetra ? sTpetra_ : sEpetra_);
196  if (s_.is_null()) {
197  if (useTpetra) {
198 #if not defined(HAVE_MUELU_IFPACK2)
200  "Error: running in Tpetra mode, but MueLu with Ifpack2 was disabled during the configure stage.\n"
201  "Please make sure that:\n"
202  " - Ifpack2 is enabled (Trilinos_ENABLE_Ifpack2=ON),\n"
203  " - Ifpack2 is available for MueLu to use (MueLu_ENABLE_Ifpack2=ON)\n");
204 #else
205  if (triedTpetra_)
206  this->GetOStream(Errors) << "Tpetra mode was disabled due to an error:\n"
207  << errorTpetra_ << std::endl;
208 #endif
209  }
210  if (!useTpetra) {
211 #if not defined(HAVE_MUELU_IFPACK)
213  "Error: running in Epetra mode, but MueLu with Ifpack was disabled during the configure stage.\n"
214  "Please make sure that:\n"
215  " - Ifpack is enabled (you can do that with Trilinos_ENABLE_Ifpack=ON),\n"
216  " - Ifpack is available for MueLu to use (MueLu_ENABLE_Ifpack=ON)\n");
217 #else
218  if (triedEpetra_)
219  this->GetOStream(Errors) << "Epetra mode was disabled due to an error:\n"
220  << errorEpetra_ << std::endl;
221 #endif
222  }
224  "Smoother for " << (useTpetra ? "Tpetra" : "Epetra") << " was not constructed");
225  }
226  }
227 
228  s_->DeclareInput(currentLevel);
229 }
230 
231 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
233  if (SmootherPrototype::IsSetup() == true)
234  this->GetOStream(Warnings0) << "MueLu::TrilinosSmoother::Setup(): Setup() has already been called" << std::endl;
235 
236  int oldRank = s_->SetProcRankVerbose(this->GetProcRankVerbose());
237 
238  s_->Setup(currentLevel);
239 
240  s_->SetProcRankVerbose(oldRank);
241 
243 
244  this->SetParameterList(s_->GetParameterList());
245 }
246 
247 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
248 void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector& X, const MultiVector& B, bool InitialGuessIsZero) const {
249  TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::TrilinosSmoother::Apply(): Setup() has not been called");
250 
251  s_->Apply(X, B, InitialGuessIsZero);
252 }
253 
254 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
257  RCP<TrilinosSmoother> newSmoo = rcp(new TrilinosSmoother(type_, this->GetParameterList(), overlap_));
258 
259  // We need to be quite careful with Copy
260  // We still want TrilinosSmoother to follow Prototype Pattern, so we need to hide the fact that we do have some state
261  if (!sEpetra_.is_null())
262  newSmoo->sEpetra_ = sEpetra_->Copy();
263  if (!sTpetra_.is_null())
264  newSmoo->sTpetra_ = sTpetra_->Copy();
265  if (!sBelos_.is_null())
266  newSmoo->sBelos_ = sBelos_->Copy();
267  if (!sStratimikos_.is_null())
268  newSmoo->sStratimikos_ = sStratimikos_->Copy();
269 
270  // Copy the default mode
271  if (s_.get() == sBelos_.get())
272  newSmoo->s_ = newSmoo->sBelos_;
273  else if (s_.get() == sStratimikos_.get())
274  newSmoo->s_ = newSmoo->sStratimikos_;
275  else if (s_.get() == sTpetra_.get())
276  newSmoo->s_ = newSmoo->sTpetra_;
277  else
278  newSmoo->s_ = newSmoo->sEpetra_;
279  newSmoo->SetParameterList(this->GetParameterList());
280 
281  return newSmoo;
282 }
283 
284 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
286  if (type == "RELAXATION") {
287  return "point relaxation stand-alone";
288  }
289  if (type == "CHEBYSHEV") {
290  return "Chebyshev";
291  }
292  if (type == "ILUT") {
293  return "ILUT";
294  }
295  if (type == "RILUK") {
296  return "ILU";
297  }
298  if (type == "ILU") {
299  return "ILU";
300  }
301  if (type == "Amesos") {
302  return "Amesos";
303  }
304 
305  // special types
306 
307  // Note: for Ifpack there is no distinction between block and banded relaxation as there is no
308  // BandedContainer or TridiagonalContainer.
309  if (type == "LINESMOOTHING_BLOCKRELAXATION") {
310  return "LINESMOOTHING_BLOCKRELAXATION";
311  }
312  if (type == "LINESMOOTHING_BLOCK RELAXATION") {
313  return "LINESMOOTHING_BLOCKRELAXATION";
314  }
315  if (type == "LINESMOOTHING_BLOCK_RELAXATION") {
316  return "LINESMOOTHING_BLOCKRELAXATION";
317  }
318  if (type == "LINESMOOTHING_BANDEDRELAXATION") {
319  return "LINESMOOTHING_BLOCKRELAXATION";
320  }
321  if (type == "LINESMOOTHING_BANDED RELAXATION") {
322  return "LINESMOOTHING_BLOCKRELAXATION";
323  }
324  if (type == "LINESMOOTHING_BANDED_RELAXATION") {
325  return "LINESMOOTHING_BLOCKRELAXATION";
326  }
327  if (type == "LINESMOOTHING_TRIDIRELAXATION") {
328  return "LINESMOOTHING_BLOCKRELAXATION";
329  }
330  if (type == "LINESMOOTHING_TRIDI RELAXATION") {
331  return "LINESMOOTHING_BLOCKRELAXATION";
332  }
333  if (type == "LINESMOOTHING_TRIDI_RELAXATION") {
334  return "LINESMOOTHING_BLOCKRELAXATION";
335  }
336  if (type == "LINESMOOTHING_TRIDIAGONALRELAXATION") {
337  return "LINESMOOTHING_BLOCKRELAXATION";
338  }
339  if (type == "LINESMOOTHING_TRIDIAGONAL RELAXATION") {
340  return "LINESMOOTHING_BLOCKRELAXATION";
341  }
342  if (type == "LINESMOOTHING_TRIDIAGONAL_RELAXATION") {
343  return "LINESMOOTHING_BLOCKRELAXATION";
344  }
345  if (type == "AGGREGATE") {
346  return "AGGREGATE";
347  }
348  if (type == "BLOCK_RELAXATION" ||
349  type == "BLOCK RELAXATION" ||
350  type == "BLOCKRELAXATION" ||
351  // Banded
352  type == "BANDED_RELAXATION" ||
353  type == "BANDED RELAXATION" ||
354  type == "BANDEDRELAXATION" ||
355  // Tridiagonal
356  type == "TRIDI_RELAXATION" ||
357  type == "TRIDI RELAXATION" ||
358  type == "TRIDIRELAXATION" ||
359  type == "TRIDIAGONAL_RELAXATION" ||
360  type == "TRIDIAGONAL RELAXATION" ||
361  type == "TRIDIAGONALRELAXATION") {
362  return "block relaxation stand-alone";
363  }
364 
365  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Cannot convert Ifpack2 preconditioner name to Ifpack: unknown type: \"" + type + "\"");
366 }
367 
368 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
370  Teuchos::ParameterList ifpack1List = ifpack2List;
371 
372  if (ifpack2List.isParameter("relaxation: type") && ifpack2List.get<std::string>("relaxation: type") == "Symmetric Gauss-Seidel")
373  ifpack1List.set("relaxation: type", "symmetric Gauss-Seidel");
374 
375  if (ifpack2List.isParameter("fact: iluk level-of-fill")) {
376  ifpack1List.remove("fact: iluk level-of-fill");
377  ifpack1List.set("fact: level-of-fill", ifpack2List.get<int>("fact: iluk level-of-fill"));
378  }
379 
380  return ifpack1List;
381 }
382 
383 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
385  std::ostringstream out;
386  if (s_ != Teuchos::null) {
387  out << s_->description();
388  } else {
390  out << "{type = " << type_ << "}";
391  }
392  return out.str();
393 }
394 
395 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
398 
399  if (verbLevel & Parameters0)
400  out0 << "Prec. type: " << type_ << std::endl;
401 
402  if (verbLevel & Parameters1) {
403  out0 << "PrecType: " << type_ << std::endl;
404  out0 << "Parameter list: " << std::endl;
405  Teuchos::OSTab tab2(out);
406  out << this->GetParameterList();
407  out0 << "Overlap: " << overlap_ << std::endl;
408  }
409 
410  if (verbLevel & Debug) {
411  out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl
412  << "-" << std::endl
413  << "Epetra PrecType: " << Ifpack2ToIfpack1Type(type_) << std::endl
414  << "Epetra Parameter list: " << std::endl;
415  Teuchos::OSTab tab2(out);
416  out << Ifpack2ToIfpack1Param(this->GetParameterList());
417  ;
418  }
419 }
420 
421 } // namespace MueLu
422 
423 #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.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
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
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:99
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.