MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_DirectSolver_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_DIRECTSOLVER_DEF_HPP
11#define MUELU_DIRECTSOLVER_DEF_HPP
12
13#include <Xpetra_Utils.hpp>
14#include <Xpetra_Matrix.hpp>
15
17
18#include "MueLu_Exceptions.hpp"
19#include "MueLu_Level.hpp"
20
21#include "MueLu_Amesos2Smoother.hpp"
22#include "MueLu_BelosSmoother.hpp"
23#include "MueLu_StratimikosSmoother.hpp"
24#include "MueLu_RefMaxwellSmoother.hpp"
25
26namespace MueLu {
27
28template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
29DirectSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::DirectSolver(const std::string& type, const Teuchos::ParameterList& paramListIn)
30 : type_(type) {
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 sTpetra_ = Teuchos::null;
39 sBelos_ = Teuchos::null;
40
41 ParameterList paramList = paramListIn;
42
43 // We want DirectSolver to be able to work with both Epetra and Tpetra objects, therefore we try to construct both
44 // Amesos and Amesos2 solver prototypes. The construction really depends on configuration options.
45 triedTpetra_ = false;
46 try {
47 sTpetra_ = rcp(new Amesos2Smoother(type_, paramList));
48 if (sTpetra_.is_null())
49 errorTpetra_ = "Unable to construct Amesos2 direct solver";
50 else if (!sTpetra_->constructionSuccessful()) {
51 errorTpetra_ = sTpetra_->constructionErrorMsg();
52 sTpetra_ = Teuchos::null;
53 }
54 } catch (Exceptions::RuntimeError& e) {
55 errorTpetra_ = e.what();
56 } catch (Exceptions::BadCast& e) {
57 errorTpetra_ = e.what();
58 } catch (Teuchos::Exceptions::InvalidParameterName& e) {
59 errorTpetra_ = e.what();
60 }
61 triedTpetra_ = true;
62#if defined(HAVE_MUELU_BELOS)
63 try {
64 sBelos_ = rcp(new BelosSmoother(type_, paramList));
65 if (sBelos_.is_null())
66 errorBelos_ = "Unable to construct Belos solver";
67 else if (!sBelos_->constructionSuccessful()) {
68 errorBelos_ = sBelos_->constructionErrorMsg();
69 sBelos_ = Teuchos::null;
70 }
71 } catch (Exceptions::RuntimeError& e) {
72 errorBelos_ = e.what();
73 } catch (Exceptions::BadCast& e) {
74 errorBelos_ = e.what();
75 }
76 triedBelos_ = true;
77#endif
78#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
79 try {
80 sStratimikos_ = rcp(new StratimikosSmoother(type_, paramList));
81 if (sStratimikos_.is_null())
82 errorStratimikos_ = "Unable to construct Stratimikos smoother";
83 else if (!sStratimikos_->constructionSuccessful()) {
84 errorStratimikos_ = sStratimikos_->constructionErrorMsg();
85 sStratimikos_ = Teuchos::null;
86 }
87 } catch (Exceptions::RuntimeError& e) {
88 errorStratimikos_ = e.what();
89 }
90 triedStratimikos_ = true;
91#endif
92 try {
93 sRefMaxwell_ = rcp(new RefMaxwellSmoother(type_, paramList));
94 if (sRefMaxwell_.is_null())
95 errorRefMaxwell_ = "Unable to construct RefMaxwell smoother";
96 else if (!sRefMaxwell_->constructionSuccessful()) {
97 errorRefMaxwell_ = sRefMaxwell_->constructionErrorMsg();
98 sRefMaxwell_ = Teuchos::null;
99 }
100 } catch (Exceptions::RuntimeError& e) {
101 errorRefMaxwell_ = e.what();
102 }
103 triedRefMaxwell_ = true;
104
105 // Check if we were able to construct at least one solver. In many cases that's all we need, for instance if a user
106 // simply wants to use Tpetra only stack, never enables Amesos, and always runs Tpetra objects.
108 "Unable to construct any direct solver.");
109
110 TEUCHOS_TEST_FOR_EXCEPTION(sTpetra_.is_null() && sBelos_.is_null() && sStratimikos_.is_null() && sRefMaxwell_.is_null(), Exceptions::RuntimeError,
111 "Could not enable any direct solver:\n"
112 << (triedTpetra_ ? "Tpetra mode was disabled due to an error:\n" : "")
113 << (triedTpetra_ ? errorTpetra_ : "")
114 << (triedBelos_ ? "Belos was disabled due to an error:\n" : "")
115 << (triedBelos_ ? errorBelos_ : "")
116 << (triedStratimikos_ ? "Stratimikos was disabled due to an error:\n" : "")
118 << (triedRefMaxwell_ ? "RefMaxwell was disabled due to an error:\n" : "")
120 ;
121
122 this->SetParameterList(paramList);
123}
124
125template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
126void DirectSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetFactory(const std::string& varName, const RCP<const FactoryBase>& factory) {
127 // We need to propagate SetFactory to proper place
128 if (!sTpetra_.is_null()) sTpetra_->SetFactory(varName, factory);
129 if (!sBelos_.is_null()) sBelos_->SetFactory(varName, factory);
130 if (!sStratimikos_.is_null()) sStratimikos_->SetFactory(varName, factory);
131 if (!sRefMaxwell_.is_null()) sRefMaxwell_->SetFactory(varName, factory);
132}
133
134template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
136 if (!sBelos_.is_null())
137 s_ = sBelos_;
138 else if (!sStratimikos_.is_null())
140 else if (!sRefMaxwell_.is_null())
142 else {
143 s_ = sTpetra_;
144 }
145 if (s_.is_null()) {
146 if (triedBelos_)
147 this->GetOStream(Errors) << "Belos mode was disabled due to an error:\n"
148 << errorBelos_ << std::endl;
150 this->GetOStream(Errors) << "Stratimikos mode was disabled due to an error:\n"
151 << errorStratimikos_ << std::endl;
153 this->GetOStream(Errors) << "RefMaxwell mode was disabled due to an error:\n"
154 << errorRefMaxwell_ << std::endl;
155 if (triedTpetra_)
156 this->GetOStream(Errors) << "Tpetra mode was disabled due to an error:\n"
157 << errorTpetra_ << std::endl;
158
159 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError,
160 "Direct solver was not constructed");
161 }
162
163 s_->DeclareInput(currentLevel);
164}
165
166template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
168 if (SmootherPrototype::IsSetup() == true)
169 this->GetOStream(Warnings0) << "MueLu::DirectSolver::Setup(): Setup() has already been called" << std::endl;
170
171 int oldRank = s_->SetProcRankVerbose(this->GetProcRankVerbose());
172
173 s_->Setup(currentLevel);
174
175 s_->SetProcRankVerbose(oldRank);
176
178
179 this->SetParameterList(s_->GetParameterList());
180}
181
182template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
183void DirectSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector& X, const MultiVector& B, bool InitialGuessIsZero) const {
184 TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::AmesosSmoother::Apply(): Setup() has not been called");
185
186 s_->Apply(X, B, InitialGuessIsZero);
187}
188
189template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
190RCP<MueLu::SmootherPrototype<Scalar, LocalOrdinal, GlobalOrdinal, Node> > DirectSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Copy() const {
191 RCP<DirectSolver> newSmoo = rcp(new DirectSolver(*this));
192
193 // We need to be quite careful with Copy
194 // We still want DirectSolver to follow Prototype Pattern, so we need to hide the fact that we do have some state
195 if (!sTpetra_.is_null())
196 newSmoo->sTpetra_ = sTpetra_->Copy();
197 if (!sBelos_.is_null())
198 newSmoo->sBelos_ = sBelos_->Copy();
199 if (!sStratimikos_.is_null())
200 newSmoo->sStratimikos_ = sStratimikos_->Copy();
201 if (!sRefMaxwell_.is_null())
202 newSmoo->sRefMaxwell_ = sRefMaxwell_->Copy();
203
204 // Copy the default mode
205 if (s_.get() == sBelos_.get())
206 newSmoo->s_ = newSmoo->sBelos_;
207 else if (s_.get() == sStratimikos_.get())
208 newSmoo->s_ = newSmoo->sStratimikos_;
209 else if (s_.get() == sRefMaxwell_.get())
210 newSmoo->s_ = newSmoo->sRefMaxwell_;
211 else
212 newSmoo->s_ = newSmoo->sTpetra_;
213 newSmoo->SetParameterList(this->GetParameterList());
214
215 return newSmoo;
216}
217
218template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
220 std::ostringstream out;
221 if (s_ != Teuchos::null) {
222 out << s_->description();
223 } else {
225 out << "{type = " << type_ << "}";
226 }
227 return out.str();
228}
229
230template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
231void DirectSolver<Scalar, LocalOrdinal, GlobalOrdinal, Node>::print(Teuchos::FancyOStream& out, const VerbLevel verbLevel) const {
233
234 if (verbLevel & Parameters0)
235 out0 << "Prec. type: " << type_ << std::endl;
236
237 if (verbLevel & Parameters1) {
238 out0 << "Parameter list: " << std::endl;
239 Teuchos::OSTab tab3(out);
240 out << this->GetParameterList();
241 }
242
243 if (verbLevel & Debug)
244 out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl;
245}
246
247} // namespace MueLu
248
249#endif // MUELU_DIRECTSOLVER_DEF_HPP
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
Class that encapsulates Amesos2 direct solvers.
Class that encapsulates Belos smoothers.
virtual std::string description() const
Return a simple one-line description of this object.
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
void Apply(MultiVector &X, const MultiVector &B, bool InitialGuessIsZero=false) const
DirectSolver cannot be applied. Apply() always returns a RuntimeError exception.
std::string description() const
Return a simple one-line description of this object.
void Setup(Level &currentLevel)
DirectSolver cannot be turned into a smoother using Setup(). Setup() always returns a RuntimeError ex...
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Custom SetFactory.
RCP< SmootherPrototype > sBelos_
RCP< SmootherPrototype > sStratimikos_
RCP< SmootherPrototype > s_
RCP< SmootherPrototype > sRefMaxwell_
void DeclareInput(Level &currentLevel) const
Input.
RCP< SmootherPrototype > Copy() const
When this prototype is cloned using Copy(), the clone is an Amesos or an Amesos2 smoother.
std::string type_
amesos1/2-specific key phrase that denote smoother type
DirectSolver(const std::string &type="", const Teuchos::ParameterList &paramList=Teuchos::ParameterList())
Constructor Note: only parameters shared by Amesos and Amesos2 should be used for type and paramList ...
RCP< SmootherPrototype > sTpetra_
Smoother.
Exception indicating invalid cast attempted.
Exception throws to report errors in the internal logical of the program.
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.
virtual const Teuchos::ParameterList & GetParameterList() const
Class that encapsulates Operator smoothers.
bool IsSetup() const
Get the state of a smoother prototype.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
int GetProcRankVerbose() const
Get proc rank used for printing. Do not use this information for any other purpose....
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).