Dune::Copasi
Loading...
Searching...
No Matches
preconditioner.hh
Go to the documentation of this file.
1#ifndef DUNE_COPASI_SOLVER_ISTL_FACTORY_PRECONDITIONER_HH
2#define DUNE_COPASI_SOLVER_ISTL_FACTORY_PRECONDITIONER_HH
3
8
9#include <dune/istl/blocklevel.hh>
10#include <dune/istl/preconditioner.hh>
11#include <dune/istl/preconditioners.hh>
12
13#include <dune/common/parameterizedobject.hh>
14
15#include <fmt/ranges.h>
16
17#define DUNE_COPASI_DEFAULT_PRECONDITIONER "SSOR"
18
19namespace Dune::Copasi::ISTL {
20
21template<Concept::LinearOperator O, class A>
23 std::shared_ptr<Preconditioner<typename O::domain_type, typename O::range_type>>(
24 const std::shared_ptr<O>&,
25 const ParameterTree&,
26 const A&);
27template<Concept::LinearOperator O, class A>
29
30namespace Impl {
31
32template<class Prec, class Alloc, bool matrix_free = false>
33auto
34defaultPreconditionerFactory(std::bool_constant<matrix_free> = {})
35{
36 using X = typename Prec::domain_type;
37 using Y = typename Prec::range_type;
38 return [&](const std::shared_ptr<LinearOperator<X, Y>>& op,
39 const ParameterTree& config,
40 const Alloc& alloc) -> std::shared_ptr<Preconditioner<X, Y>> {
41 // make an allocator for this preconditioner
42 using PrecAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<Prec>;
44
45 // construct preconditioner instance
46 if constexpr (matrix_free) {
47 return std::allocate_shared<Prec>(palloc, config);
48 } else {
49 using M = typename Prec::matrix_type; // cast operator to something the preconditioner expects
50 auto aop = std::dynamic_pointer_cast<AssembledLinearOperator<M, X, Y>>(op);
51 if (not aop)
52 throw format_exception(InvalidStateException{}, "Linear operator does not hold a matrix!");
53 return std::allocate_shared<Prec>(palloc, aop, config);
54 }
55 };
56}
57
58template<class X, class Y, class Alloc>
59auto
60inverseOperator2PreconditionerFactory()
61{
62 return [](const std::shared_ptr<LinearOperator<X, Y>>& op,
63 const ParameterTree& config,
64 const Alloc& alloc) -> std::shared_ptr<Preconditioner<X, Y>> {
65 // wrapper: make sure inverse operator is stored somewhere
66 struct Prec : public Dune::InverseOperator2Preconditioner<InverseOperator<X, Y>>
67 {
68 using InverseOperator2Preconditioner<InverseOperator<X, Y>>::InverseOperator2Preconditioner;
69 std::shared_ptr<InverseOperator<X, Y>> inverse;
70 };
71
72 // make an allocator for this preconditioner
73 using PrecAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<Prec>;
75
76 // make actual inverse operator and bind memory it to the wrapper
77 // note that ADL tag is important because this function is not be yet defined!
78 auto inverse = makeInverseOperator(op, config.sub("solver"), alloc, Impl::ADLTag{});
79 auto prec = std::allocate_shared<Prec>(palloc, *inverse);
80 prec->inverse = std::move(inverse);
81 return prec;
82 };
83}
84
85}
86
87template<Concept::LinearOperator O, class Alloc>
90{
91 using X = typename O::domain_type;
92 using Y = typename O::range_type;
94 static std::once_flag flag;
95 std::call_once(flag, [] {
96 registry.define("Richardson", Impl::defaultPreconditionerFactory<Richardson<X, Y>, Alloc>(std::true_type()));
97 registry.define("InverseOperator", Impl::inverseOperator2PreconditionerFactory<X, Y, Alloc>());
98 // preconditioner that need a matrix
100 using M = typename O::matrix_type;
101 registry.define("Jacobi", Impl::defaultPreconditionerFactory<SeqJac<M, X, Y, blockLevel<M>()>, Alloc>());
102 registry.define("SSOR", Impl::defaultPreconditionerFactory<SeqSSOR<M, X, Y, blockLevel<M>()>, Alloc>());
103 registry.define("SOR", Impl::defaultPreconditionerFactory<SeqSOR<M, X, Y, blockLevel<M>()>, Alloc>());
104 registry.define("GaussSeidel", Impl::defaultPreconditionerFactory<SeqGS<M, X, Y, blockLevel<M>()>, Alloc>());
105 // preconditioner that only have valid instantiation with matrices of depth level 1
106 if constexpr (blockLevel<M>() == 1) {
107 registry.define("DILU", Impl::defaultPreconditionerFactory<SeqDILU<M, X, Y>, Alloc>());
108 registry.define("ILU", Impl::defaultPreconditionerFactory<SeqILU<M, X, Y>, Alloc>());
109 registry.define("ILDL", Impl::defaultPreconditionerFactory<SeqILDL<M, X, Y>, Alloc>());
110 }
111 if constexpr (blockLevel<M>() >= 1) {
112 registry.define("BlockJacobi", BlockJacobi<O, Alloc>::factory());
113 }
114 }
115 });
116 return registry;
117}
118
119template<Concept::LinearOperator Op, class Alloc = std::allocator<Op>>
120std::shared_ptr<Preconditioner<typename Op::domain_type, typename Op::range_type>>
121makePreconditioner(const std::shared_ptr<Op>& op,
122 const ParameterTree& config,
123 const Alloc& alloc = Alloc())
124{
125 assert(op);
128 if (config.get("verbosity", 1) > 0)
129 spdlog::info("Creating preconditioner with type '{}'", type_name);
130 if (registry.contains(type_name))
131 return registry.create(type_name, op, config, alloc);
132 else
134 "The key '{}' is not a known preconditioner type. Allowed types are {}",
135 type_name,
136 registry.keys());
137}
138
139} // Dune::Copasi::ISTL
140
141#endif // DUNE_COPASI_SOLVER_ISTL_FACTORY_PRECONDITIONER_HH
Definition block_jacobi.hh:18
simple wrapper that captures and exposes the keys of Dune::ParameterizedObjectFactory
Definition parameterized_object.hh:14
Definition block_jacobi.hh:14
const PreconditionerRegistry< O, Alloc > & getPreconditionerRegistry()
Definition preconditioner.hh:89
std::shared_ptr< Preconditioner< typename Op::domain_type, typename Op::range_type > > makePreconditioner(const std::shared_ptr< Op > &op, const ParameterTree &config, const Alloc &alloc=Alloc())
Definition preconditioner.hh:121
std::shared_ptr< Preconditioner< typename O::domain_type, typename O::range_type > >( const std::shared_ptr< O > &, const ParameterTree &, const A &) PreconditionerFactorySignature
Definition preconditioner.hh:22
auto format_exception(Exception &&e, fmt::format_string< Args... > format, Args &&... args)
Definition exceptions.hh:23
constexpr bool is_bitflags_v
Alias for Bitflag indicator.
Definition bit_flags.hh:24
#define DUNE_COPASI_DEFAULT_PRECONDITIONER
Definition preconditioner.hh:17