Dune::Copasi
Loading...
Searching...
No Matches
direct.hh
Go to the documentation of this file.
1#ifndef DUNE_COPASI_SOLVER_ISTL_FACTORY_DIRECT_HH
2#define DUNE_COPASI_SOLVER_ISTL_FACTORY_DIRECT_HH
3
8
9#if HAVE_SUITESPARSE_UMFPACK
11#define DUNE_COPASI_DEFAULT_DIRECT_SOLVER "UMFPack"
12#endif
13
14#include <dune/istl/solver.hh>
15#include <dune/istl/superlu.hh>
16
17#include <dune/common/exceptions.hh>
18#include <dune/common/indices.hh>
19
20#include <fmt/ranges.h>
21
22namespace Dune::Copasi::ISTL {
23
24// Iterative solver factory
25template<class M, class X, class Y, class A>
27 std::shared_ptr<InverseOperator<X, Y>>(const std::shared_ptr<AssembledLinearOperator<M, X, Y>>&,
28 const ParameterTree&,
29 const A&);
30template<class M, class X, class Y, class A>
32
33namespace Impl {
34template<class Op, class Alloc>
35auto
36denseInverseFactory()
37{
38 using M = typename Op::matrix_type;
39 using X = typename Op::domain_type;
40 using Y = typename Op::range_type;
41 return [](const std::shared_ptr<AssembledLinearOperator<M, X, Y>>& op,
42 const ParameterTree& config,
43 const Alloc& alloc) -> std::shared_ptr<InverseOperator<X, Y>> {
44 static_assert(blockLevel<M>() == 1, "Matrices for this solver can only be 1 level depth");
45 std::shared_ptr<InverseOperator<X, Y>> inverse_op;
46 using namespace Dune::Indices;
47 const auto& mat = op->getmat();
48 Hybrid::switchCases(
49 Hybrid::integralRange(1_uc, 20_uc),
50 mat.N(),
51 [&](auto n) {
52 if (mat.M() != n)
53 throw format_exception(InvalidStateException{},
54 "Matrix {}x{} is not square!",
55 mat.N(),
56 mat.M());
57 // compute inverse out of the matrix
60 for (auto row_it = mat.begin(); row_it != mat.end(); ++row_it)
61 for (auto col_it = row_it->begin(); col_it != row_it->end(); ++col_it)
62 inverse[row_it.index()][col_it.index()] = *col_it;
63 inverse.invert(config.get("pivoting", true));
64
65 // make an allocator for this solver
67 using SolverAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<Solver>;
69
70 inverse_op = std::allocate_shared<Solver>(ialloc, std::move(inverse));
71 },
72 [] { throw format_exception(NotImplemented{}, "Dense inverses are only implemented up to 19 entries"); });
73 return inverse_op;
74 };
75}
76
77#if HAVE_SUPERLU
78template<class Op, class Alloc>
79auto
81{
82 using M = typename Op::matrix_type;
83 using X = typename Op::domain_type;
84 using Y = typename Op::range_type;
85 return [](const std::shared_ptr<AssembledLinearOperator<M, X, Y>>& op,
86 const ParameterTree& config,
87 const Alloc& alloc) -> std::shared_ptr<InverseOperator<X, Y>> {
88 static_assert(blockLevel<M>() == 1, "Matrices for this solver can only be 1 level depth");
89 std::shared_ptr<InverseOperator<X, Y>> inverse_op;
90 auto verbosity = config.get("verbosity", 0);
91 auto reuse_vector = config.get("reuse_vector", 0);
92 // make an allocator for this solver
93 using Solver = Dune::SuperLU<M>;
94 using SolverAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<Solver>;
96 // TODO(sospinar): check if forwarding allocator to superlu is possible
97 inverse_op = std::allocate_shared<Solver>(ialloc, op->getmat(), verbosity, reuse_vector);
98 return inverse_op;
99 };
100}
101#endif // HAVE_SUPERLU
102
103} // namespace Impl
104
105template<Concept::AssembledLinearOperator O, class Alloc>
106const DirectSolverRegistry<typename O::matrix_type,
107 typename O::domain_type,
108 typename O::range_type,
109 Alloc>&
111{
112 using M = typename O::matrix_type;
113 using X = typename O::domain_type;
114 using Y = typename O::range_type;
115 // initialize a unique registry instance
117 // register possible solver factories
118 static std::once_flag flag;
119 std::call_once(flag, [] {
120 if constexpr (blockLevel<M>() == 1)
121 registry.define("DenseInverse", Impl::denseInverseFactory<O, Alloc>());
122#if HAVE_SUITESPARSE_UMFPACK
123 registry.define("UMFPack", UMFPackWapper<O, Alloc>::factory());
124#endif // HAVE_SUITESPARSE_UMFPACK
125#if HAVE_SUPERLU
126 if constexpr (blockLevel<M>() == 1)
127 registry.define("SuperLU", Impl::superLUFactory<O, Alloc>());
128#endif // HAVE_SUPERLU
129 });
130 return registry;
131}
132
133template<Concept::AssembledLinearOperator Op, class Alloc = std::allocator<Op>>
134std::shared_ptr<InverseOperator<typename Op::domain_type, typename Op::range_type>>
135makeDirectSolver(const std::shared_ptr<Op>& op,
136 const ParameterTree& config,
137 const Alloc& alloc = Alloc())
138{
139 assert(op);
140 auto& registry = getDirectSolverRegistry<Op, Alloc>();
141#ifdef DUNE_COPASI_DEFAULT_DIRECT_SOLVER
142 auto type_name = config.get("type", DUNE_COPASI_DEFAULT_DIRECT_SOLVER);
143#else
144 auto type_name = config.get("type", "None");
145#endif
146 if (registry.contains(type_name))
147 return registry.create(type_name, op, config, alloc);
148 else
149 throw format_exception(IOError{},
150 "The key '{}' is not a known direct solver type. Allowed types are {}",
151 type_name,
152 registry.keys());
153}
154
155} // Dune::Copasi::ISTL
156
157#endif // DUNE_COPASI_SOLVER_ISTL_FACTORY_DIRECT_HH
Definition umfpack.hh:26
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 block_jacobi.hh:14
ParameterizedObjectFactoryWrapper< DirectSolverFactorySignature< M, X, Y, A > > DirectSolverRegistry
Definition direct.hh:31
const DirectSolverRegistry< typename O::matrix_type, typename O::domain_type, typename O::range_type, Alloc > & getDirectSolverRegistry()
Definition direct.hh:110
std::shared_ptr< InverseOperator< X, Y > >(const std::shared_ptr< AssembledLinearOperator< M, X, Y > > &, const ParameterTree &, const A &) DirectSolverFactorySignature
Definition direct.hh:26
std::shared_ptr< InverseOperator< typename Op::domain_type, typename Op::range_type > > makeDirectSolver(const std::shared_ptr< Op > &op, const ParameterTree &config, const Alloc &alloc=Alloc())
Definition direct.hh:135
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
Definition dense_inverse.hh:10