version 0.4
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
27 enum class SolverTypeTag {
28 none,
45 d_LLT,
46 d_LDLT
47 };
48
53 enum class MatrixTypeTag { Dense, Sparse };
54
61 template <typename ScalarType = double>
63 public:
64 using SparseMatrixType = Eigen::SparseMatrix<ScalarType>;
65 using DenseMatrixType = Eigen::MatrixX<ScalarType>;
66
71 explicit LinearSolverTemplate(const SolverTypeTag& p_solverTypeTag);
72
77
84 LinearSolverTemplate tmp(other);
85 return *this;
86 }
87
92 LinearSolverTemplate(const LinearSolverTemplate& other) { *this = LinearSolverTemplate(other.solverTypeTag); }
97 LinearSolverTemplate(LinearSolverTemplate&& other) noexcept = default;
104
105 private:
106 struct SolverBase {
107 virtual ~SolverBase() = default;
108 virtual void analyzePattern(const DenseMatrixType&) const {}
109 virtual void analyzePattern(const SparseMatrixType&) = 0;
110 virtual void factorize(const DenseMatrixType&) = 0;
111 virtual void factorize(const SparseMatrixType&) = 0;
112 virtual void compute(const SparseMatrixType&) = 0;
113 virtual void compute(const DenseMatrixType&) = 0;
114 virtual void solve(Eigen::VectorX<ScalarType>& x, const Eigen::VectorX<ScalarType>&) const = 0;
115 virtual void solve(Eigen::MatrixX2<ScalarType>& x, const Eigen::MatrixX2<ScalarType>&) const = 0;
116 virtual void solve(Eigen::MatrixX3<ScalarType>& x, const Eigen::MatrixX3<ScalarType>&) const = 0;
117 virtual void solve(Eigen::MatrixX<ScalarType>& x, const Eigen::MatrixX<ScalarType>&) const = 0;
118 };
119
120 template <typename Solver>
121 struct SolverImpl : public SolverBase {
122 using SolverBase::analyzePattern; // forward use of analyzePattern(DenseMatrixType)
123
124 void analyzePattern(const SparseMatrixType& A) final {
125 if constexpr (requires(Solver sol) { sol.analyzePattern(A); }) solver.analyzePattern(A);
126 }
127
128 void factorize(const SparseMatrixType& A) final {
129 if constexpr (requires(Solver sol) { sol.factorize(A); }) solver.factorize(A);
130 }
131
132 // Dense Solvers do not have a factorize method therefore
133 // our interface we just call compute for dense matrices
134 void factorize(const DenseMatrixType& A) final {
135 if constexpr (requires(Solver sol) { sol.compute(A); } && std::is_base_of_v<Eigen::SolverBase<Solver>, Solver>)
136 solver.compute(A);
137 }
138 void compute(const SparseMatrixType& A) final {
139 if constexpr (std::is_base_of_v<Eigen::SparseSolverBase<Solver>, Solver>)
140 solver.compute(A);
141 else
142 DUNE_THROW(Dune::NotImplemented, "This solver does not support solving with sparse matrices.");
143 }
144
145 void compute(const DenseMatrixType& A) final {
146 if constexpr (std::is_base_of_v<Eigen::SolverBase<Solver>, Solver>)
147 solver.compute(A);
148 else
149 DUNE_THROW(Dune::NotImplemented, "This solver does not support solving with dense matrices.");
150 }
151
152 void solve(Eigen::VectorX<ScalarType>& x, const Eigen::VectorX<ScalarType>& b) const final {
153 x = solver.solve(b);
154 }
155
156 void solve(Eigen::MatrixX2<ScalarType>& x, const Eigen::MatrixX2<ScalarType>& b) const final {
157 x = solver.solve(b);
158 }
159
160 void solve(Eigen::MatrixX3<ScalarType>& x, const Eigen::MatrixX3<ScalarType>& b) const final {
161 x = solver.solve(b);
162 }
163
164 void solve(Eigen::MatrixX<ScalarType>& x, const Eigen::MatrixX<ScalarType>& b) const final {
165 x = solver.solve(b);
166 }
167
168 Solver solver;
169 };
170
171 std::unique_ptr<SolverBase> solverimpl;
172 SolverTypeTag solverTypeTag{SolverTypeTag::none};
173
174 public:
181 template <typename MatrixType>
182 requires std::is_same_v<MatrixType, DenseMatrixType> || std::is_same_v<MatrixType, SparseMatrixType>
183 inline LinearSolverTemplate& compute(const MatrixType& A) {
184 solverimpl->compute(A);
185 return *this;
186 }
187
193 template <typename MatrixType>
194 requires std::is_same_v<MatrixType, DenseMatrixType> || std::is_same_v<MatrixType, SparseMatrixType>
195 inline void analyzePattern(const MatrixType& A) { solverimpl->analyzePattern(A); }
196
202 template <typename MatrixType>
203 requires std::is_same_v<MatrixType, DenseMatrixType> || std::is_same_v<MatrixType, SparseMatrixType>
204 inline void factorize(const MatrixType& A) { solverimpl->factorize(A); }
205
211 void solve(Eigen::VectorX<ScalarType>& x, const Eigen::VectorX<ScalarType>& b) { solverimpl->solve(x, b); }
212
218 void solve(Eigen::MatrixX3<ScalarType>& x, const Eigen::MatrixX3<ScalarType>& b) { solverimpl->solve(x, b); }
224 void solve(Eigen::MatrixX2<ScalarType>& x, const Eigen::MatrixX2<ScalarType>& b) { solverimpl->solve(x, b); }
225
231 void solve(Eigen::MatrixX<ScalarType>& x, const Eigen::MatrixX<ScalarType>& b) { solverimpl->solve(x, b); }
232 };
233
235 extern template class LinearSolverTemplate<double>;
236} // namespace Ikarus
Definition: simpleassemblers.hh:21
MatrixTypeTag
Enumeration representing different matrix types (Dense or Sparse).
Definition: linearsolver.hh:53
SolverTypeTag
Enumeration representing different solver types.
Definition: linearsolver.hh:27
LinearSolverTemplate< double > LinearSolver
Definition: linearsolver.hh:234
A type-erased class which wraps most of the linear solvers available in Eigen.
Definition: linearsolver.hh:62
void solve(Eigen::MatrixX< ScalarType > &x, const Eigen::MatrixX< ScalarType > &b)
Solve the linear system for a n times n matrix.
Definition: linearsolver.hh:231
LinearSolverTemplate & operator=(LinearSolverTemplate &&other) noexcept=default
Move assignment operator.
void analyzePattern(const MatrixType &A)
Analyze the pattern of the matrix.
Definition: linearsolver.hh:195
LinearSolverTemplate & compute(const MatrixType &A)
Compute the factorization of the matrix.
Definition: linearsolver.hh:183
Eigen::SparseMatrix< ScalarType > SparseMatrixType
Definition: linearsolver.hh:64
LinearSolverTemplate(const SolverTypeTag &p_solverTypeTag)
Constructor for LinearSolverTemplate.
void solve(Eigen::VectorX< ScalarType > &x, const Eigen::VectorX< ScalarType > &b)
Solve the linear system for a vector.
Definition: linearsolver.hh:211
void solve(Eigen::MatrixX2< ScalarType > &x, const Eigen::MatrixX2< ScalarType > &b)
Solve the linear system for a n times 2 matrix.
Definition: linearsolver.hh:224
LinearSolverTemplate(const LinearSolverTemplate &other)
Copy constructor.
Definition: linearsolver.hh:92
Eigen::MatrixX< ScalarType > DenseMatrixType
Definition: linearsolver.hh:65
LinearSolverTemplate & operator=(const LinearSolverTemplate &other)
Copy assignment operator.
Definition: linearsolver.hh:83
LinearSolverTemplate(LinearSolverTemplate &&other) noexcept=default
Move constructor.
void factorize(const MatrixType &A)
Factorize the matrix.
Definition: linearsolver.hh:204
~LinearSolverTemplate()=default
Destructor for LinearSolverTemplate.
void solve(Eigen::MatrixX3< ScalarType > &x, const Eigen::MatrixX3< ScalarType > &b)
Solve the linear system for a n times 3 matrix.
Definition: linearsolver.hh:218