Dune Core Modules (2.7.1)

solverfactory.hh
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_ISTL_SOLVERFACTORY_HH
5 #define DUNE_ISTL_SOLVERFACTORY_HH
6 
7 #include <unordered_map>
8 #include <functional>
9 #include <memory>
10 
12 #include <dune/common/singleton.hh>
13 
14 #include <dune/istl/common/registry.hh>
15 #include <dune/istl/solver.hh>
16 
17 #define DUNE_REGISTER_DIRECT_SOLVER(name, ...) \
18  DUNE_REGISTRY_PUT(DirectSolverTag, name, __VA_ARGS__)
19 
20 #define DUNE_REGISTER_PRECONDITIONER(name, ...) \
21  DUNE_REGISTRY_PUT(PreconditionerTag, name, __VA_ARGS__)
22 
23 #define DUNE_REGISTER_ITERATIVE_SOLVER(name, ...) \
24  DUNE_REGISTRY_PUT(IterativeSolverTag, name, __VA_ARGS__)
25 
26 namespace Dune{
31  namespace {
32  struct DirectSolverTag {};
33  struct PreconditionerTag {};
34  struct IterativeSolverTag {};
35  }
36 
37  template<template<class,class,class,int>class Preconditioner, int blockLevel=1>
38  auto defaultPreconditionerBlockLevelCreator(){
39  return [](auto typeList, const auto& matrix, const Dune::ParameterTree& config)
40  {
41  using Matrix = typename Dune::TypeListElement<0, decltype(typeList)>::type;
42  using Domain = typename Dune::TypeListElement<1, decltype(typeList)>::type;
43  using Range = typename Dune::TypeListElement<2, decltype(typeList)>::type;
44  std::shared_ptr<Dune::Preconditioner<Domain, Range>> preconditioner
45  = std::make_shared<Preconditioner<Matrix, Domain, Range, blockLevel>>(matrix, config);
46  return preconditioner;
47  };
48  }
49 
50  template<template<class,class,class>class Preconditioner>
51  auto defaultPreconditionerCreator(){
52  return [](auto typeList, const auto& matrix, const Dune::ParameterTree& config)
53  {
54  using Matrix = typename Dune::TypeListElement<0, decltype(typeList)>::type;
55  using Domain = typename Dune::TypeListElement<1, decltype(typeList)>::type;
56  using Range = typename Dune::TypeListElement<2, decltype(typeList)>::type;
57  std::shared_ptr<Dune::Preconditioner<Domain, Range>> preconditioner
58  = std::make_shared<Preconditioner<Matrix, Domain, Range>>(matrix, config);
59  return preconditioner;
60  };
61  }
62 
63  template<template<class...>class Solver>
64  auto defaultIterativeSolverCreator(){
65  return [](auto typeList,
66  const auto& linearOperator,
67  const auto& scalarProduct,
68  const auto& preconditioner,
69  const Dune::ParameterTree& config)
70  {
71  using Domain = typename Dune::TypeListElement<0, decltype(typeList)>::type;
72  using Range = typename Dune::TypeListElement<1, decltype(typeList)>::type;
73  std::shared_ptr<Dune::InverseOperator<Domain, Range>> solver
74  = std::make_shared<Solver<Domain>>(linearOperator, scalarProduct, preconditioner, config);
75  return solver;
76  };
77  }
78 
79  // Direct solver factory:
80  template<class M, class X, class Y>
81  using DirectSolverSignature = std::shared_ptr<InverseOperator<X,Y>>(const M&, const ParameterTree&);
82  template<class M, class X, class Y>
83  using DirectSolverFactory = Singleton<ParameterizedObjectFactory<DirectSolverSignature<M,X,Y>>>;
84 
85  // Preconditioner factory:
86  template<class M, class X, class Y>
87  using PreconditionerSignature = std::shared_ptr<Preconditioner<X,Y>>(const M&, const ParameterTree&);
88  template<class M, class X, class Y>
89  using PreconditionerFactory = Singleton<ParameterizedObjectFactory<PreconditionerSignature<M,X,Y>>>;
90 
91  // Iterative solver factory
92  template<class X, class Y>
93  using IterativeSolverSignature = std::shared_ptr<InverseOperator<X,Y>>(const std::shared_ptr<LinearOperator<X,Y>>&, const std::shared_ptr<ScalarProduct<X>>&, const std::shared_ptr<Preconditioner<X,Y>>, const ParameterTree&);
94  template<class X, class Y>
95  using IterativeSolverFactory = Singleton<ParameterizedObjectFactory<IterativeSolverSignature<X,Y>>>;
96 
97  // initSolverFactories differs in different compilation units, so we have it
98  // in an anonymous namespace
99  namespace {
100 
101  /* initializes the direct solvers, preconditioners and iterative solvers in
102  the factories with the corresponding Matrix and Vector types.
103 
104  @tparam M the Matrix type
105  @tparam X the Domain type
106  @tparam Y the Range type
107  */
108  template<class M, class X, class Y>
109  int initSolverFactories(){
110  using TL = Dune::TypeList<M,X,Y>;
112  addRegistryToFactory<TL>(dsfac, DirectSolverTag{});
114  addRegistryToFactory<TL>(pfac, PreconditionerTag{});
115  using TLS = Dune::TypeList<X,Y>;
117  return addRegistryToFactory<TLS>(isfac, IterativeSolverTag{});
118  }
119  } // end anonymous namespace
120 
121  /* This exception is thrown, when the requested solver is in the factory but
122  cannot be instantiated for the required template parameters
123  */
124  class UnsupportedType : public NotImplemented {};
125 
145  template<class Operator>
147  using Domain = typename Operator::domain_type;
148  using Range = typename Operator::range_type;
151 
152  template<class O>
153  using _matrix_type = typename O::matrix_type;
155  static constexpr bool isAssembled = !std::is_same<matrix_type, int>::value;
156 
157  static const matrix_type* getmat(std::shared_ptr<Operator> op){
158  std::shared_ptr<AssembledLinearOperator<matrix_type, Domain, Range>> aop
159  = std::dynamic_pointer_cast<AssembledLinearOperator<matrix_type, Domain, Range>>(op);
160  if(aop)
161  return &aop->getmat();
162  return nullptr;
163  }
164  public:
165 
166  /* @brief get a solver from the factory
167  */
168  static std::shared_ptr<Solver> get(std::shared_ptr<Operator> op,
169  const ParameterTree& config,
170  std::shared_ptr<Preconditioner> prec = nullptr){
171  std::string type = config.get<std::string>("type");
172  std::shared_ptr<Solver> result;
173  const matrix_type* mat = getmat(op);
174  if(mat){
176  result = DirectSolverFactory<matrix_type, Domain, Range>::instance().create(type, *mat, config);
177  return result;
178  }
179  }
180  // if no direct solver is found it might be an iterative solver
181  if (!IterativeSolverFactory<Domain, Range>::instance().contains(type)) {
182  DUNE_THROW(Dune::InvalidStateException, "Solver not found in the factory.");
183  }
184  if(!prec){
185  const ParameterTree& precConfig = config.sub("preconditioner");
186  std::string prec_type = precConfig.get<std::string>("type");
187  prec = PreconditionerFactory<matrix_type, Domain, Range>::instance().create(prec_type, *mat, precConfig);
188  }
189  if(op->category()!=SolverCategory::sequential){
190  DUNE_THROW(NotImplemented, "The solver factory is currently only implemented for sequential solvers!");
191  }
192  std::shared_ptr<ScalarProduct<Domain>> sp = std::make_shared<SeqScalarProduct<Domain>>();
193  result = IterativeSolverFactory<Domain, Range>::instance().create(type, op, sp, prec, config);
194  return result;
195  }
196 
197  /*
198  @brief Construct a Preconditioner for a given Operator
199  */
200  static std::shared_ptr<Preconditioner> getPreconditioner(std::shared_ptr<Operator> op,
201  const ParameterTree& config){
202  const matrix_type* mat = getmat(op);
203  if(mat){
204  std::string prec_type = config.get<std::string>("type");
205  return PreconditionerFactory<matrix_type, Domain, Range>::instance().create(prec_type, *mat, config);
206  }else{
207  DUNE_THROW(InvalidStateException, "Could not obtain matrix from operator. Please pass in an AssembledLinearOperator.");
208  }
209  }
210  };
211 
222  template<class Operator>
223  std::shared_ptr<InverseOperator<typename Operator::domain_type,
224  typename Operator::range_type>> getSolverFromFactory(std::shared_ptr<Operator> op,
225  const ParameterTree& config,
226  std::shared_ptr<Preconditioner<typename Operator::domain_type,
227  typename Operator::range_type>> prec = nullptr){
228  return SolverFactory<Operator>::get(op, config, prec);
229  }
230 
234 } // end namespace Dune
235 
236 
237 #endif
Default exception if a function was called while the object is not in a valid state for that function...
Definition: exceptions.hh:279
Abstract base class for all solvers.
Definition: solver.hh:97
Default exception for dummy implementations.
Definition: exceptions.hh:261
Hierarchical structure of string parameters.
Definition: parametertree.hh:35
std::string get(const std::string &key, const std::string &defaultValue) const
get value as string
Definition: parametertree.cc:183
ParameterTree & sub(const std::string &sub)
get substructure by name
Definition: parametertree.cc:101
Base class for matrix free definition of preconditioners.
Definition: preconditioner.hh:30
An adapter to turn a class into a singleton.
Definition: singleton.hh:54
static DUNE_EXPORT T & instance()
Get the instance of the singleton.
Definition: singleton.hh:68
Factory to assembly solvers configured by a ParameterTree.
Definition: solverfactory.hh:146
typename detected_or< Default, Op, Args... >::type detected_or_t
Returns Op<Args...> if that is valid; otherwise returns the fallback type Default.
Definition: type_traits.hh:384
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
std::shared_ptr< InverseOperator< typename Operator::domain_type, typename Operator::range_type > > getSolverFromFactory(std::shared_ptr< Operator > op, const ParameterTree &config, std::shared_ptr< Preconditioner< typename Operator::domain_type, typename Operator::range_type >> prec=nullptr)
Instantiates an InverseOperator from an Operator and a configuration given as a ParameterTree.
Definition: solverfactory.hh:224
std::tuple< MetaType< T >... > TypeList
A simple type list.
Definition: typelist.hh:87
Dune namespace.
Definition: alignedallocator.hh:14
A hierarchical structure of string parameters.
Useful wrapper for creating singletons.
Define general, extensible interface for inverse operators.
@ sequential
Category for sequential solvers.
Definition: solvercategory.hh:23
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)