MueLu Version of the Day
Loading...
Searching...
No Matches
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"
20#include "MueLu_Ifpack2Smoother.hpp"
21#include "MueLu_BelosSmoother.hpp"
22#include "MueLu_StratimikosSmoother.hpp"
23#include "MueLu_Exceptions.hpp"
24
25namespace MueLu {
26
27template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
28TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TrilinosSmoother(const std::string& type, const Teuchos::ParameterList& paramListIn, const LO& overlap)
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();
64 } catch (Teuchos::Exceptions::InvalidParameterName& e) {
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.
118 TEUCHOS_TEST_FOR_EXCEPTION(!triedEpetra_ && !triedTpetra_ && !triedBelos_ && !triedStratimikos_, Exceptions::RuntimeError,
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
136template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
137void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetFactory(const std::string& varName, const RCP<const FactoryBase>& factory) {
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
145template <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)
163 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError,
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)
176 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError,
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 }
187 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError,
188 "Smoother for " << (useTpetra ? "Tpetra" : "Epetra") << " was not constructed");
189 }
190 }
191
192 s_->DeclareInput(currentLevel);
193}
194
195template <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
211template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
212void 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
218template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
219RCP<MueLu::SmootherPrototype<Scalar, LocalOrdinal, GlobalOrdinal, 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
248template <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
332template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
333Teuchos::ParameterList TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Ifpack2ToIfpack1Param(const Teuchos::ParameterList& ifpack2List) {
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
347template <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
359template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
360void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::print(Teuchos::FancyOStream& out, const VerbLevel verbLevel) const {
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
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
Class that encapsulates Belos smoothers.
virtual std::string description() const
Return a simple one-line description of this object.
Exception indicating invalid cast attempted.
Exception throws to report errors in the internal logical of the program.
Class that encapsulates Ifpack2 smoothers.
Class that holds all level-specific information.
Xpetra::UnderlyingLib lib()
virtual void SetParameterList(const Teuchos::ParameterList &paramList)
Set parameters from a parameter list and return with default values.
bool IsSetup() const
Get the state of a smoother prototype.
Class that encapsulates external library smoothers.
RCP< SmootherPrototype > Copy() const
When this prototype is cloned using Copy(), the clone is an Ifpack or an Ifpack2 smoother.
void Setup(Level &currentLevel)
TrilinosSmoother cannot be turned into a smoother using Setup(). Setup() always returns a RuntimeErro...
LO overlap_
overlap when using the smoother in additive Schwarz mode
static Teuchos::ParameterList Ifpack2ToIfpack1Param(const Teuchos::ParameterList &ifpack2List)
Convert an Ifpack2 parameter list to Ifpack.
static std::string Ifpack2ToIfpack1Type(const std::string &type)
Convert an Ifpack2 preconditioner name to Ifpack.
std::string type_
ifpack1/2-specific key phrase that denote smoother type
friend class TrilinosSmoother
Friend declaration required for clone() functionality.
void DeclareInput(Level &currentLevel) const
Input.
RCP< SmootherPrototype > sEpetra_
Smoother.
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Custom SetFactory.
RCP< SmootherPrototype > sStratimikos_
void Apply(MultiVector &X, const MultiVector &B, bool InitialGuessIsZero=false) const
TrilinosSmoother cannot be applied. Apply() always returns a RuntimeError exception.
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the object with some verbosity level to an FancyOStream object.
std::string description() const
Return a simple one-line description of this object.
Namespace for MueLu classes and methods.
@ Warnings0
Important warning messages (one line)
@ Debug
Print additional debugging information.
@ Parameters0
Print class parameters.
@ Parameters1
Print class parameters (more parameters, more verbose)