OpenBEM
Open-source framework for electromagnetic simulation with the boundary element method.
Loading...
Searching...
No Matches
eigen_sparse.hpp
Go to the documentation of this file.
1// OpenBEM - Copyright (C) 2026 Shashwat Sharma
2
3// This file is part of OpenBEM.
4
5// OpenBEM is free software: you can redistribute it and/or modify it under the terms of the
6// GNU General Public License as published by the Free Software Foundation, either version 3
7// of the License, or (at your option) any later version.
8
9// You should have received a copy of the GNU General Public License along with OpenBEM.
10// If not, see <https://www.gnu.org/licenses/>.
11
12
18#ifndef EIGEN_SPARSE_MATRIX_HPP
19#define EIGEN_SPARSE_MATRIX_HPP
20
21#include <vector>
22#include <numeric>
23#include <stdexcept>
24
25#include <external/Eigen/Sparse>
26#include <external/Eigen/SparseLU>
27#include <external/Eigen/IterativeLinearSolvers>
28#include <external/Eigen/SVD>
29#include <external/EigenUnsupported/Eigen/IterativeSolvers>
30
31#include "types.hpp"
32#include "matrix/base.hpp"
33#include "matrix/eigen_base.hpp"
35
36
37namespace bem
38{
39
50template <typename T, int StorageOrder = Eigen::ColMajor>
51class EigenSparseMatrix: public EigenMatrixBase<T, Eigen::SparseMatrix<T, StorageOrder>>
52{
53
54 using MatrixType = Eigen::SparseMatrix<T, StorageOrder>;
56 using base::base;
57 using base::matrix_;
58
59public:
60
61 using base::raw_matrix;
62
69 void preallocate(const std::vector<Index>& nnz) override
70 {
71 triplets_.reserve(std::accumulate(nnz.begin(), nnz.end(), 0));
72 assembled_ = false;
73 return;
74 };
75
76
84 {
85 triplets_.reserve(num_entries);
86 assembled_ = false;
87 return;
88 };
89
90
97 void preallocate_directly(const std::vector<Index>& nnz)
98 {
99 matrix_->reserve(nnz);
100 assembled_ = false;
101 return;
102 };
103
104
108 void assemble() override
109 {
110 if (assembled_)
111 return;
112
113 triplets_.shrink_to_fit();
114 if (insert_mode_on_)
115 matrix_->setFromTriplets(
116 triplets_.begin(),
117 triplets_.end(),
118 [] (const T&, const T &b) { return b; }
119 );
120 else
121 matrix_->setFromTriplets(triplets_.begin(), triplets_.end());
122 triplets_.clear();
123 assembled_ = true;
124 return;
125 };
126
127
134 T value(Index row, Index col) const override
135 {
136 return matrix_->coeff(row, col);
137 };
138
139
149 void set_value(Index row, Index col, const T& a) override
150 {
151 triplets_.push_back(Eigen::Triplet<T> (row, col, a));
152 insert_mode_on_ = true;
153 assembled_ = false;
154 return;
155 };
156
157
165 {
166 matrix_->coeffRef(row, col) = a;
167 matrix_->makeCompressed();
168 return;
169 };
170
171
182 void add_value(Index row, Index col, const T& a) override
183 {
184 triplets_.push_back(Eigen::Triplet<T> (row, col, a));
185 insert_mode_on_ = false;
186 assembled_ = false;
187 return;
188 };
189
190
198 {
199 matrix_->coeffRef(row, col) += a;
200 return;
201 };
202
203
208 void scale(const T& a) override
209 {
210 for (Index kk = 0; kk < matrix_->outerSize(); ++kk)
211 for (typename MatrixType::InnerIterator it((*matrix_), kk); it; ++it)
212 it.valueRef() = a * it.value();
213 matrix_->makeCompressed();
214 return;
215 };
216
217
222 {
223 solver_.compute((*matrix_));
224 if (solver_.info() != Eigen::Success)
225 throw std::runtime_error("Matrix decomposition failed.");
226 factorized_ = true;
227 return;
228 };
229
230
238 void mat_solve(MatrixBase<T>& x, const MatrixBase<T>& b) override
239 {
240 if (!factorized_)
241 factorize();
242
243 const EigenDenseMatrix<T>& bd = dynamic_cast<const EigenDenseMatrix<T>&> (b);
244 EigenDenseMatrix<T>& xd = dynamic_cast<EigenDenseMatrix<T>&> (x);
245
246 xd.raw_matrix() = solver_.solve(bd.raw_matrix());
247
248 if (solver_.info() != Eigen::Success)
249 throw std::runtime_error("Matrix solve failed.");
250
251 return;
252 };
253
254
263 const MatrixBase<T>& x,
266 const T& a = T(1)
267 ) override
268 {
269 const EigenSparseMatrix<T>& xd = dynamic_cast<const EigenSparseMatrix<T>&> (x);
270
271 std::vector<Eigen::Triplet<T>> x_triplets;
272 x_triplets.reserve(xd.raw_matrix().nonZeros());
273
274 for (Index kk = 0; kk < xd.raw_matrix().outerSize(); ++kk)
275 for (typename MatrixType::InnerIterator it (xd.raw_matrix(), kk); it; ++it)
276 x_triplets.push_back(Eigen::Triplet<T> (row_start + it.row(), col_start + it.col(), it.value() * a));
277
278 matrix_->insertFromTriplets(
279 x_triplets.begin(),
280 x_triplets.end(),
281 [] (const T&, const T &b) { return b; }
282 );
283
284 return;
285 };
286
287
297 const MatrixBase<T>& x,
300 const T& a = T(1)
301 ) override
302 {
303 const EigenSparseMatrix<T>& xd = dynamic_cast<const EigenSparseMatrix<T>&> (x);
304
305 std::vector<Eigen::Triplet<T>> x_triplets;
306 x_triplets.reserve(xd.raw_matrix().nonZeros());
307
308 for (Index kk = 0; kk < xd.raw_matrix().outerSize(); ++kk)
309 for (typename MatrixType::InnerIterator it (xd.raw_matrix(), kk); it; ++it)
310 x_triplets.push_back(Eigen::Triplet<T> (row_start + it.row(), col_start + it.col(), it.value() * a));
311
312 matrix_->insertFromTriplets(x_triplets.begin(), x_triplets.end());
313
314 return;
315 };
316
317
332 ) const override
333 {
334 EigenSparseMatrix<T>& xd = dynamic_cast<EigenSparseMatrix<T>&> (x);
335 xd.resize(b_rows, b_cols);
336 xd.raw_matrix() = matrix_->block(row_start, col_start, b_rows, b_cols);
337 return;
338 };
339
340
345 virtual const T* data() const override
346 { return matrix_->valuePtr(); };
347
348
353 virtual T* data() override
354 { return matrix_->valuePtr(); };
355
356
357private:
358
359 std::vector<Eigen::Triplet<T>> triplets_;
360 bool insert_mode_on_ = true;
361 bool assembled_ = false;
362
363 Eigen::SparseLU<MatrixType> solver_;
364 bool factorized_ = false;
365
366};
367
372}
373
374#endif
Base class for Eigen-based matrices.
MatrixType & raw_matrix()
Returns a writable reference to the underlying raw matrix - use with caution.
Eigen-based sparse matrix wrapper.
void set_block(const MatrixBase< T > &x, Index row_start, Index col_start, const T &a=T(1)) override
Sets a block of values in this matrix to the values of a given matrix, starting at a given position.
void set_value(Index row, Index col, const T &a) override
Sets the matrix value at the specified row and column.
void factorize()
Computes and stores the LU factors using sparse factorization. The original matrix is not modified.
void mat_solve(MatrixBase< T > &x, const MatrixBase< T > &b) override
Solves for matrix with a direct solver, where is this matrix, and is a given right-hand side matr...
virtual T * data() override
Returns a writable pointer to the underlying raw data - use with care.
void add_block(const MatrixBase< T > &x, Index row_start, Index col_start, const T &a=T(1)) override
Adds a block of values to this matrix from the values of a given matrix, starting at a given position...
void preallocate_directly(const std::vector< Index > &nnz)
Preallocates memory for a given number of non-zero values per row.
void add_value_directly(Index row, Index col, const T &a)
Adds to the matrix value at the specified row and column directly, without using a cache.
void assemble() override
Assembles cached data into the matrix.
T value(Index row, Index col) const override
Returns the matrix value at the specified row and column.
void preallocate(const std::vector< Index > &nnz) override
Preallocates memory for a given number of non-zero values per row.
void preallocate(Index num_entries) override
Preallocates memory for a given total number of non-zero values.
virtual const T * data() const override
Returns a read-only pointer to the underlying raw data.
void add_value(Index row, Index col, const T &a) override
Adds to the matrix value at the specified row and column.
void get_block(MatrixBase< T > &x, Index row_start, Index col_start, Index b_rows, Index b_cols) const override
Retrieves a block of values from this matrix.
void scale(const T &a) override
Scales all matrix entries by a given value.
void set_value_directly(Index row, Index col, const T &a)
Sets the matrix value at the specified row and column directly, without using a cache.
Eigen::Matrix< T, N, 1 > EigColVecN
Fixed-size column vector of size N containing type T.
Definition types.hpp:86
std::size_t Index
Unsigned integer type for indices and container sizes.
Definition types.hpp:54
Primary namespace for the OpenBEM library.
Definition constants.hpp:31