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 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2011 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 //
42 // @HEADER
43 
47 
48 #ifndef MUELU_DETAILS_LINEARSOLVERFACTORY_DEF_HPP
49 #define MUELU_DETAILS_LINEARSOLVERFACTORY_DEF_HPP
50 
51 #include "MueLu_config.hpp"
54 #include <type_traits>
55 
56 #ifdef HAVE_MUELU_EPETRA
57 #include "Epetra_CrsMatrix.h"
59 #endif // HAVE_MUELU_EPETRA
60 
61 #include "Tpetra_Operator.hpp"
63 
64 namespace MueLu {
65 namespace Details {
66 
67 template <class MV, class OP, class NormType>
68 class LinearSolver : public Trilinos::Details::LinearSolver<MV, OP, NormType>,
69  virtual public Teuchos::Describable {
70  public:
73 
75  virtual ~LinearSolver() {}
76 
81  void setMatrix(const Teuchos::RCP<const OP>& A);
82 
85  return A_;
86  }
87 
89  void solve(MV& X, const MV& B);
90 
93 
96  void symbolic() {}
97 
100  void numeric();
101 
103  std::string description() const;
104 
106  void
108  const Teuchos::EVerbosityLevel verbLevel =
110 
111  private:
114 };
115 
116 // Why does MueLu_EpetraOperator insist on HAVE_MUELU_SERIAL?
117 #if defined(HAVE_MUELU_SERIAL) and defined(HAVE_MUELU_EPETRA)
118 template <>
119 class LinearSolver<Epetra_MultiVector, Epetra_Operator, double> : public Trilinos::Details::LinearSolver<Epetra_MultiVector, Epetra_Operator, double>,
120  virtual public Teuchos::Describable {
121  public:
123  LinearSolver()
124  : changedA_(false)
125  , changedParams_(false) {}
126 
128  virtual ~LinearSolver() {}
129 
135  const char prefix[] = "MueLu::Details::LinearSolver::setMatrix: ";
136 
137  if (A != A_) {
138  if (solver_ != Teuchos::null)
139  changedA_ = true;
140 
141  A_ = rcp_dynamic_cast<const Epetra_CrsMatrix>(A);
142  TEUCHOS_TEST_FOR_EXCEPTION(A_.is_null(), std::runtime_error, prefix << "MueLu requires "
143  "an Epetra_CrsMatrix, but the matrix you provided is of a "
144  "different type. Please provide an Epetra_CrsMatrix instead.");
145  }
146  }
147 
150  return A_;
151  }
152 
154  void solve(Epetra_MultiVector& X, const Epetra_MultiVector& B) {
155  // TODO amk: Do we assume the user has called numeric before solve, or should we call it for them?
156  const char prefix[] = "MueLu::Details::LinearSolver::solve: ";
157  TEUCHOS_TEST_FOR_EXCEPTION(solver_.is_null(), std::runtime_error, prefix << "The solver does not "
158  "exist yet. You must call numeric() before you may call this method.");
159  TEUCHOS_TEST_FOR_EXCEPTION(changedA_, std::runtime_error, prefix << "The matrix A has been reset "
160  "since the last call to numeric(). Please call numeric() again.");
161  TEUCHOS_TEST_FOR_EXCEPTION(changedParams_, std::runtime_error, prefix << "The parameters have been reset "
162  "since the last call to numeric(). Please call numeric() again.");
163 
164  int err = solver_->ApplyInverse(B, X);
165 
166  TEUCHOS_TEST_FOR_EXCEPTION(err != 0, std::runtime_error, prefix << "EpetraOperator::ApplyInverse returned "
167  "nonzero error code "
168  << err);
169  }
170 
173  if (solver_ != Teuchos::null && params != params_)
174  changedParams_ = true;
175 
176  params_ = params;
177  }
178 
181  void symbolic() {}
182 
185  void numeric() {
186  const char prefix[] = "MueLu::Details::LinearSolver::numeric: ";
187 
188  // If the solver is up-to-date, leave it alone
189  if (solver_ == Teuchos::null || changedA_ || changedParams_) {
190  changedA_ = false;
191  changedParams_ = false;
192 
193  TEUCHOS_TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
194  "set yet. You must call setMatrix() with a nonnull matrix before you may "
195  "call this method.");
196 
197  // TODO: We should not have to cast away the constness here
198  // TODO: See bug 6462
199  if (params_ != Teuchos::null)
200  solver_ = CreateEpetraPreconditioner(rcp_const_cast<Epetra_CrsMatrix>(A_), *params_);
201  else
202  solver_ = CreateEpetraPreconditioner(rcp_const_cast<Epetra_CrsMatrix>(A_));
203  }
204  }
205 
207  std::string description() const {
208  if (solver_.is_null()) {
209  return "\"MueLu::Details::LinearSolver\": {MV: Epetra_MultiVector, OP: Epetra_Operator, NormType: double}";
210  } else {
211  return solver_->GetHierarchy()->description();
212  }
213  }
214 
216  void
218  const Teuchos::EVerbosityLevel verbLevel =
220  using std::endl;
221  if (solver_.is_null()) {
222  if (verbLevel > Teuchos::VERB_NONE) {
223  Teuchos::OSTab tab0(out);
224  out << "\"MueLu::Details::LinearSolver\":" << endl;
225  Teuchos::OSTab tab1(out);
226  out << "MV: Epetra_MultiVector" << endl
227  << "OP: Epetra_Operator" << endl
228  << "NormType: double" << endl;
229  }
230  } else {
231  solver_->GetHierarchy()->describe(out, verbLevel);
232  }
233  }
234 
235  private:
239  bool changedA_;
240  bool changedParams_;
241 };
242 #endif // HAVE_MUELU_EPETRA
243 
244 template <class Scalar, class LO, class GO, class Node>
245 class LinearSolver<Tpetra::MultiVector<Scalar, LO, GO, Node>,
246  Tpetra::Operator<Scalar, LO, GO, Node>,
247  typename Teuchos::ScalarTraits<Scalar>::magnitudeType> : public Trilinos::Details::LinearSolver<Tpetra::MultiVector<Scalar, LO, GO, Node>,
248  Tpetra::Operator<Scalar, LO, GO, Node>,
249  typename Teuchos::ScalarTraits<Scalar>::magnitudeType>,
250  virtual public Teuchos::Describable {
251  public:
254  : changedA_(false)
255  , changedParams_(false) {}
256 
258  virtual ~LinearSolver() {}
259 
265  if (A != A_) {
266  if (solver_ != Teuchos::null)
267  changedA_ = true;
268 
269  A_ = A;
270  }
271  }
272 
275  return A_;
276  }
277 
280  // TODO amk: Do we assume the user has called numeric before solve, or should we call it for them?
281  const char prefix[] = "MueLu::Details::LinearSolver::solve: ";
282  TEUCHOS_TEST_FOR_EXCEPTION(solver_.is_null(), std::runtime_error, prefix << "The solver does not "
283  "exist yet. You must call numeric() before you may call this method.");
284  TEUCHOS_TEST_FOR_EXCEPTION(changedA_, std::runtime_error, prefix << "The matrix A has been reset "
285  "since the last call to numeric(). Please call numeric() again.");
286  TEUCHOS_TEST_FOR_EXCEPTION(changedParams_, std::runtime_error, prefix << "The parameters have been reset "
287  "since the last call to numeric(). Please call numeric() again.");
288 
289  solver_->apply(B, X);
290  }
291 
294  if (solver_ != Teuchos::null && params != params_)
295  changedParams_ = true;
296 
297  params_ = params;
298  }
299 
302  void symbolic() {}
303 
306  void numeric() {
307  const char prefix[] = "MueLu::Details::LinearSolver::numeric: ";
308 
309  // If the solver is up-to-date, leave it alone
310  if (solver_ == Teuchos::null || changedParams_) {
311  TEUCHOS_TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
312  "set yet. You must call setMatrix() with a nonnull matrix before you may "
313  "call this method.");
314 
315  // TODO: We should not have to cast away the constness here
316  // TODO: See bug 6462
317  if (params_ != Teuchos::null)
319  else
321  } else if (changedA_) {
322  TEUCHOS_TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
323  "set yet. You must call setMatrix() with a nonnull matrix before you may "
324  "call this method.");
325 
326  // TODO: We should not have to cast away the constness here
327  // TODO: See bug 6462
329  helperMat = rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar, LO, GO, Node> >(A_);
330  TEUCHOS_TEST_FOR_EXCEPTION(helperMat.is_null(), std::runtime_error, prefix << "MueLu requires "
331  "a Tpetra::CrsMatrix, but the matrix you provided is of a "
332  "different type. Please provide a Tpetra::CrsMatrix instead.");
333  ReuseTpetraPreconditioner(rcp_const_cast<Tpetra::CrsMatrix<Scalar, LO, GO, Node> >(helperMat), *solver_);
334  }
335 
336  changedA_ = false;
337  changedParams_ = false;
338  }
339 
341  std::string description() const {
343  if (solver_.is_null()) {
344  std::ostringstream os;
345  os << "\"MueLu::Details::LinearSolver\": {"
346  << "MV: " << TypeNameTraits<Tpetra::MultiVector<Scalar, LO, GO, Node> >::name()
347  << "OP: " << TypeNameTraits<Tpetra::Operator<Scalar, LO, GO, Node> >::name()
348  << "NormType: " << TypeNameTraits<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>::name()
349  << "}";
350  return os.str();
351  } else {
352  return solver_->GetHierarchy()->description();
353  }
354  }
355 
357  void
359  const Teuchos::EVerbosityLevel verbLevel =
361  using std::endl;
363  if (solver_.is_null()) {
364  if (verbLevel > Teuchos::VERB_NONE) {
365  Teuchos::OSTab tab0(out);
366  out << "\"MueLu::Details::LinearSolver\":" << endl;
367  Teuchos::OSTab tab1(out);
368  out << "MV: " << TypeNameTraits<Tpetra::MultiVector<Scalar, LO, GO, Node> >::name() << endl
369  << "OP: " << TypeNameTraits<Tpetra::Operator<Scalar, LO, GO, Node> >::name() << endl
370  << "NormType: " << TypeNameTraits<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>::name() << endl;
371  }
372  } else {
373  solver_->GetHierarchy()->describe(out, verbLevel);
374  }
375  }
376 
377  private:
381  bool changedA_;
383 };
384 
385 template <class MV, class OP, class NormType>
388  getLinearSolver(const std::string& solverName) {
389  using Teuchos::rcp;
391 }
392 
393 template <class MV, class OP, class NormType>
396 #ifdef HAVE_TEUCHOSCORE_CXX11
397  typedef std::shared_ptr<MueLu::Details::LinearSolverFactory<MV, OP, NormType> > ptr_type;
398  // typedef std::shared_ptr<Trilinos::Details::LinearSolverFactory<MV, OP> > base_ptr_type;
399 #else
401  // typedef Teuchos::RCP<Trilinos::Details::LinearSolverFactory<MV, OP> > base_ptr_type;
402 #endif // HAVE_TEUCHOSCORE_CXX11
403 
405  Trilinos::Details::registerLinearSolverFactory<MV, OP, NormType>("MueLu", factory);
406 }
407 
408 } // namespace Details
409 } // namespace MueLu
410 
411 // Macro for doing explicit instantiation of
412 // MueLu::Details::LinearSolverFactory, for Tpetra objects, with
413 // given Tpetra template parameters (SC = Scalar, LO = LocalOrdinal,
414 // GO = GlobalOrdinal, NT = Node).
415 //
416 // We don't have to protect use of Tpetra objects here, or include
417 // any header files for them, because this is a macro definition.
418 #define MUELU_DETAILS_LINEARSOLVERFACTORY_INSTANT(SC, LO, GO, NT) \
419  template class MueLu::Details::LinearSolverFactory<Tpetra::MultiVector<SC, LO, GO, NT>, \
420  Tpetra::Operator<SC, LO, GO, NT>, \
421  typename Tpetra::MultiVector<SC, LO, GO, NT>::mag_type>;
422 
423 #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