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 try {
52 sTpetra_ = rcp(new Ifpack2Smoother(type_, paramList, overlap_));
53 if (sTpetra_.is_null())
54 errorTpetra_ = "Unable to construct Ifpack2 smoother";
55 else if (!sTpetra_->constructionSuccessful()) {
56 errorTpetra_ = sTpetra_->constructionErrorMsg();
57 sTpetra_ = Teuchos::null;
58 }
59 } catch (Exceptions::RuntimeError& e) {
60 errorTpetra_ = e.what();
61 } catch (Exceptions::BadCast& e) {
62 errorTpetra_ = e.what();
63 } catch (Teuchos::Exceptions::InvalidParameterName& e) {
64 errorTpetra_ = e.what();
65 }
66 triedTpetra_ = true;
67#if defined(HAVE_MUELU_BELOS)
68 try {
69 sBelos_ = rcp(new BelosSmoother(type_, paramList));
70 if (sBelos_.is_null())
71 errorBelos_ = "Unable to construct Belos smoother";
72 else if (!sBelos_->constructionSuccessful()) {
73 errorBelos_ = sBelos_->constructionErrorMsg();
74 sBelos_ = Teuchos::null;
75 }
76 } catch (Exceptions::RuntimeError& e) {
77 errorBelos_ = e.what();
78 } catch (Exceptions::BadCast& e) {
79 errorBelos_ = e.what();
80 }
81 triedBelos_ = true;
82#endif
83#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
84 try {
85 sStratimikos_ = rcp(new StratimikosSmoother(type_, paramList));
86 if (sStratimikos_.is_null())
87 errorStratimikos_ = "Unable to construct Stratimikos smoother";
88 else if (!sStratimikos_->constructionSuccessful()) {
89 errorStratimikos_ = sStratimikos_->constructionErrorMsg();
90 sStratimikos_ = Teuchos::null;
91 }
92 } catch (Exceptions::RuntimeError& e) {
93 errorStratimikos_ = e.what();
94 }
95 triedStratimikos_ = true;
96#endif
97
98 // Check if we were able to construct at least one smoother. In many cases that's all we need, for instance if a user
99 // simply wants to use Tpetra only stack, never enables Ifpack, and always runs Tpetra objects.
100 TEUCHOS_TEST_FOR_EXCEPTION(!triedEpetra_ && !triedTpetra_ && !triedBelos_ && !triedStratimikos_, Exceptions::RuntimeError,
101 "Unable to construct any smoother."
102 "Please enable (TPETRA and IFPACK2) or (EPETRA and IFPACK) or (BELOS) or (STRATIMIKOS)");
103
104 TEUCHOS_TEST_FOR_EXCEPTION(sEpetra_.is_null() && sTpetra_.is_null() && sBelos_.is_null() && sStratimikos_.is_null(), Exceptions::RuntimeError,
105 "Could not construct any smoother:\n"
106 << (triedEpetra_ ? "=> Failed to build an Epetra smoother due to the following exception:\n" : "=> Epetra and/or Ifpack are not enabled.\n")
107 << (triedEpetra_ ? errorEpetra_ + "\n" : "")
108 << (triedTpetra_ ? "=> Failed to build a Tpetra smoother due to the following exception:\n" : "=> Tpetra and/or Ifpack2 are not enabled.\n")
109 << (triedTpetra_ ? errorTpetra_ + "\n" : "")
110 << (triedBelos_ ? "=> Failed to build a Belos smoother due to the following exception:\n" : "=> Belos not enabled.\n")
111 << (triedBelos_ ? errorBelos_ + "\n" : "")
112 << (triedStratimikos_ ? "=> Failed to build a Stratimikos smoother due to the following exception:\n" : "=> Stratimikos not enabled.\n")
113 << (triedStratimikos_ ? errorStratimikos_ + "\n" : ""));
114
115 this->SetParameterList(paramList);
116}
117
118template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
119void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetFactory(const std::string& varName, const RCP<const FactoryBase>& factory) {
120 // We need to propagate SetFactory to proper place
121 if (!sEpetra_.is_null()) sEpetra_->SetFactory(varName, factory);
122 if (!sTpetra_.is_null()) sTpetra_->SetFactory(varName, factory);
123 if (!sBelos_.is_null()) sBelos_->SetFactory(varName, factory);
124 if (!sStratimikos_.is_null()) sStratimikos_->SetFactory(varName, factory);
125}
126
127template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
129 if (!sBelos_.is_null())
130 s_ = sBelos_;
131 else if (!sStratimikos_.is_null())
132 s_ = sStratimikos_;
133 else {
134 // Decide whether we are running in Epetra or Tpetra mode
135 //
136 // Theoretically, we could make this decision in the constructor, and create only
137 // one of the smoothers. But we want to be able to reuse, so one can imagine a scenario
138 // where one first runs hierarchy with tpetra matrix, and then with epetra.
139
140 bool useTpetra = (currentLevel.lib() == Xpetra::UseTpetra);
141 s_ = (useTpetra ? sTpetra_ : sEpetra_);
142 if (s_.is_null()) {
143 if (useTpetra) {
144#if not defined(HAVE_MUELU_IFPACK2)
145 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError,
146 "Error: running in Tpetra mode, but MueLu with Ifpack2 was disabled during the configure stage.\n"
147 "Please make sure that:\n"
148 " - Ifpack2 is enabled (Trilinos_ENABLE_Ifpack2=ON),\n"
149 " - Ifpack2 is available for MueLu to use (MueLu_ENABLE_Ifpack2=ON)\n");
150#else
151 if (triedTpetra_)
152 this->GetOStream(Errors) << "Tpetra mode was disabled due to an error:\n"
153 << errorTpetra_ << std::endl;
154#endif
155 }
156 if (!useTpetra) {
157#if not defined(HAVE_MUELU_IFPACK)
158 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError,
159 "Error: running in Epetra mode, but MueLu with Ifpack was disabled during the configure stage.\n"
160 "Please make sure that:\n"
161 " - Ifpack is enabled (you can do that with Trilinos_ENABLE_Ifpack=ON),\n"
162 " - Ifpack is available for MueLu to use (MueLu_ENABLE_Ifpack=ON)\n");
163#else
164 if (triedEpetra_)
165 this->GetOStream(Errors) << "Epetra mode was disabled due to an error:\n"
166 << errorEpetra_ << std::endl;
167#endif
168 }
169 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError,
170 "Smoother for " << (useTpetra ? "Tpetra" : "Epetra") << " was not constructed");
171 }
172 }
173
174 s_->DeclareInput(currentLevel);
175}
176
177template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
179 if (SmootherPrototype::IsSetup() == true)
180 this->GetOStream(Warnings0) << "MueLu::TrilinosSmoother::Setup(): Setup() has already been called" << std::endl;
181
182 int oldRank = s_->SetProcRankVerbose(this->GetProcRankVerbose());
183
184 s_->Setup(currentLevel);
185
186 s_->SetProcRankVerbose(oldRank);
187
189
190 this->SetParameterList(s_->GetParameterList());
191}
192
193template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
194void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector& X, const MultiVector& B, bool InitialGuessIsZero) const {
195 TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::TrilinosSmoother::Apply(): Setup() has not been called");
196
197 s_->Apply(X, B, InitialGuessIsZero);
198}
199
200template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
201RCP<MueLu::SmootherPrototype<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
203 RCP<TrilinosSmoother> newSmoo = rcp(new TrilinosSmoother(type_, this->GetParameterList(), overlap_));
204
205 // We need to be quite careful with Copy
206 // We still want TrilinosSmoother to follow Prototype Pattern, so we need to hide the fact that we do have some state
207 if (!sEpetra_.is_null())
208 newSmoo->sEpetra_ = sEpetra_->Copy();
209 if (!sTpetra_.is_null())
210 newSmoo->sTpetra_ = sTpetra_->Copy();
211 if (!sBelos_.is_null())
212 newSmoo->sBelos_ = sBelos_->Copy();
213 if (!sStratimikos_.is_null())
214 newSmoo->sStratimikos_ = sStratimikos_->Copy();
215
216 // Copy the default mode
217 if (s_.get() == sBelos_.get())
218 newSmoo->s_ = newSmoo->sBelos_;
219 else if (s_.get() == sStratimikos_.get())
220 newSmoo->s_ = newSmoo->sStratimikos_;
221 else if (s_.get() == sTpetra_.get())
222 newSmoo->s_ = newSmoo->sTpetra_;
223 else
224 newSmoo->s_ = newSmoo->sEpetra_;
225 newSmoo->SetParameterList(this->GetParameterList());
226
227 return newSmoo;
228}
229
230template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
232 if (type == "RELAXATION") {
233 return "point relaxation stand-alone";
234 }
235 if (type == "CHEBYSHEV") {
236 return "Chebyshev";
237 }
238 if (type == "ILUT") {
239 return "ILUT";
240 }
241 if (type == "RILUK") {
242 return "ILU";
243 }
244 if (type == "ILU") {
245 return "ILU";
246 }
247 if (type == "Amesos") {
248 return "Amesos";
249 }
250
251 // special types
252
253 // Note: for Ifpack there is no distinction between block and banded relaxation as there is no
254 // BandedContainer or TridiagonalContainer.
255 if (type == "LINESMOOTHING_BLOCKRELAXATION") {
256 return "LINESMOOTHING_BLOCKRELAXATION";
257 }
258 if (type == "LINESMOOTHING_BLOCK RELAXATION") {
259 return "LINESMOOTHING_BLOCKRELAXATION";
260 }
261 if (type == "LINESMOOTHING_BLOCK_RELAXATION") {
262 return "LINESMOOTHING_BLOCKRELAXATION";
263 }
264 if (type == "LINESMOOTHING_BANDEDRELAXATION") {
265 return "LINESMOOTHING_BLOCKRELAXATION";
266 }
267 if (type == "LINESMOOTHING_BANDED RELAXATION") {
268 return "LINESMOOTHING_BLOCKRELAXATION";
269 }
270 if (type == "LINESMOOTHING_BANDED_RELAXATION") {
271 return "LINESMOOTHING_BLOCKRELAXATION";
272 }
273 if (type == "LINESMOOTHING_TRIDIRELAXATION") {
274 return "LINESMOOTHING_BLOCKRELAXATION";
275 }
276 if (type == "LINESMOOTHING_TRIDI RELAXATION") {
277 return "LINESMOOTHING_BLOCKRELAXATION";
278 }
279 if (type == "LINESMOOTHING_TRIDI_RELAXATION") {
280 return "LINESMOOTHING_BLOCKRELAXATION";
281 }
282 if (type == "LINESMOOTHING_TRIDIAGONALRELAXATION") {
283 return "LINESMOOTHING_BLOCKRELAXATION";
284 }
285 if (type == "LINESMOOTHING_TRIDIAGONAL RELAXATION") {
286 return "LINESMOOTHING_BLOCKRELAXATION";
287 }
288 if (type == "LINESMOOTHING_TRIDIAGONAL_RELAXATION") {
289 return "LINESMOOTHING_BLOCKRELAXATION";
290 }
291 if (type == "AGGREGATE") {
292 return "AGGREGATE";
293 }
294 if (type == "BLOCK_RELAXATION" ||
295 type == "BLOCK RELAXATION" ||
296 type == "BLOCKRELAXATION" ||
297 // Banded
298 type == "BANDED_RELAXATION" ||
299 type == "BANDED RELAXATION" ||
300 type == "BANDEDRELAXATION" ||
301 // Tridiagonal
302 type == "TRIDI_RELAXATION" ||
303 type == "TRIDI RELAXATION" ||
304 type == "TRIDIRELAXATION" ||
305 type == "TRIDIAGONAL_RELAXATION" ||
306 type == "TRIDIAGONAL RELAXATION" ||
307 type == "TRIDIAGONALRELAXATION") {
308 return "block relaxation stand-alone";
309 }
310
311 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Cannot convert Ifpack2 preconditioner name to Ifpack: unknown type: \"" + type + "\"");
312}
313
314template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
315Teuchos::ParameterList TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Ifpack2ToIfpack1Param(const Teuchos::ParameterList& ifpack2List) {
316 Teuchos::ParameterList ifpack1List = ifpack2List;
317
318 if (ifpack2List.isParameter("relaxation: type") && ifpack2List.get<std::string>("relaxation: type") == "Symmetric Gauss-Seidel")
319 ifpack1List.set("relaxation: type", "symmetric Gauss-Seidel");
320
321 if (ifpack2List.isParameter("fact: iluk level-of-fill")) {
322 ifpack1List.remove("fact: iluk level-of-fill");
323 ifpack1List.set("fact: level-of-fill", ifpack2List.get<int>("fact: iluk level-of-fill"));
324 }
325
326 return ifpack1List;
327}
328
329template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
331 std::ostringstream out;
332 if (s_ != Teuchos::null) {
333 out << s_->description();
334 } else {
336 out << "{type = " << type_ << "}";
337 }
338 return out.str();
339}
340
341template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
342void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::print(Teuchos::FancyOStream& out, const VerbLevel verbLevel) const {
344
345 if (verbLevel & Parameters0)
346 out0 << "Prec. type: " << type_ << std::endl;
347
348 if (verbLevel & Parameters1) {
349 out0 << "PrecType: " << type_ << std::endl;
350 out0 << "Parameter list: " << std::endl;
351 Teuchos::OSTab tab2(out);
352 out << this->GetParameterList();
353 out0 << "Overlap: " << overlap_ << std::endl;
354 }
355
356 if (verbLevel & Debug) {
357 out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl
358 << "-" << std::endl
359 << "Epetra PrecType: " << Ifpack2ToIfpack1Type(type_) << std::endl
360 << "Epetra Parameter list: " << std::endl;
361 Teuchos::OSTab tab2(out);
362 out << Ifpack2ToIfpack1Param(this->GetParameterList());
363 ;
364 }
365}
366
367} // namespace MueLu
368
369#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)