DUNE PDELab (2.7)

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
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
26namespace 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
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
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
Define general, extensible interface for inverse operators.
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.
@ sequential
Category for sequential solvers.
Definition: solvercategory.hh:23
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)