6 #pragma GCC diagnostic ignored "-Wint-in-bool-context"
7 #pragma GCC diagnostic ignored "-Wduplicated-branches"
12 #include <Eigen/IterativeLinearSolvers>
13 #include <Eigen/SparseLU>
20 class SparseMatrix::Impl {
22 Eigen::SparseMatrix<Float> matrix;
25 using SparseVector = Eigen::Matrix<Float, Eigen::Dynamic, 1>;
28 Impl(
const Size rows,
const Size cols)
29 : matrix(rows, cols) {}
32 SPH_ASSERT(i < matrix.innerSize() && j < matrix.innerSize(), i, j);
33 triplets.
push(Eigen::Triplet<Float>(i, j, value));
38 const Float tolerance) {
43 matrix.setFromTriplets(triplets.
begin(), triplets.
end());
47 b.resize(values.
size());
48 for (
Size i = 0; i < values.
size(); ++i) {
55 Eigen::SparseLU<Eigen::SparseMatrix<Float>, Eigen::COLAMDOrdering<int>> solver;
56 a = solveImpl(solver, b);
63 const Size n = matrix.innerSize();
64 for (
Size i = 0; i < n; ++i) {
65 for (
Size j = i; j < n; ++j) {
66 const Float mij = matrix.coeff(i, j);
67 const Float mji = matrix.coeff(j, i);
73 Eigen::ConjugateGradient<Eigen::SparseMatrix<Float>, Eigen::Lower | Eigen::Upper> solver;
74 if (tolerance > 0._f) {
75 solver.setTolerance(tolerance);
77 a = solveImpl(solver, b);
81 Eigen::LeastSquaresConjugateGradient<Eigen::SparseMatrix<Float>> solver;
82 if (tolerance > 0._f) {
83 solver.setTolerance(tolerance);
85 a = solveImpl(solver, b);
89 Eigen::BiCGSTAB<Eigen::SparseMatrix<Float>> solver;
90 if (tolerance > 0._f) {
91 solver.setTolerance(tolerance);
93 a = solveImpl(solver, b);
101 return makeUnexpected<Array<Float>>(a.
error());
104 result.
resize(matrix.outerSize());
105 for (
Size i = 0; i < result.
size(); ++i) {
106 result[i] = a.
value()(i);
112 template <
typename TSolver>
114 solver.compute(matrix);
115 if (solver.info() != Eigen::Success) {
116 return makeUnexpected<SparseVector>(
"Decomposition of matrix failed");
120 if (solver.info() != Eigen::Success) {
121 return makeUnexpected<SparseVector>(
"Equations cannot be solved");
130 : impl(
makeAuto<Impl>(rows, cols)) {}
135 impl = makeAuto<Impl>(rows, cols);
139 impl->insert(i, j, value);
144 const Float tolerance) {
145 return impl->solve(values, solver, tolerance);
INLINE bool almostEqual(const AffineMatrix &m1, const AffineMatrix &m2, const Float eps=EPS)
#define SPH_ASSERT(x,...)
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
INLINE AutoPtr< T > makeAuto(TArgs &&... args)
uint32_t Size
Integral type used to index arrays (by default).
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
#define NAMESPACE_SPH_END
Sparse matrix with utility functions (a thin wrapper over Eigen3 implementation)
Generic dynamically allocated resizable storage.
void resize(const TCounter newSize)
Resizes the array to new size.
INLINE Iterator< StorageType > end() noexcept
INLINE void push(U &&u)
Adds new element to the end of the array, resizing the array if necessary.
INLINE TCounter size() const noexcept
INLINE Iterator< StorageType > begin() noexcept
Wrapper of type that either contains a value of given type, or an error message.
const Error & error() const
Returns the error message.
Type & value()
Returns the reference to expected value.
void insert(const Size i, const Size j, const Float value)
Adds a values to given element of the matrix.
void resize(const Size rows, const Size cols)
Changes the size of the matrix, removing all previous entries.
Expected< Array< Float > > solve(const Array< Float > &values, const Solver solver, const Float tolerance=0.)
Solver
Solvers of sparse systems.
@ BICGSTAB
Stabilized bi-conjugate gradient method, can be used for any square matrix.
@ LSCG
Least-square conjugate gradient, can be used for any matrix.
@ LU
LU factorization, precise but very slow for large problems.