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// ***********************************************************************
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"
52#include "Trilinos_Details_LinearSolver.hpp"
53#include "Trilinos_Details_LinearSolverFactory.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
64namespace MueLu {
65namespace Details {
66
67template<class MV, class OP, class NormType>
69 public Trilinos::Details::LinearSolver<MV, OP, NormType>,
70 virtual public Teuchos::Describable
71{
72
73public:
74
77
79 virtual ~LinearSolver () {}
80
85 void setMatrix (const Teuchos::RCP<const OP>& A);
86
88 Teuchos::RCP<const OP> getMatrix () const {
89 return A_;
90 }
91
93 void solve (MV& X, const MV& B);
94
96 void setParameters (const Teuchos::RCP<Teuchos::ParameterList>& params);
97
100 void symbolic () {}
101
104 void numeric ();
105
107 std::string description () const;
108
110 void
111 describe (Teuchos::FancyOStream& out,
112 const Teuchos::EVerbosityLevel verbLevel =
113 Teuchos::Describable::verbLevel_default) const;
114
115private:
116 Teuchos::RCP<const OP> A_;
117 Teuchos::RCP<Teuchos::ParameterList> params_;
118};
119
120// Why does MueLu_EpetraOperator insist on HAVE_MUELU_SERIAL?
121#if defined(HAVE_MUELU_SERIAL) and defined(HAVE_MUELU_EPETRA)
122template<>
124 public Trilinos::Details::LinearSolver<Epetra_MultiVector, Epetra_Operator, double>,
125 virtual public Teuchos::Describable
126{
127
128public:
129
131 LinearSolver () :
132 changedA_(false),
133 changedParams_(false)
134 {}
135
137 virtual ~LinearSolver () {}
138
143 void setMatrix (const Teuchos::RCP<const Epetra_Operator>& A)
144 {
145 const char prefix[] = "MueLu::Details::LinearSolver::setMatrix: ";
146
147 if(A != A_)
148 {
149 if(solver_ != Teuchos::null)
150 changedA_ = true;
151
152 A_ = rcp_dynamic_cast<const Epetra_CrsMatrix>(A);
153 TEUCHOS_TEST_FOR_EXCEPTION
154 (A_.is_null(), std::runtime_error, prefix << "MueLu requires "
155 "an Epetra_CrsMatrix, but the matrix you provided is of a "
156 "different type. Please provide an Epetra_CrsMatrix instead.");
157 }
158 }
159
161 Teuchos::RCP<const Epetra_Operator> getMatrix () const {
162 return A_;
163 }
164
166 void solve (Epetra_MultiVector& X, const Epetra_MultiVector& B)
167 {
168 // TODO amk: Do we assume the user has called numeric before solve, or should we call it for them?
169 const char prefix[] = "MueLu::Details::LinearSolver::solve: ";
170 TEUCHOS_TEST_FOR_EXCEPTION
171 (solver_.is_null (), std::runtime_error, prefix << "The solver does not "
172 "exist yet. You must call numeric() before you may call this method.");
173 TEUCHOS_TEST_FOR_EXCEPTION
174 (changedA_, std::runtime_error, prefix << "The matrix A has been reset "
175 "since the last call to numeric(). Please call numeric() again.");
176 TEUCHOS_TEST_FOR_EXCEPTION
177 (changedParams_, std::runtime_error, prefix << "The parameters have been reset "
178 "since the last call to numeric(). Please call numeric() again.");
179
180 int err = solver_->ApplyInverse(B, X);
181
182 TEUCHOS_TEST_FOR_EXCEPTION
183 (err != 0, std::runtime_error, prefix << "EpetraOperator::ApplyInverse returned "
184 "nonzero error code " << err);
185 }
186
188 void setParameters (const Teuchos::RCP<Teuchos::ParameterList>& params)
189 {
190 if(solver_ != Teuchos::null && params != params_)
191 changedParams_ = true;
192
193 params_ = params;
194 }
195
198 void symbolic () {}
199
202 void numeric ()
203 {
204 const char prefix[] = "MueLu::Details::LinearSolver::numeric: ";
205
206 // If the solver is up-to-date, leave it alone
207 if(solver_ == Teuchos::null || changedA_ || changedParams_)
208 {
209 changedA_ = false;
210 changedParams_ = false;
211
212 TEUCHOS_TEST_FOR_EXCEPTION
213 (A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
214 "set yet. You must call setMatrix() with a nonnull matrix before you may "
215 "call this method.");
216
217 // TODO: We should not have to cast away the constness here
218 // TODO: See bug 6462
219 if(params_ != Teuchos::null)
220 solver_ = CreateEpetraPreconditioner(rcp_const_cast<Epetra_CrsMatrix>(A_), *params_);
221 else
222 solver_ = CreateEpetraPreconditioner(rcp_const_cast<Epetra_CrsMatrix>(A_));
223 }
224 }
225
227 std::string description () const
228 {
229 if (solver_.is_null()) {
230 return "\"MueLu::Details::LinearSolver\": {MV: Epetra_MultiVector, OP: Epetra_Operator, NormType: double}";
231 }
232 else {
233 return solver_->GetHierarchy()->description ();
234 }
235 }
236
238 void
239 describe (Teuchos::FancyOStream& out,
240 const Teuchos::EVerbosityLevel verbLevel =
241 Teuchos::Describable::verbLevel_default) const
242 {
243 using std::endl;
244 if (solver_.is_null()) {
245 if(verbLevel > Teuchos::VERB_NONE) {
246 Teuchos::OSTab tab0 (out);
247 out << "\"MueLu::Details::LinearSolver\":" << endl;
248 Teuchos::OSTab tab1 (out);
249 out << "MV: Epetra_MultiVector" << endl
250 << "OP: Epetra_Operator" << endl
251 << "NormType: double" << endl;
252 }
253 }
254 else {
255 solver_->GetHierarchy()->describe (out, verbLevel);
256 }
257 }
258
259private:
260 Teuchos::RCP<const Epetra_CrsMatrix> A_;
261 Teuchos::RCP<Teuchos::ParameterList> params_;
262 Teuchos::RCP<EpetraOperator> solver_;
263 bool changedA_;
264 bool changedParams_;
265};
266#endif // HAVE_MUELU_EPETRA
267
268template<class Scalar, class LO, class GO, class Node>
269class LinearSolver<Tpetra::MultiVector<Scalar,LO,GO,Node>,
270 Tpetra::Operator<Scalar,LO,GO,Node>,
271 typename Teuchos::ScalarTraits<Scalar>::magnitudeType> :
272 public Trilinos::Details::LinearSolver<Tpetra::MultiVector<Scalar,LO,GO,Node>,
273 Tpetra::Operator<Scalar,LO,GO,Node>,
274 typename Teuchos::ScalarTraits<Scalar>::magnitudeType>,
275 virtual public Teuchos::Describable
276{
277
278public:
279
282 changedA_(false),
283 changedParams_(false)
284 {}
285
287 virtual ~LinearSolver () {}
288
293 void setMatrix (const Teuchos::RCP<const Tpetra::Operator<Scalar,LO,GO,Node> >& A)
294 {
295 if(A != A_)
296 {
297 if(solver_ != Teuchos::null)
298 changedA_ = true;
299
300 A_ = A;
301 }
302 }
303
305 Teuchos::RCP<const Tpetra::Operator<Scalar,LO,GO,Node> > getMatrix () const {
306 return A_;
307 }
308
310 void solve (Tpetra::MultiVector<Scalar,LO,GO,Node>& X, const Tpetra::MultiVector<Scalar,LO,GO,Node>& B)
311 {
312 // TODO amk: Do we assume the user has called numeric before solve, or should we call it for them?
313 const char prefix[] = "MueLu::Details::LinearSolver::solve: ";
314 TEUCHOS_TEST_FOR_EXCEPTION
315 (solver_.is_null (), std::runtime_error, prefix << "The solver does not "
316 "exist yet. You must call numeric() before you may call this method.");
317 TEUCHOS_TEST_FOR_EXCEPTION
318 (changedA_, std::runtime_error, prefix << "The matrix A has been reset "
319 "since the last call to numeric(). Please call numeric() again.");
320 TEUCHOS_TEST_FOR_EXCEPTION
321 (changedParams_, std::runtime_error, prefix << "The parameters have been reset "
322 "since the last call to numeric(). Please call numeric() again.");
323
324 solver_->apply(B, X);
325 }
326
328 void setParameters (const Teuchos::RCP<Teuchos::ParameterList>& params)
329 {
330 if(solver_ != Teuchos::null && params != params_)
331 changedParams_ = true;
332
333 params_ = params;
334 }
335
338 void symbolic () {}
339
342 void numeric ()
343 {
344 const char prefix[] = "MueLu::Details::LinearSolver::numeric: ";
345
346 // If the solver is up-to-date, leave it alone
347 if(solver_ == Teuchos::null || changedParams_)
348 {
349 TEUCHOS_TEST_FOR_EXCEPTION
350 (A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
351 "set yet. You must call setMatrix() with a nonnull matrix before you may "
352 "call this method.");
353
354 // TODO: We should not have to cast away the constness here
355 // TODO: See bug 6462
356 if(params_ != Teuchos::null)
357 solver_ = CreateTpetraPreconditioner(rcp_const_cast<Tpetra::Operator<Scalar,LO,GO,Node> >(A_), *params_);
358 else
359 solver_ = CreateTpetraPreconditioner(rcp_const_cast<Tpetra::Operator<Scalar,LO,GO,Node> >(A_));
360 }
361 else if(changedA_)
362 {
363 TEUCHOS_TEST_FOR_EXCEPTION
364 (A_ == Teuchos::null, std::runtime_error, prefix << "The matrix has not been "
365 "set yet. You must call setMatrix() with a nonnull matrix before you may "
366 "call this method.");
367
368 // TODO: We should not have to cast away the constness here
369 // TODO: See bug 6462
370 RCP<const Tpetra::CrsMatrix<Scalar,LO,GO,Node> > helperMat;
371 helperMat = rcp_dynamic_cast<const Tpetra::CrsMatrix<Scalar,LO,GO,Node> >(A_);
372 TEUCHOS_TEST_FOR_EXCEPTION
373 (helperMat.is_null(), std::runtime_error, prefix << "MueLu requires "
374 "a Tpetra::CrsMatrix, but the matrix you provided is of a "
375 "different type. Please provide a Tpetra::CrsMatrix instead.");
376 ReuseTpetraPreconditioner(rcp_const_cast<Tpetra::CrsMatrix<Scalar,LO,GO,Node> >(helperMat), *solver_);
377 }
378
379 changedA_ = false;
380 changedParams_ = false;
381 }
382
384 std::string description () const
385 {
386 using Teuchos::TypeNameTraits;
387 if (solver_.is_null()) {
388 std::ostringstream os;
389 os << "\"MueLu::Details::LinearSolver\": {"
390 << "MV: " << TypeNameTraits<Tpetra::MultiVector<Scalar,LO,GO,Node> >::name()
391 << "OP: " << TypeNameTraits<Tpetra::Operator<Scalar,LO,GO,Node> >::name()
392 << "NormType: " << TypeNameTraits<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>::name()
393 << "}";
394 return os.str ();
395 }
396 else {
397 return solver_->GetHierarchy()->description ();
398 }
399 }
400
402 void
403 describe (Teuchos::FancyOStream& out,
404 const Teuchos::EVerbosityLevel verbLevel =
405 Teuchos::Describable::verbLevel_default) const
406 {
407 using Teuchos::TypeNameTraits;
408 using std::endl;
409 if (solver_.is_null()) {
410 if(verbLevel > Teuchos::VERB_NONE) {
411 Teuchos::OSTab tab0 (out);
412 out << "\"MueLu::Details::LinearSolver\":" << endl;
413 Teuchos::OSTab tab1 (out);
414 out << "MV: " << TypeNameTraits<Tpetra::MultiVector<Scalar,LO,GO,Node> >::name() << endl
415 << "OP: " << TypeNameTraits<Tpetra::Operator<Scalar,LO,GO,Node> >::name() << endl
416 << "NormType: " << TypeNameTraits<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>::name() << endl;
417 }
418 }
419 else {
420 solver_->GetHierarchy()->describe (out, verbLevel);
421 }
422 }
423
424private:
425 Teuchos::RCP<const Tpetra::Operator<Scalar,LO,GO,Node> > A_;
426 Teuchos::RCP<Teuchos::ParameterList> params_;
427 Teuchos::RCP<TpetraOperator<Scalar,LO,GO,Node> > solver_;
430};
431
432template<class MV, class OP, class NormType>
433Teuchos::RCP<Trilinos::Details::LinearSolver<MV, OP, NormType> >
435getLinearSolver (const std::string& solverName)
436{
437 using Teuchos::rcp;
439}
440
441template<class MV, class OP, class NormType>
442void
445{
446#ifdef HAVE_TEUCHOSCORE_CXX11
447 typedef std::shared_ptr<MueLu::Details::LinearSolverFactory<MV, OP, NormType> > ptr_type;
448 //typedef std::shared_ptr<Trilinos::Details::LinearSolverFactory<MV, OP> > base_ptr_type;
449#else
450 typedef Teuchos::RCP<MueLu::Details::LinearSolverFactory<MV, OP, NormType> > ptr_type;
451 //typedef Teuchos::RCP<Trilinos::Details::LinearSolverFactory<MV, OP> > base_ptr_type;
452#endif // HAVE_TEUCHOSCORE_CXX11
453
455 Trilinos::Details::registerLinearSolverFactory<MV, OP, NormType> ("MueLu", factory);
456}
457
458} // namespace Details
459} // namespace MueLu
460
461// Macro for doing explicit instantiation of
462// MueLu::Details::LinearSolverFactory, for Tpetra objects, with
463// given Tpetra template parameters (SC = Scalar, LO = LocalOrdinal,
464// GO = GlobalOrdinal, NT = Node).
465//
466// We don't have to protect use of Tpetra objects here, or include
467// any header files for them, because this is a macro definition.
468#define MUELU_DETAILS_LINEARSOLVERFACTORY_INSTANT(SC, LO, GO, NT) \
469 template class MueLu::Details::LinearSolverFactory<Tpetra::MultiVector<SC, LO, GO, NT>, \
470 Tpetra::Operator<SC, LO, GO, NT>, \
471 typename Tpetra::MultiVector<SC, LO, GO, NT>::mag_type>;
472
473#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,...