PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
Cholmod.h
1// clang-format off
2#ifdef PBAT_USE_SUITESPARSE
3
4#ifndef PBAT_MATH_LINALG_CHOLMOD_H
5#define PBAT_MATH_LINALG_CHOLMOD_H
6
7#include "pbat/Aliases.h"
8#include "PhysicsBasedAnimationToolkitExport.h"
9
10#include <exception>
11#include <suitesparse/cholmod.h>
12#include <type_traits>
13// clang-format on
14
15namespace pbat {
16namespace math {
17namespace linalg {
18
19class Cholmod
20{
21 public:
22 static_assert(
23 std::is_same_v<Scalar, double>,
24 "Cholmod implementation uses double floating point coefficients");
25 static_assert(
26 std::is_same_v<CSCMatrix::StorageIndex, std::int32_t>,
27 "Cholmod implementation uses 32-bit integer indices");
28
29 enum class ESparseStorage {
30 SymmetricLowerTriangular = -1,
31 Unsymmetric = 0,
32 SymmetricUpperTriangular = 1
33 };
34
35 PBAT_API Cholmod();
36
37 template <class Derived>
38 void Analyze(
39 Eigen::SparseCompressedBase<Derived> const& A,
40 ESparseStorage storage = ESparseStorage::SymmetricLowerTriangular);
41
42 template <class Derived>
43 bool Factorize(
44 Eigen::SparseCompressedBase<Derived> const& A,
45 ESparseStorage storage = ESparseStorage::SymmetricLowerTriangular);
46
47 template <class Derived>
48 bool Compute(
49 Eigen::SparseCompressedBase<Derived> const& A,
50 ESparseStorage storage = ESparseStorage::SymmetricLowerTriangular);
51
52 template <class Derived>
53 bool Update(Eigen::SparseCompressedBase<Derived> const& U);
54
55 template <class Derived>
56 bool Downdate(Eigen::SparseCompressedBase<Derived> const& U);
57
58 PBAT_API MatrixX Solve(Eigen::Ref<MatrixX const> const& B) const;
59
60 PBAT_API ~Cholmod();
61
62 private:
63 template <class Derived>
64 void ToCholmodView(
65 Eigen::SparseCompressedBase<Derived> const& A,
66 ESparseStorage storage,
67 cholmod_sparse& cholmod_A) const;
68
69 PBAT_API void Deallocate();
70
71 cholmod_common mCholmodCommon;
72 cholmod_factor* mCholmodL;
73};
74
75template <class Derived>
76inline void Cholmod::Analyze(Eigen::SparseCompressedBase<Derived> const& A, ESparseStorage storage)
77{
78 Deallocate();
79 cholmod_sparse cholmod_A{};
80 ToCholmodView(A, storage, cholmod_A);
81 mCholmodL = cholmod_analyze(&cholmod_A, &mCholmodCommon);
82 if (mCholmodL == NULL)
83 throw std::runtime_error("Symbolic analysis of Cholesky factor failed");
84}
85
86template <class Derived>
87inline bool
88Cholmod::Factorize(Eigen::SparseCompressedBase<Derived> const& A, ESparseStorage storage)
89{
90 if (mCholmodL == NULL)
91 Analyze(A, storage);
92
93 cholmod_sparse cholmod_A;
94 ToCholmodView(A, storage, cholmod_A);
95 int const ec = cholmod_factorize(&cholmod_A, mCholmodL, &mCholmodCommon);
96 return ec == 1;
97}
98
99template <class Derived>
100inline bool Cholmod::Compute(Eigen::SparseCompressedBase<Derived> const& A, ESparseStorage storage)
101{
102 return Factorize(A, storage);
103}
104
105template <class Derived>
106inline bool Cholmod::Update(Eigen::SparseCompressedBase<Derived> const& U)
107{
108 cholmod_sparse cholmod_U{};
109 ToCholmodView(U, ESparseStorage::Unsymmetric, cholmod_U);
110 cholmod_sparse* cholmod_PU = cholmod_submatrix(
111 &cholmod_U,
112 static_cast<std::int32_t*>(mCholmodL->Perm) /*Fill-reducing permutation*/,
113 static_cast<long long>(mCholmodL->n) /*Number of rows*/,
114 NULL /*No column permutation*/,
115 -1 /*all columns*/,
116 1 /*TRUE*/,
117 1 /*TRUE*/,
118 &mCholmodCommon);
119 int const ec = cholmod_updown(1 /*TRUE == update*/, cholmod_PU, mCholmodL, &mCholmodCommon);
120 cholmod_free_sparse(&cholmod_PU, &mCholmodCommon);
121 return ec == 1 /*success*/;
122}
123
124template <class Derived>
125inline bool Cholmod::Downdate(Eigen::SparseCompressedBase<Derived> const& U)
126{
127 // NOTE: Implementation copied from Update, except that FALSE is passed to cholmod_update(...)
128 cholmod_sparse cholmod_U{};
129 ToCholmodView(U, ESparseStorage::Unsymmetric, cholmod_U);
130 cholmod_sparse* cholmod_PU = cholmod_submatrix(
131 &cholmod_U,
132 static_cast<std::int32_t*>(mCholmodL->Perm) /*Fill-reducing permutation*/,
133 static_cast<long long>(mCholmodL->n) /*Number of rows*/,
134 NULL /*No column permutation*/,
135 -1 /*all columns*/,
136 1 /*TRUE*/,
137 1 /*TRUE*/,
138 &mCholmodCommon);
139 int const ec = cholmod_updown(0 /*FALSE == downdate*/, cholmod_PU, mCholmodL, &mCholmodCommon);
140 cholmod_free_sparse(&cholmod_PU, &mCholmodCommon);
141 return ec == 1 /*success*/;
142}
143
144template <class Derived>
145inline void Cholmod::ToCholmodView(
146 Eigen::SparseCompressedBase<Derived> const& A,
147 ESparseStorage storage,
148 cholmod_sparse& cholmod_A) const
149{
150 using ScalarType = typename Derived::Scalar;
151 using IndexType = typename Derived::StorageIndex;
152 static_assert(
153 std::is_same_v<ScalarType, double> || std::is_same_v<ScalarType, float>,
154 "Cholmod implementation uses double or float floating point coefficients");
155 static_assert(
156 std::is_same_v<IndexType, std::int32_t> or std::is_same_v<IndexType, std::int64_t>,
157 "Cholmod implementation uses 32-bit or 64-bit integer indices");
158 // Store only the lower triangular part of A
159 cholmod_A.nrow = static_cast<size_t>(A.innerSize());
160 cholmod_A.ncol = static_cast<size_t>(A.outerSize());
161 cholmod_A.nzmax = static_cast<size_t>(A.nonZeros());
162 cholmod_A.p = const_cast<IndexType*>(A.outerIndexPtr());
163 cholmod_A.i = const_cast<IndexType*>(A.innerIndexPtr());
164 cholmod_A.nz = NULL;
165 cholmod_A.x = const_cast<ScalarType*>(A.valuePtr());
166 cholmod_A.z = NULL;
167 cholmod_A.stype = static_cast<std::int32_t>(storage);
168 cholmod_A.itype = std::is_same_v<IndexType, std::int64_t> ? CHOLMOD_LONG : CHOLMOD_INT;
169 cholmod_A.xtype = CHOLMOD_REAL;
170 cholmod_A.dtype = std::is_same_v<ScalarType, double> ? CHOLMOD_DOUBLE : CHOLMOD_SINGLE;
171 cholmod_A.sorted = 1 /*TRUE*/;
172 cholmod_A.packed = 1 /*TRUE*/;
173}
174
175} // namespace linalg
176} // namespace math
177} // namespace pbat
178
179 // clang-format off
180#endif // PBAT_MATH_LINALG_CHOLMOD_H
181#endif // PBAT_USE_SUITESPARSE
182// clang-format on
Linear Algebra related functionality.
Definition FilterEigenvalues.h:7
Math related functionality.
Definition Concepts.h:19
The main namespace of the library.
Definition Aliases.h:15
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic-size matrix type.
Definition Aliases.h:34