Dune Core Modules (2.9.0)

solverfactory.hh
1 // SPDX-FileCopyrightText: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
2 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 // vi: set et ts=4 sw=2 sts=2:
5 
6 #ifndef DUNE_ISTL_SOLVERFACTORY_HH
7 #define DUNE_ISTL_SOLVERFACTORY_HH
8 
9 #include <unordered_map>
10 #include <functional>
11 #include <memory>
12 
14 #include <dune/common/singleton.hh>
15 
16 #include "solverregistry.hh"
17 #include <dune/istl/solver.hh>
18 #include <dune/istl/schwarz.hh>
19 #include <dune/istl/novlpschwarz.hh>
20 
21 namespace Dune{
26  // Direct solver factory:
27  template<class M, class X, class Y>
28  using DirectSolverSignature = std::shared_ptr<InverseOperator<X,Y>>(const M&, const ParameterTree&);
29  template<class M, class X, class Y>
30  using DirectSolverFactory = Singleton<ParameterizedObjectFactory<DirectSolverSignature<M,X,Y>>>;
31 
32  // Preconditioner factory:
33  template<class M, class X, class Y>
34  using PreconditionerSignature = std::shared_ptr<Preconditioner<X,Y>>(const std::shared_ptr<M>&, const ParameterTree&);
35  template<class M, class X, class Y>
36  using PreconditionerFactory = Singleton<ParameterizedObjectFactory<PreconditionerSignature<M,X,Y>>>;
37 
38  // Iterative solver factory
39  template<class X, class Y>
40  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&);
41  template<class X, class Y>
42  using IterativeSolverFactory = Singleton<ParameterizedObjectFactory<IterativeSolverSignature<X,Y>>>;
43 
44  // initSolverFactories differs in different compilation units, so we have it
45  // in an anonymous namespace
46  namespace {
47 
53  template<class O>
54  int initSolverFactories(){
55  using M = typename O::matrix_type;
56  using X = typename O::range_type;
57  using Y = typename O::domain_type;
58  using TL = Dune::TypeList<M,X,Y>;
60  addRegistryToFactory<TL>(dsfac, DirectSolverTag{});
62  addRegistryToFactory<TL>(pfac, PreconditionerTag{});
63  using TLS = Dune::TypeList<X,Y>;
65  return addRegistryToFactory<TLS>(isfac, IterativeSolverTag{});
66  }
77  template<class O, class X, class Y>
78  [[deprecated("Use method 'initSolverFactories<O>' instead")]]
79  int initSolverFactories() {
80  return initSolverFactories<O>();
81  }
82  } // end anonymous namespace
83 
84 
85  template<class O, class Preconditioner>
86  std::shared_ptr<Preconditioner> wrapPreconditioner4Parallel(const std::shared_ptr<Preconditioner>& prec,
87  const O&)
88  {
89  return prec;
90  }
91 
92  template<class M, class X, class Y, class C, class Preconditioner>
93  std::shared_ptr<Preconditioner>
94  wrapPreconditioner4Parallel(const std::shared_ptr<Preconditioner>& prec,
95  const std::shared_ptr<OverlappingSchwarzOperator<M,X,Y,C> >& op)
96  {
97  return std::make_shared<BlockPreconditioner<X,Y,C,Preconditioner> >(prec, op->getCommunication());
98  }
99 
100  template<class M, class X, class Y, class C, class Preconditioner>
101  std::shared_ptr<Preconditioner>
102  wrapPreconditioner4Parallel(const std::shared_ptr<Preconditioner>& prec,
103  const std::shared_ptr<NonoverlappingSchwarzOperator<M,X,Y,C> >& op)
104  {
105  return std::make_shared<NonoverlappingBlockPreconditioner<C,Preconditioner> >(prec, op->getCommunication());
106  }
107 
108  template<class M, class X, class Y>
109  std::shared_ptr<ScalarProduct<X>> createScalarProduct(const std::shared_ptr<MatrixAdapter<M,X,Y> >&)
110  {
111  return std::make_shared<SeqScalarProduct<X>>();
112  }
113  template<class M, class X, class Y, class C>
114  std::shared_ptr<ScalarProduct<X>> createScalarProduct(const std::shared_ptr<OverlappingSchwarzOperator<M,X,Y,C> >& op)
115  {
116  return createScalarProduct<X>(op->getCommunication(), op->category());
117  }
118 
119  template<class M, class X, class Y, class C>
120  std::shared_ptr<ScalarProduct<X>> createScalarProduct(const std::shared_ptr<NonoverlappingSchwarzOperator<M,X,Y,C> >& op)
121  {
122  return createScalarProduct<X>(op->getCommunication(), op->category());
123  }
124 
144  template<class Operator>
146  using Domain = typename Operator::domain_type;
147  using Range = typename Operator::range_type;
150 
151  template<class O>
152  using _matrix_type = typename O::matrix_type;
154  static constexpr bool isAssembled = !std::is_same<matrix_type, int>::value;
155 
156  static const matrix_type* getmat(std::shared_ptr<Operator> op){
157  std::shared_ptr<AssembledLinearOperator<matrix_type, Domain, Range>> aop
158  = std::dynamic_pointer_cast<AssembledLinearOperator<matrix_type, Domain, Range>>(op);
159  if(aop)
160  return &aop->getmat();
161  return nullptr;
162  }
163 
164  public:
165 
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  if(op->category()!=SolverCategory::sequential){
177  DUNE_THROW(NotImplemented, "The solver factory does not support parallel direct solvers!");
178  }
179  result = DirectSolverFactory<matrix_type, Domain, Range>::instance().create(type, *mat, config);
180  return result;
181  }
182  }
183  // if no direct solver is found it might be an iterative solver
184  if (!IterativeSolverFactory<Domain, Range>::instance().contains(type)) {
185  DUNE_THROW(Dune::InvalidStateException, "Solver not found in the factory.");
186  }
187  if(!prec){
188  const ParameterTree& precConfig = config.sub("preconditioner");
189  std::string prec_type = precConfig.get<std::string>("type");
190  prec = PreconditionerFactory<Operator, Domain, Range>::instance().create(prec_type, op, precConfig);
191  if (prec->category() != op->category() && prec->category() == SolverCategory::sequential)
192  // try to wrap to a parallel preconditioner
193  prec = wrapPreconditioner4Parallel(prec, op);
194  }
195  std::shared_ptr<ScalarProduct<Domain>> sp = createScalarProduct(op);
196  result = IterativeSolverFactory<Domain, Range>::instance().create(type, op, sp, prec, config);
197  return result;
198  }
199 
203  static std::shared_ptr<Preconditioner> getPreconditioner(std::shared_ptr<Operator> op,
204  const ParameterTree& config){
205  const matrix_type* mat = getmat(op);
206  if(mat){
207  std::string prec_type = config.get<std::string>("type");
208  return PreconditionerFactory<Operator, Domain, Range>::instance().create(prec_type, op, config);
209  }else{
210  DUNE_THROW(InvalidStateException, "Could not obtain matrix from operator. Please pass in an AssembledLinearOperator.");
211  }
212  }
213  };
214 
225  template<class Operator>
226  std::shared_ptr<InverseOperator<typename Operator::domain_type,
227  typename Operator::range_type>> getSolverFromFactory(std::shared_ptr<Operator> op,
228  const ParameterTree& config,
229  std::shared_ptr<Preconditioner<typename Operator::domain_type,
230  typename Operator::range_type>> prec = nullptr){
231  return SolverFactory<Operator>::get(op, config, prec);
232  }
233 
237 } // end namespace Dune
238 
239 
240 #endif
Default exception if a function was called while the object is not in a valid state for that function...
Definition: exceptions.hh:281
Abstract base class for all solvers.
Definition: solver.hh:99
Default exception for dummy implementations.
Definition: exceptions.hh:263
Hierarchical structure of string parameters.
Definition: parametertree.hh:37
std::string get(const std::string &key, const std::string &defaultValue) const
get value as string
Definition: parametertree.cc:185
ParameterTree & sub(const std::string &sub)
get substructure by name
Definition: parametertree.cc:103
Base class for matrix free definition of preconditioners.
Definition: preconditioner.hh:32
An adapter to turn a class into a singleton.
Definition: singleton.hh:56
static DUNE_EXPORT T & instance()
Get the instance of the singleton.
Definition: singleton.hh:70
Factory to assembly solvers configured by a ParameterTree.
Definition: solverfactory.hh:145
static std::shared_ptr< Solver > get(std::shared_ptr< Operator > op, const ParameterTree &config, std::shared_ptr< Preconditioner > prec=nullptr)
get a solver from the factory
Definition: solverfactory.hh:168
static std::shared_ptr< Preconditioner > getPreconditioner(std::shared_ptr< Operator > op, const ParameterTree &config)
Construct a Preconditioner for a given Operator.
Definition: solverfactory.hh:203
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:185
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
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:227
std::tuple< MetaType< T >... > TypeList
A simple type list.
Definition: typelist.hh:87
Dune namespace.
Definition: alignedallocator.hh:13
std::shared_ptr< ScalarProduct< X > > createScalarProduct(const Comm &comm, SolverCategory::Category category)
Definition: scalarproducts.hh:242
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:25
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 18, 22:30, 2024)