MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_Details_LinearSolverFactory_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
13
14#ifndef MUELU_DETAILS_LINEARSOLVERFACTORY_DEF_HPP
15#define MUELU_DETAILS_LINEARSOLVERFACTORY_DEF_HPP
16
17#include "MueLu_config.hpp"
18#include "Trilinos_Details_LinearSolver.hpp"
19#include "Trilinos_Details_LinearSolverFactory.hpp"
20#include <type_traits>
21
22#include "Tpetra_Operator.hpp"
24
25namespace MueLu {
26namespace Details {
27
28template <class MV, class OP, class NormType>
29class LinearSolver : public Trilinos::Details::LinearSolver<MV, OP, NormType>,
30 virtual public Teuchos::Describable {
31 public:
34
36 virtual ~LinearSolver() {}
37
42 void setMatrix(const Teuchos::RCP<const OP>& A);
43
45 Teuchos::RCP<const OP> getMatrix() const {
46 return A_;
47 }
48
50 void solve(MV& X, const MV& B);
51
53 void setParameters(const Teuchos::RCP<Teuchos::ParameterList>& params);
54
57 void symbolic() {}
58
61 void numeric();
62
64 std::string description() const;
65
67 void
68 describe(Teuchos::FancyOStream& out,
69 const Teuchos::EVerbosityLevel verbLevel =
70 Teuchos::Describable::verbLevel_default) const;
71
72 private:
73 Teuchos::RCP<const OP> A_;
74 Teuchos::RCP<Teuchos::ParameterList> params_;
75};
76
77// Why does MueLu_EpetraOperator insist on HAVE_MUELU_SERIAL?
78#if defined(HAVE_MUELU_SERIAL) and defined(HAVE_MUELU_EPETRA)
79template <>
80class LinearSolver<Epetra_MultiVector, Epetra_Operator, double> : public Trilinos::Details::LinearSolver<Epetra_MultiVector, Epetra_Operator, double>,
81 virtual public Teuchos::Describable {
82 public:
85 : changedA_(false)
86 , changedParams_(false) {}
87
89 virtual ~LinearSolver() {}
90
95 void setMatrix(const Teuchos::RCP<const Epetra_Operator>& A) {
96 const char prefix[] = "MueLu::Details::LinearSolver::setMatrix: ";
97
98 if (A != A_) {
99 if (solver_ != Teuchos::null)
100 changedA_ = true;
101
102 A_ = rcp_dynamic_cast<const Epetra_CrsMatrix>(A);
103 TEUCHOS_TEST_FOR_EXCEPTION(A_.is_null(), std::runtime_error, prefix << "MueLu requires "
104 "an Epetra_CrsMatrix, but the matrix you provided is of a "
105 "different type. Please provide an Epetra_CrsMatrix instead.");
106 }
107 }
108
110 Teuchos::RCP<const Epetra_Operator> getMatrix() const {
111 return A_;
112 }
113
115 void solve(Epetra_MultiVector& X, const Epetra_MultiVector& B) {
116 // TODO amk: Do we assume the user has called numeric before solve, or should we call it for them?
117 const char prefix[] = "MueLu::Details::LinearSolver::solve: ";
118 TEUCHOS_TEST_FOR_EXCEPTION(solver_.is_null(), std::runtime_error, prefix << "The solver does not "
119 "exist yet. You must call numeric() before you may call this method.");
120 TEUCHOS_TEST_FOR_EXCEPTION(changedA_, std::runtime_error, prefix << "The matrix A has been reset "
121 "since the last call to numeric(). Please call numeric() again.");
122 TEUCHOS_TEST_FOR_EXCEPTION(changedParams_, std::runtime_error, prefix << "The parameters have been reset "
123 "since the last call to numeric(). Please call numeric() again.");
124
125 int err = solver_->ApplyInverse(B, X);
126
127 TEUCHOS_TEST_FOR_EXCEPTION(err != 0, std::runtime_error, prefix << "EpetraOperator::ApplyInverse returned "
128 "nonzero error code "
129 << err);
130 }
131
133 void setParameters(const Teuchos::RCP<Teuchos::ParameterList>& params) {
134 if (solver_ != Teuchos::null && params != params_)
135 changedParams_ = true;
136
137 params_ = params;
138 }
139
142 void symbolic() {}
143
146 void numeric() {
147 const char prefix[] = "MueLu::Details::LinearSolver::numeric: ";
148
149 // If the solver is up-to-date, leave it alone
150 if (solver_ == Teuchos::null || changedA_ || changedParams_) {
151 changedA_ = false;
152 changedParams_ = false;
153
154 TEUCHOS_TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
155 "set yet. You must call setMatrix() with a nonnull matrix before you may "
156 "call this method.");
157
158 // TODO: We should not have to cast away the constness here
159 // TODO: See bug 6462
160 if (params_ != Teuchos::null)
161 solver_ = CreateEpetraPreconditioner(rcp_const_cast<Epetra_CrsMatrix>(A_), *params_);
162 else
163 solver_ = CreateEpetraPreconditioner(rcp_const_cast<Epetra_CrsMatrix>(A_));
164 }
165 }
166
168 std::string description() const {
169 if (solver_.is_null()) {
170 return "\"MueLu::Details::LinearSolver\": {MV: Epetra_MultiVector, OP: Epetra_Operator, NormType: double}";
171 } else {
172 return solver_->GetHierarchy()->description();
173 }
174 }
175
177 void
178 describe(Teuchos::FancyOStream& out,
179 const Teuchos::EVerbosityLevel verbLevel =
180 Teuchos::Describable::verbLevel_default) const {
181 using std::endl;
182 if (solver_.is_null()) {
183 if (verbLevel > Teuchos::VERB_NONE) {
184 Teuchos::OSTab tab0(out);
185 out << "\"MueLu::Details::LinearSolver\":" << endl;
186 Teuchos::OSTab tab1(out);
187 out << "MV: Epetra_MultiVector" << endl
188 << "OP: Epetra_Operator" << endl
189 << "NormType: double" << endl;
190 }
191 } else {
192 solver_->GetHierarchy()->describe(out, verbLevel);
193 }
194 }
195
196 private:
197 Teuchos::RCP<const Epetra_CrsMatrix> A_;
198 Teuchos::RCP<Teuchos::ParameterList> params_;
199 Teuchos::RCP<EpetraOperator> solver_;
200 bool changedA_;
201 bool changedParams_;
202};
203#endif // HAVE_MUELU_EPETRA
204
205template <class Scalar, class LO, class GO, class Node>
206class LinearSolver<Tpetra::MultiVector<Scalar, LO, GO, Node>,
207 Tpetra::Operator<Scalar, LO, GO, Node>,
208 typename Teuchos::ScalarTraits<Scalar>::magnitudeType> : public Trilinos::Details::LinearSolver<Tpetra::MultiVector<Scalar, LO, GO, Node>,
209 Tpetra::Operator<Scalar, LO, GO, Node>,
210 typename Teuchos::ScalarTraits<Scalar>::magnitudeType>,
211 virtual public Teuchos::Describable {
212 public:
215 : changedA_(false)
216 , changedParams_(false) {}
217
219 virtual ~LinearSolver() {}
220
225 void setMatrix(const Teuchos::RCP<const Tpetra::Operator<Scalar, LO, GO, Node> >& A) {
226 if (A != A_) {
227 if (solver_ != Teuchos::null)
228 changedA_ = true;
229
230 A_ = A;
231 }
232 }
233
235 Teuchos::RCP<const Tpetra::Operator<Scalar, LO, GO, Node> > getMatrix() const {
236 return A_;
237 }
238
240 void solve(Tpetra::MultiVector<Scalar, LO, GO, Node>& X, const Tpetra::MultiVector<Scalar, LO, GO, Node>& B) {
241 // TODO amk: Do we assume the user has called numeric before solve, or should we call it for them?
242 const char prefix[] = "MueLu::Details::LinearSolver::solve: ";
243 TEUCHOS_TEST_FOR_EXCEPTION(solver_.is_null(), std::runtime_error, prefix << "The solver does not "
244 "exist yet. You must call numeric() before you may call this method.");
245 TEUCHOS_TEST_FOR_EXCEPTION(changedA_, std::runtime_error, prefix << "The matrix A has been reset "
246 "since the last call to numeric(). Please call numeric() again.");
247 TEUCHOS_TEST_FOR_EXCEPTION(changedParams_, std::runtime_error, prefix << "The parameters have been reset "
248 "since the last call to numeric(). Please call numeric() again.");
249
250 solver_->apply(B, X);
251 }
252
254 void setParameters(const Teuchos::RCP<Teuchos::ParameterList>& params) {
255 if (solver_ != Teuchos::null && params != params_)
256 changedParams_ = true;
257
258 params_ = params;
259 }
260
263 void symbolic() {}
264
267 void numeric() {
268 const char prefix[] = "MueLu::Details::LinearSolver::numeric: ";
269
270 // If the solver is up-to-date, leave it alone
271 if (solver_ == Teuchos::null || changedParams_) {
272 TEUCHOS_TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
273 "set yet. You must call setMatrix() with a nonnull matrix before you may "
274 "call this method.");
275
276 // TODO: We should not have to cast away the constness here
277 // TODO: See bug 6462
278 if (params_ != Teuchos::null)
279 solver_ = CreateTpetraPreconditioner(rcp_const_cast<Tpetra::Operator<Scalar, LO, GO, Node> >(A_), *params_);
280 else
281 solver_ = CreateTpetraPreconditioner(rcp_const_cast<Tpetra::Operator<Scalar, LO, GO, Node> >(A_));
282 } else if (changedA_) {
283 TEUCHOS_TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
284 "set yet. You must call setMatrix() with a nonnull matrix before you may "
285 "call this method.");
286
287 // TODO: We should not have to cast away the constness here
288 // TODO: See bug 6462
289 RCP<const Tpetra::CrsMatrix<Scalar, LO, GO, Node> > helperMat;
290 helperMat = rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar, LO, GO, Node> >(A_);
291 TEUCHOS_TEST_FOR_EXCEPTION(helperMat.is_null(), std::runtime_error, prefix << "MueLu requires "
292 "a Tpetra::CrsMatrix, but the matrix you provided is of a "
293 "different type. Please provide a Tpetra::CrsMatrix instead.");
294 ReuseTpetraPreconditioner(rcp_const_cast<Tpetra::CrsMatrix<Scalar, LO, GO, Node> >(helperMat), *solver_);
295 }
296
297 changedA_ = false;
298 changedParams_ = false;
299 }
300
302 std::string description() const {
303 using Teuchos::TypeNameTraits;
304 if (solver_.is_null()) {
305 std::ostringstream os;
306 os << "\"MueLu::Details::LinearSolver\": {"
307 << "MV: " << TypeNameTraits<Tpetra::MultiVector<Scalar, LO, GO, Node> >::name()
308 << "OP: " << TypeNameTraits<Tpetra::Operator<Scalar, LO, GO, Node> >::name()
309 << "NormType: " << TypeNameTraits<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>::name()
310 << "}";
311 return os.str();
312 } else {
313 return solver_->GetHierarchy()->description();
314 }
315 }
316
318 void
319 describe(Teuchos::FancyOStream& out,
320 const Teuchos::EVerbosityLevel verbLevel =
321 Teuchos::Describable::verbLevel_default) const {
322 using std::endl;
323 using Teuchos::TypeNameTraits;
324 if (solver_.is_null()) {
325 if (verbLevel > Teuchos::VERB_NONE) {
326 Teuchos::OSTab tab0(out);
327 out << "\"MueLu::Details::LinearSolver\":" << endl;
328 Teuchos::OSTab tab1(out);
329 out << "MV: " << TypeNameTraits<Tpetra::MultiVector<Scalar, LO, GO, Node> >::name() << endl
330 << "OP: " << TypeNameTraits<Tpetra::Operator<Scalar, LO, GO, Node> >::name() << endl
331 << "NormType: " << TypeNameTraits<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>::name() << endl;
332 }
333 } else {
334 solver_->GetHierarchy()->describe(out, verbLevel);
335 }
336 }
337
338 private:
339 Teuchos::RCP<const Tpetra::Operator<Scalar, LO, GO, Node> > A_;
340 Teuchos::RCP<Teuchos::ParameterList> params_;
341 Teuchos::RCP<TpetraOperator<Scalar, LO, GO, Node> > solver_;
344};
345
346template <class MV, class OP, class NormType>
347Teuchos::RCP<Trilinos::Details::LinearSolver<MV, OP, NormType> >
349 getLinearSolver(const std::string& solverName) {
350 using Teuchos::rcp;
352}
353
354template <class MV, class OP, class NormType>
357#ifdef HAVE_TEUCHOSCORE_CXX11
358 typedef std::shared_ptr<MueLu::Details::LinearSolverFactory<MV, OP, NormType> > ptr_type;
359 // typedef std::shared_ptr<Trilinos::Details::LinearSolverFactory<MV, OP> > base_ptr_type;
360#else
361 typedef Teuchos::RCP<MueLu::Details::LinearSolverFactory<MV, OP, NormType> > ptr_type;
362 // typedef Teuchos::RCP<Trilinos::Details::LinearSolverFactory<MV, OP> > base_ptr_type;
363#endif // HAVE_TEUCHOSCORE_CXX11
364
366 Trilinos::Details::registerLinearSolverFactory<MV, OP, NormType>("MueLu", factory);
367}
368
369} // namespace Details
370} // namespace MueLu
371
372// Macro for doing explicit instantiation of
373// MueLu::Details::LinearSolverFactory, for Tpetra objects, with
374// given Tpetra template parameters (SC = Scalar, LO = LocalOrdinal,
375// GO = GlobalOrdinal, NT = Node).
376//
377// We don't have to protect use of Tpetra objects here, or include
378// any header files for them, because this is a macro definition.
379#define MUELU_DETAILS_LINEARSOLVERFACTORY_INSTANT(SC, LO, GO, NT) \
380 template class MueLu::Details::LinearSolverFactory<Tpetra::MultiVector<SC, LO, GO, NT>, \
381 Tpetra::Operator<SC, LO, GO, NT>, \
382 typename Tpetra::MultiVector<SC, LO, GO, NT>::mag_type>;
383
384#endif // MUELU_DETAILS_LINEARSOLVERFACTORY_DEF_HPP
Various adapters that will create a MueLu preconditioner that is a Tpetra::Operator.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Implementation of Teuchos::Describable::describe.
void solve(Tpetra::MultiVector< Scalar, LO, GO, Node > &X, const Tpetra::MultiVector< Scalar, LO, GO, Node > &B)
Solve the linear system(s) AX=B.
Interface for a "factory" that creates MueLu solvers.
static void registerLinearSolverFactory()
Register this LinearSolverFactory with the central registry.
virtual Teuchos::RCP< Trilinos::Details::LinearSolver< MV, OP, NormType > > getLinearSolver(const std::string &solverName)
Get an instance of a MueLu solver.
Teuchos::RCP< Teuchos::ParameterList > params_
std::string description() const
Implementation of Teuchos::Describable::description.
void symbolic()
Set up any part of the solve that depends on the structure of the input matrix, but not its numerical...
virtual ~LinearSolver()
Destructor (virtual for memory safety).
Teuchos::RCP< const OP > getMatrix() const
Get a pointer to this Solver's matrix.
void setParameters(const Teuchos::RCP< Teuchos::ParameterList > &params)
Set this solver's parameters.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Implementation of Teuchos::Describable::describe.
void solve(MV &X, const MV &B)
Solve the linear system(s) AX=B.
void numeric()
Set up any part of the solve that depends on both the structure and the numerical values of the input...
void setMatrix(const Teuchos::RCP< const OP > &A)
Set the Solver's matrix.
Namespace for MueLu classes and methods.
Teuchos::RCP< MueLu::TpetraOperator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > CreateTpetraPreconditioner(const Teuchos::RCP< Tpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &inA, Teuchos::ParameterList &inParamList)
Helper function to create a MueLu or AMGX preconditioner that can be used by Tpetra....
void ReuseTpetraPreconditioner(const Teuchos::RCP< Tpetra::CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &inA, MueLu::TpetraOperator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op)
Helper function to reuse an existing MueLu preconditioner.