AMDiS  0.3
The Adaptive Multi-Dimensional Simulation Toolbox
SolverCreator.hpp
1 #pragma once
2 
3 #include <memory>
4 
5 #include <dune/common/classname.hh>
6 #include <dune/common/version.hh>
7 
8 #include <dune/common/ftraits.hh>
9 
10 #include <amdis/CreatorMap.hpp>
11 #include <amdis/Environment.hpp>
12 #include <amdis/Initfile.hpp>
13 #include <amdis/Output.hpp>
14 
15 #include <amdis/linearalgebra/LinearSolver.hpp>
16 #include <amdis/linearalgebra/istl/CreatorInterfaces.hpp>
17 #include <amdis/linearalgebra/istl/ISTLSolver.hpp>
18 #include <amdis/linearalgebra/istl/SolverWrapper.hpp>
19 #include <amdis/linearalgebra/istl/precompiled/Solvers.hpp>
20 
21 namespace AMDiS
22 {
23  namespace tag
24  {
25  template <class Solver> struct pcg {};
26  template <class Solver> struct gmres {};
27  }
28 
30 
36  template <class Model, class Traits>
38  : public ISTLSolverCreatorInterface<Traits>
39  {
40  using Interface = ISTLSolverCreatorInterface<Traits>;
41  struct Creator : CreatorInterfaceName<Interface>
42  {
43  std::unique_ptr<Interface> createWithString(std::string prefix) override
44  {
45  return std::make_unique<Model>(prefix);
46  }
47  };
48 
49  explicit ISTLSolverCreator(std::string const& prefix)
50  {
51  if (Environment::mpiRank() == 0)
52  Parameters::get(prefix + "->info", info_);
53  }
54 
55  protected:
56  int info_ = 0;
57  };
58 
59 
61 
69  template <class Creator, class Traits>
71  : public ISTLSolverCreator<Creator, Traits>
72  {
74 
75  using LinOp = typename Traits::LinOp;
76  using ScalProd = typename Traits::ScalProd;
77  using Prec = typename Traits::Prec;
78 
79  using real_type = typename Dune::FieldTraits<typename Traits::M::field_type>::real_type;
80 
81  public:
82  explicit ISTLIterativeSolverCreator(std::string const& prefix)
83  : Super(prefix)
84  {
85  Parameters::get(prefix + "->max iteration", maxIter_);
86  Parameters::get(prefix + "->relative tolerance", rTol_);
87 
88  std::string precon = "default";
89  Parameters::get(prefix + "->precon", precon);
90 
92  auto* creator = named(CreatorMap::getCreator(precon, prefix + "->precon"));
93  preconCreator_ = creator->createWithString(prefix + "->precon");
94  assert(preconCreator_);
95  }
96 
97  protected:
98  template <class Solver, class... Args>
99  auto create_impl(typename Traits::M const& mat, typename Traits::Comm const& comm, Args&&... args) const
100  {
101  auto cat = Dune::SolverCategory::category(comm);
102  auto sp = Traits::ScalProdCreator::create(cat, comm);
103  auto linOp = Traits::LinOpCreator::create(cat, mat, comm);
104 
105  auto precon = preconCreator_->create(mat, comm);
106  return std::make_unique<IterativeSolverWrapper<Solver>>(
107  std::move(linOp), std::move(sp), std::move(precon), FWD(args)...);
108  }
109 
110  protected:
111  int maxIter_ = 500;
112  real_type rTol_ = 1.e-6;
113  std::shared_ptr<ISTLPreconCreatorInterface<Traits>> preconCreator_;
114  };
115 
116 
118 
122  template <class Solver, class Traits>
124  : public ISTLIterativeSolverCreator<IterativeSolverCreator<Solver,Traits>, Traits>
125  {
127  using Interface = typename Traits::Solver;
128 
129  public:
130  using Super::Super;
131 
132  std::unique_ptr<Interface> create(typename Traits::M const& mat, typename Traits::Comm const& comm) const override
133  {
134  return this->template create_impl<Solver>(mat, comm, this->rTol_, this->maxIter_, this->info_);
135  }
136  };
137 
138 
140 
147  template <class Solver, class Traits>
150  {
152  using Interface = typename Traits::Solver;
153 
154  public:
155  explicit IterativeSolverCreator(std::string const& prefix)
156  : Super(prefix)
157  {
158  Parameters::get(prefix + "->restart", restart_);
159  }
160 
161  std::unique_ptr<Interface> create(typename Traits::M const& mat, typename Traits::Comm const& comm) const override
162  {
163  return this->template create_impl<Solver>(mat, comm, this->rTol_, restart_, this->maxIter_, this->info_);
164  }
165 
166  private:
167  int restart_ = 30;
168  };
169 
170 
172 
179  template <class Solver, class Traits>
182  {
184  using Interface = typename Traits::Solver;
185 
186  public:
187  explicit IterativeSolverCreator(std::string const& prefix)
188  : Super(prefix)
189  {
190  Parameters::get(prefix + "->restart", restart_);
191  }
192 
193  std::unique_ptr<Interface> create(typename Traits::M const& mat, typename Traits::Comm const& comm) const override
194  {
195  return this->template create_impl<Solver>(mat, comm, this->rTol_, this->maxIter_, this->info_, restart_);
196  }
197 
198  private:
199  int restart_ = 30;
200  };
201 
202 
204 
214  template <class Solver, class Traits>
217  {
219 
220  explicit DirectSolverCreator(std::string const& prefix)
221  : Super(prefix)
222  {
223  Parameters::get(prefix + "->reuse vector", reuseVector_);
224  }
225 
226  std::unique_ptr<typename Traits::Solver>
227  create(typename Traits::M const& mat, typename Traits::Comm const& comm) const override
228  {
229  test_exit(Dune::SolverCategory::category(comm) == Dune::SolverCategory::sequential,
230  "Direct solver can be used as sequential solver only.");
231  return std::make_unique<Solver>(mat, this->info_, reuseVector_);
232  }
233 
234  protected:
235  bool reuseVector_ = true;
236  };
237 
238 #if HAVE_SUITESPARSE_CHOLMOD && DUNE_VERSION_GTE(DUNE_ISTL,2,7)
239  template <class X, class Traits>
241  struct DirectSolverCreator<Dune::Cholmod<X>,Traits>
242  : public ISTLSolverCreator<DirectSolverCreator<Dune::Cholmod<X>,Traits>, Traits>
243  {
245  using Super::Super;
246 
247  std::unique_ptr<typename Traits::Solver>
248  create(typename Traits::M const& mat, typename Traits::Comm const& comm) const override
249  {
250  test_exit(Dune::SolverCategory::category(comm) == Dune::SolverCategory::sequential,
251  "Direct solver can be used as sequential solver only.");
252  auto solver = std::make_unique<Dune::Cholmod<X>>();
253  solver->setMatrix(mat);
254  return std::move(solver);
255  }
256  };
257 #endif
258 
259 
261 
277  template <class Traits, class Interface>
279  {
280  using M = typename Traits::M;
281  using X = typename Traits::X;
282  using Y = typename Traits::Y;
283 
284  using FTraits = Dune::FieldTraits<typename M::field_type>;
285 
286  template <class Solver>
287  using IterativeSolver = typename IterativeSolverCreator<Solver,Traits>::Creator;
288 
289  template <class Solver>
290  using DirectSolver = typename DirectSolverCreator<Solver,Traits>::Creator;
291 
292  using Map = CreatorMap<Interface>;
293 
294  public:
295  static void init()
296  {
297  auto cg = new IterativeSolver<Dune::CGSolver<X>>;
298  addCreator("cg", cg);
299 
300  // Generalized preconditioned conjugate gradient solver.
301  auto pcg = new IterativeSolver<tag::pcg<Dune::GeneralizedPCGSolver<X>>>;
302  addCreator("pcg", pcg);
303 
304 #if DUNE_VERSION_GTE(DUNE_ISTL,2,7)
305  auto fcg = new IterativeSolver<tag::pcg<Dune::RestartedFCGSolver<X>>>;
306  addCreator("fcg", fcg);
307 
308  auto cfcg = new IterativeSolver<tag::pcg<Dune::CompleteFCGSolver<X>>>;
309  addCreator("cfcg", cfcg);
310 #endif
311 
312  auto bicgstab = new IterativeSolver<Dune::BiCGSTABSolver<X>>;
313  addCreator("bicgstab", bicgstab);
314  addCreator("bcgs", bicgstab);
315  addCreator("default", bicgstab);
316 
317  auto minres = new IterativeSolver<Dune::MINRESSolver<X>>;
318  addCreator("minres", minres);
319 
320  auto gmres = new IterativeSolver<tag::gmres<Dune::RestartedGMResSolver<X,Y>>>;
321  addCreator("gmres", gmres);
322 
323 #if DUNE_VERSION_GTE(DUNE_ISTL,2,7)
324  auto fgmres = new IterativeSolver<tag::gmres<Dune::RestartedFlexibleGMResSolver<X,Y>>>;
325  addCreator("fgmres", fgmres);
326 #endif
327 
328  init_direct(std::is_same<typename FTraits::real_type, double>{});
329  }
330 
331  static void init_direct(std::false_type)
332  {
333  warning("Direct solvers not created for the matrix with real_type = {}.",
334  Dune::className<typename FTraits::real_type>());
335  }
336 
337  static void init_direct(std::true_type)
338  {
339 #if HAVE_SUITESPARSE_UMFPACK
340  auto umfpack = new DirectSolver<Dune::UMFPack<M>>;
341  addCreator("umfpack", umfpack);
342 #endif
343 
344 #if HAVE_SUITESPARSE_LDL
345  auto ldl = new DirectSolver<Dune::LDL<M>>;
346  addCreator("ldl", ldl);
347 #endif
348 
349 #if HAVE_SUITESPARSE_SPQR
350  auto spqr = new DirectSolver<Dune::SPQR<M>>;
351  addCreator("spqr", spqr);
352 #endif
353 
354 #if HAVE_SUITESPARSE_CHOLMOD && DUNE_VERSION_GTE(DUNE_ISTL,2,7)
355  auto cholmod = new DirectSolver<Dune::Cholmod<X>>;
356  addCreator("cholmod", cholmod);
357 #endif
358 
359 #if HAVE_SUPERLU
360  auto superlu = new DirectSolver<Dune::SuperLU<M>>;
361  addCreator("superlu", superlu);
362 #endif
363 
364  // default direct solvers
365 #if HAVE_SUITESPARSE_UMFPACK
366  addCreator("direct", umfpack);
367 #elif HAVE_SUPERLU
368  addCreator("direct", superlu);
369 #endif
370  }
371 
372  private:
373  template <class T> struct Type {};
374 
375  template <class Creator>
376  static void addCreator(std::string name, Creator* creator)
377  {
378  addCreatorImpl(name, creator, Type<Interface>{});
379  }
380 
381  template <class Creator>
382  static void addCreatorImpl(std::string name, Creator* creator, Type<ISTLSolverCreatorInterface<Traits>>)
383  {
384  Map::addCreator(name, creator);
385  }
386 
387  template <class Creator, class Mat, class Vec>
388  static void addCreatorImpl(std::string name, Creator* creator, Type<LinearSolverInterface<Mat,Vec>>)
389  {
390  using LinearSolverCreator = typename ISTLSolver<Mat, Vec>::Creator;
391  Map::addCreator(name, new LinearSolverCreator);
392  }
393  };
394 
395 
396  template <class Traits>
398  : public DefaultSolverCreators<Traits, ISTLSolverCreatorInterface<Traits>>
399  {};
400 
401  template <class Mat, class Vec>
402  class DefaultCreators< LinearSolverInterface<Mat,Vec> >
403  : public DefaultSolverCreators<SolverTraits<Mat, Vec>, LinearSolverInterface<Mat,Vec>>
404  {};
405 
406 
407  // extern template declarations:
409 
410 } // end namespace AMDiS
std::unique_ptr< Interface > createWithString(std::string prefix) override
Must be implemented by sub classes of CreatorInterfaceName. Creates a new instance of the sub class o...
Definition: SolverCreator.hpp:43
Definition: SolverCreator.hpp:41
A creator to be used instead of the constructor.
Definition: ISTLSolver.hpp:26
Adds default creators for linear solvers based on Dune::BCRSMatrix.
Definition: SolverCreator.hpp:278
Interface for creators with name.
Definition: CreatorInterface.hpp:42
A CreatorMap is used to construct objects, which types depends on key words determined at run time...
Definition: CreatorMap.hpp:29
Contains all classes needed for solving linear and non linear equation systems.
Definition: AdaptBase.hpp:6
auto cat(Dune::TypeTree::HybridTreePath< S... > const &tp0, Dune::TypeTree::HybridTreePath< T... > const &tp1)
Concatenate two treepaths.
Definition: TreePath.hpp:209
Definition: SolverCreator.hpp:26
Definition: SolverCreator.hpp:25
void info_(int noInfoLevel, std::string const &str, Args &&... args)
prints a message, if Environment::infoLevel() >= noInfoLevel
Definition: Output.hpp:127
static std::optional< T > get(std::string const &key)
Get parameter-values from parameter-tree.
Definition: Initfile.hpp:25
CreatorInterfaceName< BaseClass > * named(CreatorInterface< BaseClass > *ptr)
cast a ptr of CreatorInterface to CreatorInterfaceName
Definition: CreatorInterface.hpp:64
Abstract base class for linear solvers.
Definition: LinearSolverInterface.hpp:27
Default creator for direct solvers.
Definition: SolverCreator.hpp:215
Base solver creator for iterative solvers.
Definition: SolverCreator.hpp:70
Definition: CreatorMap.hpp:16
Definition: CreatorInterfaces.hpp:20
static CreatorInterface< BaseClass > * getCreator(std::string key, std::string initFileStr)
Creates a object of the type corresponding to key.
Definition: CreatorMap.hpp:44
Base class for solver creators,.
Definition: SolverCreator.hpp:37
Default solver creator for iterative solvers.
Definition: SolverCreator.hpp:24
void init(int &argc, char **&argv, std::string const &initFileName="")
Initialized the Environment for MPI.
Definition: AMDiS.hpp:29
void test_exit(bool condition, std::string const &str, Args &&... args)
test for condition and in case of failure print message and exit
Definition: Output.hpp:163
static int mpiRank()
Return the MPI_Rank of the current processor.
Definition: Environment.hpp:68