1#ifndef DUNE_COPASI_SOLVER_ISTL_FACTORY_PRECONDITIONER_HH
2#define DUNE_COPASI_SOLVER_ISTL_FACTORY_PRECONDITIONER_HH
9#include <dune/istl/blocklevel.hh>
10#include <dune/istl/preconditioner.hh>
11#include <dune/istl/preconditioners.hh>
13#include <dune/common/parameterizedobject.hh>
15#include <fmt/ranges.h>
17#define DUNE_COPASI_DEFAULT_PRECONDITIONER "SSOR"
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>&,
27template<Concept::LinearOperator O,
class A>
32template<
class Prec,
class Alloc,
bool matrix_free = false>
34defaultPreconditionerFactory(std::bool_constant<matrix_free> = {})
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>> {
42 using PrecAlloc =
typename std::allocator_traits<Alloc>::template rebind_alloc<Prec>;
43 PrecAlloc palloc(alloc);
46 if constexpr (matrix_free) {
47 return std::allocate_shared<Prec>(palloc, config);
49 using M =
typename Prec::matrix_type;
50 auto aop = std::dynamic_pointer_cast<AssembledLinearOperator<M, X, Y>>(op);
52 throw format_exception(InvalidStateException{},
"Linear operator does not hold a matrix!");
53 return std::allocate_shared<Prec>(palloc, aop, config);
58template<
class X,
class Y,
class Alloc>
60inverseOperator2PreconditionerFactory()
62 return [](
const std::shared_ptr<LinearOperator<X, Y>>& op,
63 const ParameterTree& config,
64 const Alloc& alloc) -> std::shared_ptr<Preconditioner<X, Y>> {
66 struct Prec :
public Dune::InverseOperator2Preconditioner<InverseOperator<X, Y>>
68 using InverseOperator2Preconditioner<InverseOperator<X, Y>>::InverseOperator2Preconditioner;
69 std::shared_ptr<InverseOperator<X, Y>> inverse;
73 using PrecAlloc =
typename std::allocator_traits<Alloc>::template rebind_alloc<Prec>;
74 PrecAlloc palloc(alloc);
79 auto prec = std::allocate_shared<Prec>(palloc, *inverse);
80 prec->inverse = std::move(inverse);
87template<Concept::LinearOperator O,
class Alloc>
88const PreconditionerRegistry<O, Alloc>&
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>());
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>());
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>());
111 if constexpr (blockLevel<M>() >= 1) {
119template<Concept::LinearOperator Op,
class Alloc = std::allocator<Op>>
120std::shared_ptr<Preconditioner<typename Op::domain_type, typename Op::range_type>>
122 const ParameterTree& config,
123 const Alloc& alloc = Alloc())
126 const auto& registry = getPreconditionerRegistry<Op, Alloc>();
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);
134 "The key '{}' is not a known preconditioner type. Allowed types are {}",
Definition: block_jacobi.hh:18
simple wrapper that captures and exposes the keys of Dune::ParameterizedObjectFactory
Definition: parameterized_object.hh:14
void define(Key const &key, T &&t)
Definition: parameterized_object.hh:21
Definition: concepts.hh:14
Definition: block_jacobi.hh:14
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:26
const PreconditionerRegistry< O, Alloc > & getPreconditionerRegistry()
Definition: preconditioner.hh:89
std::shared_ptr< InverseOperator< typename Op::domain_type, typename Op::range_type > > makeInverseOperator(const std::shared_ptr< Op > &op, const ParameterTree &config, const Alloc &alloc=Alloc())
Definition: inverse.hh:65
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
auto format_exception(Exception &&e, fmt::format_string< Args... > format, Args &&... args)
Definition: exceptions.hh:23
#define DUNE_COPASI_DEFAULT_PRECONDITIONER
Definition: preconditioner.hh:17