MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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"
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 
30 namespace MueLu {
31 namespace Details {
32 
33 template <class MV, class OP, class NormType>
34 class 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 
51  return A_;
52  }
53 
55  void solve(MV& X, const MV& B);
56 
59 
62  void symbolic() {}
63 
66  void numeric();
67 
69  std::string description() const;
70 
72  void
74  const Teuchos::EVerbosityLevel verbLevel =
76 
77  private:
80 };
81 
82 // Why does MueLu_EpetraOperator insist on HAVE_MUELU_SERIAL?
83 #if defined(HAVE_MUELU_SERIAL) and defined(HAVE_MUELU_EPETRA)
84 template <>
85 class LinearSolver<Epetra_MultiVector, Epetra_Operator, double> : public Trilinos::Details::LinearSolver<Epetra_MultiVector, Epetra_Operator, double>,
86  virtual public Teuchos::Describable {
87  public:
89  LinearSolver()
90  : changedA_(false)
91  , changedParams_(false) {}
92 
94  virtual ~LinearSolver() {}
95 
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 
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 
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
184  const Teuchos::EVerbosityLevel verbLevel =
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:
205  bool changedA_;
206  bool changedParams_;
207 };
208 #endif // HAVE_MUELU_EPETRA
209 
210 template <class Scalar, class LO, class GO, class Node>
211 class 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 
231  if (A != A_) {
232  if (solver_ != Teuchos::null)
233  changedA_ = true;
234 
235  A_ = A;
236  }
237  }
238 
241  return A_;
242  }
243 
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 
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)
285  else
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
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 {
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
325  const Teuchos::EVerbosityLevel verbLevel =
327  using std::endl;
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:
347  bool changedA_;
349 };
350 
351 template <class MV, class OP, class NormType>
354  getLinearSolver(const std::string& solverName) {
355  using Teuchos::rcp;
357 }
358 
359 template <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
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
Interface for a &quot;factory&quot; that creates MueLu solvers.
Teuchos::RCP< const OP > getMatrix() const
Get a pointer to this Solver&#39;s matrix.
std::string description() const
Implementation of Teuchos::Describable::description.
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.Given a Tpetra::Operator, this function returns a constructed MueLu preconditioner.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual Teuchos::RCP< Trilinos::Details::LinearSolver< MV, OP, NormType > > getLinearSolver(const std::string &solverName)
Get an instance of a MueLu solver.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void setParameters(const Teuchos::RCP< Teuchos::ParameterList > &params)
Set this solver&#39;s parameters.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Implementation of Teuchos::Describable::describe.
Various adapters that will create a MueLu preconditioner that is a Tpetra::Operator.
static const EVerbosityLevel verbLevel_default
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...
static void registerLinearSolverFactory()
Register this LinearSolverFactory with the central registry.
Various adapters that will create a MueLu preconditioner that is an Epetra_Operator.
virtual ~LinearSolver()
Destructor (virtual for memory safety).
void symbolic()
Set up any part of the solve that depends on the structure of the input matrix, but not its numerical...
Teuchos::RCP< Teuchos::ParameterList > params_
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 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.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Implementation of Teuchos::Describable::describe.
void setMatrix(const Teuchos::RCP< const OP > &A)
Set the Solver&#39;s matrix.
void solve(Tpetra::MultiVector< Scalar, LO, GO, Node > &X, const Tpetra::MultiVector< Scalar, LO, GO, Node > &B)
Solve the linear system(s) AX=B.
bool is_null() const