version 0.4.1
linearsolver.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2024 The Ikarus Developers mueller@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
9#pragma once
10#include <memory>
11#include <type_traits>
12#include <variant>
13
14#include <dune/common/exceptions.hh>
15
16#include <Eigen/Core>
17#include <Eigen/SparseCore>
18
19namespace Ikarus {
20
27enum class SolverTypeTag
28{
29 none,
46 d_LLT,
47 d_LDLT
48};
49
54enum class MatrixTypeTag
55{
56 Dense,
57 Sparse
58};
59
66template <typename ST = double>
68{
69public:
70 using ScalarType = ST;
71 using SparseMatrixType = Eigen::SparseMatrix<ScalarType>;
72 using DenseMatrixType = Eigen::MatrixX<ScalarType>;
73
78 explicit LinearSolverTemplate(const SolverTypeTag& solverTypeTag);
79
84
91 LinearSolverTemplate tmp(other);
92 return *this;
93 }
94
99 LinearSolverTemplate(const LinearSolverTemplate& other) { *this = LinearSolverTemplate(other.solverTypeTag_); }
104 LinearSolverTemplate(LinearSolverTemplate&& other) noexcept = default;
111
112private:
113 struct SolverBase
114 {
115 virtual ~SolverBase() = default;
116 virtual void analyzePattern(const DenseMatrixType&) const {}
117 virtual void analyzePattern(const SparseMatrixType&) = 0;
118 virtual void factorize(const DenseMatrixType&) = 0;
119 virtual void factorize(const SparseMatrixType&) = 0;
120 virtual void compute(const SparseMatrixType&) = 0;
121 virtual void compute(const DenseMatrixType&) = 0;
122 virtual void solve(Eigen::VectorX<ScalarType>& x, const Eigen::VectorX<ScalarType>&) const = 0;
123 virtual void solve(Eigen::MatrixX2<ScalarType>& x, const Eigen::MatrixX2<ScalarType>&) const = 0;
124 virtual void solve(Eigen::MatrixX3<ScalarType>& x, const Eigen::MatrixX3<ScalarType>&) const = 0;
125 virtual void solve(Eigen::MatrixX<ScalarType>& x, const Eigen::MatrixX<ScalarType>&) const = 0;
126 };
127
128 template <typename Solver>
129 struct SolverImpl : public SolverBase
130 {
131 using SolverBase::analyzePattern; // forward use of analyzePattern(DenseMatrixType)
132
133 void analyzePattern(const SparseMatrixType& A) final {
134 if constexpr (requires(Solver sol) { sol.analyzePattern(A); })
135 solver.analyzePattern(A);
136 }
137
138 void factorize(const SparseMatrixType& A) final {
139 if constexpr (requires(Solver sol) { sol.factorize(A); })
140 solver.factorize(A);
141 }
142
143 // Dense Solvers do not have a factorize method therefore
144 // our interface we just call compute for dense matrices
145 void factorize(const DenseMatrixType& A) final {
146 if constexpr (requires(Solver sol) { sol.compute(A); } && std::is_base_of_v<Eigen::SolverBase<Solver>, Solver>)
147 solver.compute(A);
148 }
149 void compute(const SparseMatrixType& A) final {
150 if constexpr (std::is_base_of_v<Eigen::SparseSolverBase<Solver>, Solver>)
151 solver.compute(A);
152 else
153 DUNE_THROW(Dune::NotImplemented, "This solver does not support solving with sparse matrices.");
154 }
155
156 void compute(const DenseMatrixType& A) final {
157 if constexpr (std::is_base_of_v<Eigen::SolverBase<Solver>, Solver>)
158 solver.compute(A);
159 else
160 DUNE_THROW(Dune::NotImplemented, "This solver does not support solving with dense matrices.");
161 }
162
163 void solve(Eigen::VectorX<ScalarType>& x, const Eigen::VectorX<ScalarType>& b) const final { x = solver.solve(b); }
164
165 void solve(Eigen::MatrixX2<ScalarType>& x, const Eigen::MatrixX2<ScalarType>& b) const final {
166 x = solver.solve(b);
167 }
168
169 void solve(Eigen::MatrixX3<ScalarType>& x, const Eigen::MatrixX3<ScalarType>& b) const final {
170 x = solver.solve(b);
171 }
172
173 void solve(Eigen::MatrixX<ScalarType>& x, const Eigen::MatrixX<ScalarType>& b) const final { x = solver.solve(b); }
174
175 Solver solver;
176 };
177
178 std::unique_ptr<SolverBase> solverimpl_;
179 SolverTypeTag solverTypeTag_{SolverTypeTag::none};
180
181public:
188 template <typename MatrixType>
189 requires std::is_same_v<MatrixType, DenseMatrixType> || std::is_same_v<MatrixType, SparseMatrixType>
190 inline LinearSolverTemplate& compute(const MatrixType& A) {
191 solverimpl_->compute(A);
192 return *this;
193 }
194
200 template <typename MatrixType>
201 requires std::is_same_v<MatrixType, DenseMatrixType> || std::is_same_v<MatrixType, SparseMatrixType>
202 inline void analyzePattern(const MatrixType& A) {
203 solverimpl_->analyzePattern(A);
204 }
205
211 template <typename MatrixType>
212 requires std::is_same_v<MatrixType, DenseMatrixType> || std::is_same_v<MatrixType, SparseMatrixType>
213 inline void factorize(const MatrixType& A) {
214 solverimpl_->factorize(A);
215 }
216
222 void solve(Eigen::VectorX<ScalarType>& x, const Eigen::VectorX<ScalarType>& b) { solverimpl_->solve(x, b); }
223
229 void solve(Eigen::MatrixX3<ScalarType>& x, const Eigen::MatrixX3<ScalarType>& b) { solverimpl_->solve(x, b); }
235 void solve(Eigen::MatrixX2<ScalarType>& x, const Eigen::MatrixX2<ScalarType>& b) { solverimpl_->solve(x, b); }
236
242 void solve(Eigen::MatrixX<ScalarType>& x, const Eigen::MatrixX<ScalarType>& b) { solverimpl_->solve(x, b); }
243};
244
246extern template class LinearSolverTemplate<double>;
247} // namespace Ikarus
Definition: simpleassemblers.hh:22
MatrixTypeTag
Enumeration representing different matrix types (Dense or Sparse).
Definition: linearsolver.hh:55
SolverTypeTag
Enumeration representing different solver types.
Definition: linearsolver.hh:28
A type-erased class which wraps most of the linear solvers available in Eigen.
Definition: linearsolver.hh:68
LinearSolverTemplate & compute(const MatrixType &A)
Compute the factorization of the matrix.
Definition: linearsolver.hh:190
LinearSolverTemplate(const SolverTypeTag &solverTypeTag)
Constructor for LinearSolverTemplate.
LinearSolverTemplate & operator=(LinearSolverTemplate &&other) noexcept=default
Move assignment operator.
LinearSolverTemplate(const LinearSolverTemplate &other)
Copy constructor.
Definition: linearsolver.hh:99
void solve(Eigen::MatrixX3< ScalarType > &x, const Eigen::MatrixX3< ScalarType > &b)
Solve the linear system for a n times 3 matrix.
Definition: linearsolver.hh:229
~LinearSolverTemplate()=default
Destructor for LinearSolverTemplate.
void solve(Eigen::MatrixX< ScalarType > &x, const Eigen::MatrixX< ScalarType > &b)
Solve the linear system for a n times n matrix.
Definition: linearsolver.hh:242
void analyzePattern(const MatrixType &A)
Analyze the pattern of the matrix.
Definition: linearsolver.hh:202
LinearSolverTemplate(LinearSolverTemplate &&other) noexcept=default
Move constructor.
Eigen::MatrixX< ScalarType > DenseMatrixType
Definition: linearsolver.hh:72
LinearSolverTemplate & operator=(const LinearSolverTemplate &other)
Copy assignment operator.
Definition: linearsolver.hh:90
ST ScalarType
Definition: linearsolver.hh:70
Eigen::SparseMatrix< ScalarType > SparseMatrixType
Definition: linearsolver.hh:71
void factorize(const MatrixType &A)
Factorize the matrix.
Definition: linearsolver.hh:213
void solve(Eigen::VectorX< ScalarType > &x, const Eigen::VectorX< ScalarType > &b)
Solve the linear system for a vector.
Definition: linearsolver.hh:222
void solve(Eigen::MatrixX2< ScalarType > &x, const Eigen::MatrixX2< ScalarType > &b)
Solve the linear system for a n times 2 matrix.
Definition: linearsolver.hh:235