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"
19#include "MueLu_Ifpack2Smoother.hpp"
20#include "MueLu_BelosSmoother.hpp"
21#include "MueLu_StratimikosSmoother.hpp"
22#include "MueLu_Exceptions.hpp"
23
24namespace MueLu {
25
26template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
27TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TrilinosSmoother(const std::string& type, const Teuchos::ParameterList& paramListIn, const LO& overlap)
28 : type_(type)
29 , overlap_(overlap) {
30 // The original idea behind all smoothers was to use prototype pattern. However, it does not fully work of the dependencies
31 // calculation. Particularly, we need to propagate DeclareInput to proper prototypes. Therefore, both TrilinosSmoother and
32 // DirectSolver do not follow the pattern exactly.
33 // The difference is that in order to propagate the calculation of dependencies, we need to call a DeclareInput on a
34 // constructed object (or objects, as we have two different code branches for Epetra and Tpetra). The only place where we
35 // could construct these objects is the constructor. Thus, we need to store RCPs, and both TrilinosSmoother and DirectSolver
36 // obtain a state: they contain RCP to smoother prototypes.
37 sTpetra_ = Teuchos::null;
38 sBelos_ = Teuchos::null;
39 sStratimikos_ = Teuchos::null;
40
41 TEUCHOS_TEST_FOR_EXCEPTION(overlap_ < 0, Exceptions::RuntimeError, "Overlap parameter is negative (" << overlap << ")");
42
43 // paramList contains only parameters which are understood by Ifpack/Ifpack2
44 ParameterList paramList = paramListIn;
45
46 // We want TrilinosSmoother to be able to work with both Epetra and Tpetra objects, therefore we try to construct both
47 // Ifpack and Ifpack2 smoother prototypes. The construction really depends on configuration options.
49 try {
50 sTpetra_ = rcp(new Ifpack2Smoother(type_, paramList, overlap_));
51 if (sTpetra_.is_null())
52 errorTpetra_ = "Unable to construct Ifpack2 smoother";
53 else if (!sTpetra_->constructionSuccessful()) {
54 errorTpetra_ = sTpetra_->constructionErrorMsg();
55 sTpetra_ = Teuchos::null;
56 }
57 } catch (Exceptions::RuntimeError& e) {
58 errorTpetra_ = e.what();
59 } catch (Exceptions::BadCast& e) {
60 errorTpetra_ = e.what();
61 } catch (Teuchos::Exceptions::InvalidParameterName& e) {
62 errorTpetra_ = e.what();
63 }
64 triedTpetra_ = true;
65#if defined(HAVE_MUELU_BELOS)
66 try {
67 sBelos_ = rcp(new BelosSmoother(type_, paramList));
68 if (sBelos_.is_null())
69 errorBelos_ = "Unable to construct Belos smoother";
70 else if (!sBelos_->constructionSuccessful()) {
71 errorBelos_ = sBelos_->constructionErrorMsg();
72 sBelos_ = Teuchos::null;
73 }
74 } catch (Exceptions::RuntimeError& e) {
75 errorBelos_ = e.what();
76 } catch (Exceptions::BadCast& e) {
77 errorBelos_ = e.what();
78 }
79 triedBelos_ = true;
80#endif
81#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
82 try {
83 sStratimikos_ = rcp(new StratimikosSmoother(type_, paramList));
84 if (sStratimikos_.is_null())
85 errorStratimikos_ = "Unable to construct Stratimikos smoother";
86 else if (!sStratimikos_->constructionSuccessful()) {
87 errorStratimikos_ = sStratimikos_->constructionErrorMsg();
88 sStratimikos_ = Teuchos::null;
89 }
90 } catch (Exceptions::RuntimeError& e) {
91 errorStratimikos_ = e.what();
92 }
93 triedStratimikos_ = true;
94#endif
95
96 // Check if we were able to construct at least one smoother. In many cases that's all we need, for instance if a user
97 // simply wants to use Tpetra only stack, never enables Ifpack, and always runs Tpetra objects.
98 TEUCHOS_TEST_FOR_EXCEPTION(!triedTpetra_ && !triedBelos_ && !triedStratimikos_, Exceptions::RuntimeError,
99 "Unable to construct any smoother.");
100
101 TEUCHOS_TEST_FOR_EXCEPTION(sTpetra_.is_null() && sBelos_.is_null() && sStratimikos_.is_null(), Exceptions::RuntimeError,
102 "Could not construct any smoother:\n"
103 << (triedTpetra_ ? "=> Failed to build a Tpetra smoother due to the following exception:\n" : "=> Tpetra and/or Ifpack2 are not enabled.\n")
104 << (triedTpetra_ ? errorTpetra_ + "\n" : "")
105 << (triedBelos_ ? "=> Failed to build a Belos smoother due to the following exception:\n" : "=> Belos not enabled.\n")
106 << (triedBelos_ ? errorBelos_ + "\n" : "")
107 << (triedStratimikos_ ? "=> Failed to build a Stratimikos smoother due to the following exception:\n" : "=> Stratimikos not enabled.\n")
108 << (triedStratimikos_ ? errorStratimikos_ + "\n" : ""));
109
110 this->SetParameterList(paramList);
111}
112
113template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
114void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetFactory(const std::string& varName, const RCP<const FactoryBase>& factory) {
115 // We need to propagate SetFactory to proper place
116 if (!sTpetra_.is_null()) sTpetra_->SetFactory(varName, factory);
117 if (!sBelos_.is_null()) sBelos_->SetFactory(varName, factory);
118 if (!sStratimikos_.is_null()) sStratimikos_->SetFactory(varName, factory);
119}
120
121template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
123 if (!sBelos_.is_null())
124 s_ = sBelos_;
125 else if (!sStratimikos_.is_null())
126 s_ = sStratimikos_;
127 else {
128 s_ = sTpetra_;
129 }
130 if (s_.is_null()) {
131 if (triedBelos_)
132 this->GetOStream(Errors) << "Belos was disabled due to an error:\n"
133 << errorBelos_ << std::endl;
134 if (triedStratimikos_)
135 this->GetOStream(Errors) << "Stratimikos was disabled due to an error:\n"
136 << errorStratimikos_ << std::endl;
137 if (triedTpetra_)
138 this->GetOStream(Errors) << "Tpetra mode was disabled due to an error:\n"
139 << errorTpetra_ << std::endl;
140 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError,
141 "Smoother was not constructed");
142 }
143
144 s_->DeclareInput(currentLevel);
145}
146
147template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
149 if (SmootherPrototype::IsSetup() == true)
150 this->GetOStream(Warnings0) << "MueLu::TrilinosSmoother::Setup(): Setup() has already been called" << std::endl;
151
152 int oldRank = s_->SetProcRankVerbose(this->GetProcRankVerbose());
153
154 s_->Setup(currentLevel);
155
156 s_->SetProcRankVerbose(oldRank);
157
159
160 this->SetParameterList(s_->GetParameterList());
161}
162
163template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
164void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector& X, const MultiVector& B, bool InitialGuessIsZero) const {
165 TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::TrilinosSmoother::Apply(): Setup() has not been called");
166
167 s_->Apply(X, B, InitialGuessIsZero);
168}
169
170template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
171RCP<MueLu::SmootherPrototype<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
173 RCP<TrilinosSmoother> newSmoo = rcp(new TrilinosSmoother(type_, this->GetParameterList(), overlap_));
174
175 // We need to be quite careful with Copy
176 // We still want TrilinosSmoother to follow Prototype Pattern, so we need to hide the fact that we do have some state
177 if (!sTpetra_.is_null())
178 newSmoo->sTpetra_ = sTpetra_->Copy();
179 if (!sBelos_.is_null())
180 newSmoo->sBelos_ = sBelos_->Copy();
181 if (!sStratimikos_.is_null())
182 newSmoo->sStratimikos_ = sStratimikos_->Copy();
183
184 // Copy the default mode
185 if (s_.get() == sBelos_.get())
186 newSmoo->s_ = newSmoo->sBelos_;
187 else if (s_.get() == sStratimikos_.get())
188 newSmoo->s_ = newSmoo->sStratimikos_;
189 else
190 newSmoo->s_ = newSmoo->sTpetra_;
191
192 newSmoo->SetParameterList(this->GetParameterList());
193
194 return newSmoo;
195}
196
197template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
199 if (type == "RELAXATION") {
200 return "point relaxation stand-alone";
201 }
202 if (type == "CHEBYSHEV") {
203 return "Chebyshev";
204 }
205 if (type == "ILUT") {
206 return "ILUT";
207 }
208 if (type == "RILUK") {
209 return "ILU";
210 }
211 if (type == "ILU") {
212 return "ILU";
213 }
214 if (type == "Amesos") {
215 return "Amesos";
216 }
217
218 // special types
219
220 // Note: for Ifpack there is no distinction between block and banded relaxation as there is no
221 // BandedContainer or TridiagonalContainer.
222 if (type == "LINESMOOTHING_BLOCKRELAXATION") {
223 return "LINESMOOTHING_BLOCKRELAXATION";
224 }
225 if (type == "LINESMOOTHING_BLOCK RELAXATION") {
226 return "LINESMOOTHING_BLOCKRELAXATION";
227 }
228 if (type == "LINESMOOTHING_BLOCK_RELAXATION") {
229 return "LINESMOOTHING_BLOCKRELAXATION";
230 }
231 if (type == "LINESMOOTHING_BANDEDRELAXATION") {
232 return "LINESMOOTHING_BLOCKRELAXATION";
233 }
234 if (type == "LINESMOOTHING_BANDED RELAXATION") {
235 return "LINESMOOTHING_BLOCKRELAXATION";
236 }
237 if (type == "LINESMOOTHING_BANDED_RELAXATION") {
238 return "LINESMOOTHING_BLOCKRELAXATION";
239 }
240 if (type == "LINESMOOTHING_TRIDIRELAXATION") {
241 return "LINESMOOTHING_BLOCKRELAXATION";
242 }
243 if (type == "LINESMOOTHING_TRIDI RELAXATION") {
244 return "LINESMOOTHING_BLOCKRELAXATION";
245 }
246 if (type == "LINESMOOTHING_TRIDI_RELAXATION") {
247 return "LINESMOOTHING_BLOCKRELAXATION";
248 }
249 if (type == "LINESMOOTHING_TRIDIAGONALRELAXATION") {
250 return "LINESMOOTHING_BLOCKRELAXATION";
251 }
252 if (type == "LINESMOOTHING_TRIDIAGONAL RELAXATION") {
253 return "LINESMOOTHING_BLOCKRELAXATION";
254 }
255 if (type == "LINESMOOTHING_TRIDIAGONAL_RELAXATION") {
256 return "LINESMOOTHING_BLOCKRELAXATION";
257 }
258 if (type == "AGGREGATE") {
259 return "AGGREGATE";
260 }
261 if (type == "BLOCK_RELAXATION" ||
262 type == "BLOCK RELAXATION" ||
263 type == "BLOCKRELAXATION" ||
264 // Banded
265 type == "BANDED_RELAXATION" ||
266 type == "BANDED RELAXATION" ||
267 type == "BANDEDRELAXATION" ||
268 // Tridiagonal
269 type == "TRIDI_RELAXATION" ||
270 type == "TRIDI RELAXATION" ||
271 type == "TRIDIRELAXATION" ||
272 type == "TRIDIAGONAL_RELAXATION" ||
273 type == "TRIDIAGONAL RELAXATION" ||
274 type == "TRIDIAGONALRELAXATION") {
275 return "block relaxation stand-alone";
276 }
277
278 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Cannot convert Ifpack2 preconditioner name to Ifpack: unknown type: \"" + type + "\"");
279}
280
281template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
282Teuchos::ParameterList TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Ifpack2ToIfpack1Param(const Teuchos::ParameterList& ifpack2List) {
283 Teuchos::ParameterList ifpack1List = ifpack2List;
284
285 if (ifpack2List.isParameter("relaxation: type") && ifpack2List.get<std::string>("relaxation: type") == "Symmetric Gauss-Seidel")
286 ifpack1List.set("relaxation: type", "symmetric Gauss-Seidel");
287
288 if (ifpack2List.isParameter("fact: iluk level-of-fill")) {
289 ifpack1List.remove("fact: iluk level-of-fill");
290 ifpack1List.set("fact: level-of-fill", ifpack2List.get<int>("fact: iluk level-of-fill"));
291 }
292
293 return ifpack1List;
294}
295
296template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
298 std::ostringstream out;
299 if (s_ != Teuchos::null) {
300 out << s_->description();
301 } else {
303 out << "{type = " << type_ << "}";
304 }
305 return out.str();
306}
307
308template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
309void TrilinosSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::print(Teuchos::FancyOStream& out, const VerbLevel verbLevel) const {
311
312 if (verbLevel & Parameters0)
313 out0 << "Prec. type: " << type_ << std::endl;
314
315 if (verbLevel & Parameters1) {
316 out0 << "PrecType: " << type_ << std::endl;
317 out0 << "Parameter list: " << std::endl;
318 Teuchos::OSTab tab2(out);
319 out << this->GetParameterList();
320 out0 << "Overlap: " << overlap_ << std::endl;
321 }
322
323 if (verbLevel & Debug) {
324 out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl;
325 }
326}
327
328} // namespace MueLu
329
330#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.
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.
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.
RCP< SmootherPrototype > sTpetra_
Smoother.
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)