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())
139 s_ = sStratimikos_;
140 else if (!sRefMaxwell_.is_null())
141 s_ = sRefMaxwell_;
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;
149 if (triedStratimikos_)
150 this->GetOStream(Errors) << "Stratimikos mode was disabled due to an error:\n"
151 << errorStratimikos_ << std::endl;
152 if (triedRefMaxwell_)
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.
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
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 > 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.
Class that encapsulates Operator smoothers.
bool IsSetup() const
Get the state of a smoother prototype.
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)