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#ifdef HAVE_MUELU_EPETRA
23#include "Epetra_CrsMatrix.h"
25#endif // HAVE_MUELU_EPETRA
26
27#include "Tpetra_Operator.hpp"
29
30namespace MueLu {
31namespace Details {
32
33template <class MV, class OP, class NormType>
34class LinearSolver : public Trilinos::Details::LinearSolver<MV, OP, NormType>,
35 virtual public Teuchos::Describable {
36 public:
39
41 virtual ~LinearSolver() {}
42
47 void setMatrix(const Teuchos::RCP<const OP>& A);
48
50 Teuchos::RCP<const OP> getMatrix() const {
51 return A_;
52 }
53
55 void solve(MV& X, const MV& B);
56
58 void setParameters(const Teuchos::RCP<Teuchos::ParameterList>& params);
59
62 void symbolic() {}
63
66 void numeric();
67
69 std::string description() const;
70
72 void
73 describe(Teuchos::FancyOStream& out,
74 const Teuchos::EVerbosityLevel verbLevel =
75 Teuchos::Describable::verbLevel_default) const;
76
77 private:
78 Teuchos::RCP<const OP> A_;
79 Teuchos::RCP<Teuchos::ParameterList> params_;
80};
81
82// Why does MueLu_EpetraOperator insist on HAVE_MUELU_SERIAL?
83#if defined(HAVE_MUELU_SERIAL) and defined(HAVE_MUELU_EPETRA)
84template <>
85class LinearSolver<Epetra_MultiVector, Epetra_Operator, double> : public Trilinos::Details::LinearSolver<Epetra_MultiVector, Epetra_Operator, double>,
86 virtual public Teuchos::Describable {
87 public:
90 : changedA_(false)
91 , changedParams_(false) {}
92
94 virtual ~LinearSolver() {}
95
100 void setMatrix(const Teuchos::RCP<const Epetra_Operator>& A) {
101 const char prefix[] = "MueLu::Details::LinearSolver::setMatrix: ";
102
103 if (A != A_) {
104 if (solver_ != Teuchos::null)
105 changedA_ = true;
106
107 A_ = rcp_dynamic_cast<const Epetra_CrsMatrix>(A);
108 TEUCHOS_TEST_FOR_EXCEPTION(A_.is_null(), std::runtime_error, prefix << "MueLu requires "
109 "an Epetra_CrsMatrix, but the matrix you provided is of a "
110 "different type. Please provide an Epetra_CrsMatrix instead.");
111 }
112 }
113
115 Teuchos::RCP<const Epetra_Operator> getMatrix() const {
116 return A_;
117 }
118
120 void solve(Epetra_MultiVector& X, const Epetra_MultiVector& B) {
121 // TODO amk: Do we assume the user has called numeric before solve, or should we call it for them?
122 const char prefix[] = "MueLu::Details::LinearSolver::solve: ";
123 TEUCHOS_TEST_FOR_EXCEPTION(solver_.is_null(), std::runtime_error, prefix << "The solver does not "
124 "exist yet. You must call numeric() before you may call this method.");
125 TEUCHOS_TEST_FOR_EXCEPTION(changedA_, std::runtime_error, prefix << "The matrix A has been reset "
126 "since the last call to numeric(). Please call numeric() again.");
127 TEUCHOS_TEST_FOR_EXCEPTION(changedParams_, std::runtime_error, prefix << "The parameters have been reset "
128 "since the last call to numeric(). Please call numeric() again.");
129
130 int err = solver_->ApplyInverse(B, X);
131
132 TEUCHOS_TEST_FOR_EXCEPTION(err != 0, std::runtime_error, prefix << "EpetraOperator::ApplyInverse returned "
133 "nonzero error code "
134 << err);
135 }
136
138 void setParameters(const Teuchos::RCP<Teuchos::ParameterList>& params) {
139 if (solver_ != Teuchos::null && params != params_)
140 changedParams_ = true;
141
142 params_ = params;
143 }
144
147 void symbolic() {}
148
151 void numeric() {
152 const char prefix[] = "MueLu::Details::LinearSolver::numeric: ";
153
154 // If the solver is up-to-date, leave it alone
155 if (solver_ == Teuchos::null || changedA_ || changedParams_) {
156 changedA_ = false;
157 changedParams_ = false;
158
159 TEUCHOS_TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
160 "set yet. You must call setMatrix() with a nonnull matrix before you may "
161 "call this method.");
162
163 // TODO: We should not have to cast away the constness here
164 // TODO: See bug 6462
165 if (params_ != Teuchos::null)
166 solver_ = CreateEpetraPreconditioner(rcp_const_cast<Epetra_CrsMatrix>(A_), *params_);
167 else
168 solver_ = CreateEpetraPreconditioner(rcp_const_cast<Epetra_CrsMatrix>(A_));
169 }
170 }
171
173 std::string description() const {
174 if (solver_.is_null()) {
175 return "\"MueLu::Details::LinearSolver\": {MV: Epetra_MultiVector, OP: Epetra_Operator, NormType: double}";
176 } else {
177 return solver_->GetHierarchy()->description();
178 }
179 }
180
182 void
183 describe(Teuchos::FancyOStream& out,
184 const Teuchos::EVerbosityLevel verbLevel =
185 Teuchos::Describable::verbLevel_default) const {
186 using std::endl;
187 if (solver_.is_null()) {
188 if (verbLevel > Teuchos::VERB_NONE) {
189 Teuchos::OSTab tab0(out);
190 out << "\"MueLu::Details::LinearSolver\":" << endl;
191 Teuchos::OSTab tab1(out);
192 out << "MV: Epetra_MultiVector" << endl
193 << "OP: Epetra_Operator" << endl
194 << "NormType: double" << endl;
195 }
196 } else {
197 solver_->GetHierarchy()->describe(out, verbLevel);
198 }
199 }
200
201 private:
202 Teuchos::RCP<const Epetra_CrsMatrix> A_;
203 Teuchos::RCP<Teuchos::ParameterList> params_;
204 Teuchos::RCP<EpetraOperator> solver_;
205 bool changedA_;
206 bool changedParams_;
207};
208#endif // HAVE_MUELU_EPETRA
209
210template <class Scalar, class LO, class GO, class Node>
211class LinearSolver<Tpetra::MultiVector<Scalar, LO, GO, Node>,
212 Tpetra::Operator<Scalar, LO, GO, Node>,
213 typename Teuchos::ScalarTraits<Scalar>::magnitudeType> : public Trilinos::Details::LinearSolver<Tpetra::MultiVector<Scalar, LO, GO, Node>,
214 Tpetra::Operator<Scalar, LO, GO, Node>,
215 typename Teuchos::ScalarTraits<Scalar>::magnitudeType>,
216 virtual public Teuchos::Describable {
217 public:
220 : changedA_(false)
221 , changedParams_(false) {}
222
224 virtual ~LinearSolver() {}
225
230 void setMatrix(const Teuchos::RCP<const Tpetra::Operator<Scalar, LO, GO, Node> >& A) {
231 if (A != A_) {
232 if (solver_ != Teuchos::null)
233 changedA_ = true;
234
235 A_ = A;
236 }
237 }
238
240 Teuchos::RCP<const Tpetra::Operator<Scalar, LO, GO, Node> > getMatrix() const {
241 return A_;
242 }
243
245 void solve(Tpetra::MultiVector<Scalar, LO, GO, Node>& X, const Tpetra::MultiVector<Scalar, LO, GO, Node>& B) {
246 // TODO amk: Do we assume the user has called numeric before solve, or should we call it for them?
247 const char prefix[] = "MueLu::Details::LinearSolver::solve: ";
248 TEUCHOS_TEST_FOR_EXCEPTION(solver_.is_null(), std::runtime_error, prefix << "The solver does not "
249 "exist yet. You must call numeric() before you may call this method.");
250 TEUCHOS_TEST_FOR_EXCEPTION(changedA_, std::runtime_error, prefix << "The matrix A has been reset "
251 "since the last call to numeric(). Please call numeric() again.");
252 TEUCHOS_TEST_FOR_EXCEPTION(changedParams_, std::runtime_error, prefix << "The parameters have been reset "
253 "since the last call to numeric(). Please call numeric() again.");
254
255 solver_->apply(B, X);
256 }
257
259 void setParameters(const Teuchos::RCP<Teuchos::ParameterList>& params) {
260 if (solver_ != Teuchos::null && params != params_)
261 changedParams_ = true;
262
263 params_ = params;
264 }
265
268 void symbolic() {}
269
272 void numeric() {
273 const char prefix[] = "MueLu::Details::LinearSolver::numeric: ";
274
275 // If the solver is up-to-date, leave it alone
276 if (solver_ == Teuchos::null || changedParams_) {
277 TEUCHOS_TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
278 "set yet. You must call setMatrix() with a nonnull matrix before you may "
279 "call this method.");
280
281 // TODO: We should not have to cast away the constness here
282 // TODO: See bug 6462
283 if (params_ != Teuchos::null)
284 solver_ = CreateTpetraPreconditioner(rcp_const_cast<Tpetra::Operator<Scalar, LO, GO, Node> >(A_), *params_);
285 else
286 solver_ = CreateTpetraPreconditioner(rcp_const_cast<Tpetra::Operator<Scalar, LO, GO, Node> >(A_));
287 } else if (changedA_) {
288 TEUCHOS_TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
289 "set yet. You must call setMatrix() with a nonnull matrix before you may "
290 "call this method.");
291
292 // TODO: We should not have to cast away the constness here
293 // TODO: See bug 6462
294 RCP<const Tpetra::CrsMatrix<Scalar, LO, GO, Node> > helperMat;
295 helperMat = rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar, LO, GO, Node> >(A_);
296 TEUCHOS_TEST_FOR_EXCEPTION(helperMat.is_null(), std::runtime_error, prefix << "MueLu requires "
297 "a Tpetra::CrsMatrix, but the matrix you provided is of a "
298 "different type. Please provide a Tpetra::CrsMatrix instead.");
299 ReuseTpetraPreconditioner(rcp_const_cast<Tpetra::CrsMatrix<Scalar, LO, GO, Node> >(helperMat), *solver_);
300 }
301
302 changedA_ = false;
303 changedParams_ = false;
304 }
305
307 std::string description() const {
308 using Teuchos::TypeNameTraits;
309 if (solver_.is_null()) {
310 std::ostringstream os;
311 os << "\"MueLu::Details::LinearSolver\": {"
312 << "MV: " << TypeNameTraits<Tpetra::MultiVector<Scalar, LO, GO, Node> >::name()
313 << "OP: " << TypeNameTraits<Tpetra::Operator<Scalar, LO, GO, Node> >::name()
314 << "NormType: " << TypeNameTraits<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>::name()
315 << "}";
316 return os.str();
317 } else {
318 return solver_->GetHierarchy()->description();
319 }
320 }
321
323 void
324 describe(Teuchos::FancyOStream& out,
325 const Teuchos::EVerbosityLevel verbLevel =
326 Teuchos::Describable::verbLevel_default) const {
327 using std::endl;
328 using Teuchos::TypeNameTraits;
329 if (solver_.is_null()) {
330 if (verbLevel > Teuchos::VERB_NONE) {
331 Teuchos::OSTab tab0(out);
332 out << "\"MueLu::Details::LinearSolver\":" << endl;
333 Teuchos::OSTab tab1(out);
334 out << "MV: " << TypeNameTraits<Tpetra::MultiVector<Scalar, LO, GO, Node> >::name() << endl
335 << "OP: " << TypeNameTraits<Tpetra::Operator<Scalar, LO, GO, Node> >::name() << endl
336 << "NormType: " << TypeNameTraits<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>::name() << endl;
337 }
338 } else {
339 solver_->GetHierarchy()->describe(out, verbLevel);
340 }
341 }
342
343 private:
344 Teuchos::RCP<const Tpetra::Operator<Scalar, LO, GO, Node> > A_;
345 Teuchos::RCP<Teuchos::ParameterList> params_;
346 Teuchos::RCP<TpetraOperator<Scalar, LO, GO, Node> > solver_;
349};
350
351template <class MV, class OP, class NormType>
352Teuchos::RCP<Trilinos::Details::LinearSolver<MV, OP, NormType> >
354 getLinearSolver(const std::string& solverName) {
355 using Teuchos::rcp;
357}
358
359template <class MV, class OP, class NormType>
362#ifdef HAVE_TEUCHOSCORE_CXX11
363 typedef std::shared_ptr<MueLu::Details::LinearSolverFactory<MV, OP, NormType> > ptr_type;
364 // typedef std::shared_ptr<Trilinos::Details::LinearSolverFactory<MV, OP> > base_ptr_type;
365#else
366 typedef Teuchos::RCP<MueLu::Details::LinearSolverFactory<MV, OP, NormType> > ptr_type;
367 // typedef Teuchos::RCP<Trilinos::Details::LinearSolverFactory<MV, OP> > base_ptr_type;
368#endif // HAVE_TEUCHOSCORE_CXX11
369
371 Trilinos::Details::registerLinearSolverFactory<MV, OP, NormType>("MueLu", factory);
372}
373
374} // namespace Details
375} // namespace MueLu
376
377// Macro for doing explicit instantiation of
378// MueLu::Details::LinearSolverFactory, for Tpetra objects, with
379// given Tpetra template parameters (SC = Scalar, LO = LocalOrdinal,
380// GO = GlobalOrdinal, NT = Node).
381//
382// We don't have to protect use of Tpetra objects here, or include
383// any header files for them, because this is a macro definition.
384#define MUELU_DETAILS_LINEARSOLVERFACTORY_INSTANT(SC, LO, GO, NT) \
385 template class MueLu::Details::LinearSolverFactory<Tpetra::MultiVector<SC, LO, GO, NT>, \
386 Tpetra::Operator<SC, LO, GO, NT>, \
387 typename Tpetra::MultiVector<SC, LO, GO, NT>::mag_type>;
388
389#endif // MUELU_DETAILS_LINEARSOLVERFACTORY_DEF_HPP
Various adapters that will create a MueLu preconditioner that is an Epetra_Operator.
Various adapters that will create a MueLu preconditioner that is a Tpetra::Operator.
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.
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.
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.
Teuchos::RCP< MueLu::EpetraOperator > CreateEpetraPreconditioner(const Teuchos::RCP< Epetra_CrsMatrix > &inA, Teuchos::ParameterList &paramListIn)
Helper function to create a MueLu preconditioner that can be used by Epetra.Given a EpetraCrs_Matrix,...