Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 1 | // This file is part of Eigen, a lightweight C++ template library |
| 2 | // for linear algebra. |
| 3 | // |
| 4 | // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
| 5 | // |
| 6 | // This Source Code Form is subject to the terms of the Mozilla |
| 7 | // Public License v. 2.0. If a copy of the MPL was not distributed |
| 8 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 9 | |
| 10 | #ifndef EIGEN_CHOLMODSUPPORT_H |
| 11 | #define EIGEN_CHOLMODSUPPORT_H |
| 12 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 13 | namespace Eigen { |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 14 | |
| 15 | namespace internal { |
| 16 | |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 17 | template<typename Scalar> struct cholmod_configure_matrix; |
| 18 | |
| 19 | template<> struct cholmod_configure_matrix<double> { |
| 20 | template<typename CholmodType> |
| 21 | static void run(CholmodType& mat) { |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 22 | mat.xtype = CHOLMOD_REAL; |
| 23 | mat.dtype = CHOLMOD_DOUBLE; |
| 24 | } |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 25 | }; |
| 26 | |
| 27 | template<> struct cholmod_configure_matrix<std::complex<double> > { |
| 28 | template<typename CholmodType> |
| 29 | static void run(CholmodType& mat) { |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 30 | mat.xtype = CHOLMOD_COMPLEX; |
| 31 | mat.dtype = CHOLMOD_DOUBLE; |
| 32 | } |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 33 | }; |
| 34 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 35 | // Other scalar types are not yet supported by Cholmod |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 36 | // template<> struct cholmod_configure_matrix<float> { |
| 37 | // template<typename CholmodType> |
| 38 | // static void run(CholmodType& mat) { |
| 39 | // mat.xtype = CHOLMOD_REAL; |
| 40 | // mat.dtype = CHOLMOD_SINGLE; |
| 41 | // } |
| 42 | // }; |
| 43 | // |
| 44 | // template<> struct cholmod_configure_matrix<std::complex<float> > { |
| 45 | // template<typename CholmodType> |
| 46 | // static void run(CholmodType& mat) { |
| 47 | // mat.xtype = CHOLMOD_COMPLEX; |
| 48 | // mat.dtype = CHOLMOD_SINGLE; |
| 49 | // } |
| 50 | // }; |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 51 | |
| 52 | } // namespace internal |
| 53 | |
| 54 | /** Wraps the Eigen sparse matrix \a mat into a Cholmod sparse matrix object. |
| 55 | * Note that the data are shared. |
| 56 | */ |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 57 | template<typename _Scalar, int _Options, typename _StorageIndex> |
| 58 | cholmod_sparse viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_StorageIndex> > mat) |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 59 | { |
| 60 | cholmod_sparse res; |
| 61 | res.nzmax = mat.nonZeros(); |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 62 | res.nrow = mat.rows(); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 63 | res.ncol = mat.cols(); |
| 64 | res.p = mat.outerIndexPtr(); |
| 65 | res.i = mat.innerIndexPtr(); |
| 66 | res.x = mat.valuePtr(); |
| 67 | res.z = 0; |
| 68 | res.sorted = 1; |
| 69 | if(mat.isCompressed()) |
| 70 | { |
| 71 | res.packed = 1; |
| 72 | res.nz = 0; |
| 73 | } |
| 74 | else |
| 75 | { |
| 76 | res.packed = 0; |
| 77 | res.nz = mat.innerNonZeroPtr(); |
| 78 | } |
| 79 | |
| 80 | res.dtype = 0; |
| 81 | res.stype = -1; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 82 | |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 83 | if (internal::is_same<_StorageIndex,int>::value) |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 84 | { |
| 85 | res.itype = CHOLMOD_INT; |
| 86 | } |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 87 | else if (internal::is_same<_StorageIndex,SuiteSparse_long>::value) |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 88 | { |
| 89 | res.itype = CHOLMOD_LONG; |
| 90 | } |
| 91 | else |
| 92 | { |
| 93 | eigen_assert(false && "Index type not supported yet"); |
| 94 | } |
| 95 | |
| 96 | // setup res.xtype |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 97 | internal::cholmod_configure_matrix<_Scalar>::run(res); |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 98 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 99 | res.stype = 0; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 100 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 101 | return res; |
| 102 | } |
| 103 | |
| 104 | template<typename _Scalar, int _Options, typename _Index> |
| 105 | const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat) |
| 106 | { |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 107 | cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived())); |
| 108 | return res; |
| 109 | } |
| 110 | |
| 111 | template<typename _Scalar, int _Options, typename _Index> |
| 112 | const cholmod_sparse viewAsCholmod(const SparseVector<_Scalar,_Options,_Index>& mat) |
| 113 | { |
| 114 | cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.const_cast_derived())); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 115 | return res; |
| 116 | } |
| 117 | |
| 118 | /** Returns a view of the Eigen sparse matrix \a mat as Cholmod sparse matrix. |
| 119 | * The data are not copied but shared. */ |
| 120 | template<typename _Scalar, int _Options, typename _Index, unsigned int UpLo> |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 121 | cholmod_sparse viewAsCholmod(const SparseSelfAdjointView<const SparseMatrix<_Scalar,_Options,_Index>, UpLo>& mat) |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 122 | { |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 123 | cholmod_sparse res = viewAsCholmod(Ref<SparseMatrix<_Scalar,_Options,_Index> >(mat.matrix().const_cast_derived())); |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 124 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 125 | if(UpLo==Upper) res.stype = 1; |
| 126 | if(UpLo==Lower) res.stype = -1; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 127 | // swap stype for rowmajor matrices (only works for real matrices) |
| 128 | EIGEN_STATIC_ASSERT((_Options & RowMajorBit) == 0 || NumTraits<_Scalar>::IsComplex == 0, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); |
| 129 | if(_Options & RowMajorBit) res.stype *=-1; |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 130 | |
| 131 | return res; |
| 132 | } |
| 133 | |
| 134 | /** Returns a view of the Eigen \b dense matrix \a mat as Cholmod dense matrix. |
| 135 | * The data are not copied but shared. */ |
| 136 | template<typename Derived> |
| 137 | cholmod_dense viewAsCholmod(MatrixBase<Derived>& mat) |
| 138 | { |
| 139 | EIGEN_STATIC_ASSERT((internal::traits<Derived>::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); |
| 140 | typedef typename Derived::Scalar Scalar; |
| 141 | |
| 142 | cholmod_dense res; |
| 143 | res.nrow = mat.rows(); |
| 144 | res.ncol = mat.cols(); |
| 145 | res.nzmax = res.nrow * res.ncol; |
| 146 | res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride(); |
| 147 | res.x = (void*)(mat.derived().data()); |
| 148 | res.z = 0; |
| 149 | |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 150 | internal::cholmod_configure_matrix<Scalar>::run(res); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 151 | |
| 152 | return res; |
| 153 | } |
| 154 | |
| 155 | /** Returns a view of the Cholmod sparse matrix \a cm as an Eigen sparse matrix. |
| 156 | * The data are not copied but shared. */ |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 157 | template<typename Scalar, int Flags, typename StorageIndex> |
| 158 | MappedSparseMatrix<Scalar,Flags,StorageIndex> viewAsEigen(cholmod_sparse& cm) |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 159 | { |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 160 | return MappedSparseMatrix<Scalar,Flags,StorageIndex> |
| 161 | (cm.nrow, cm.ncol, static_cast<StorageIndex*>(cm.p)[cm.ncol], |
| 162 | static_cast<StorageIndex*>(cm.p), static_cast<StorageIndex*>(cm.i),static_cast<Scalar*>(cm.x) ); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 163 | } |
| 164 | |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 165 | namespace internal { |
| 166 | |
| 167 | // template specializations for int and long that call the correct cholmod method |
| 168 | |
| 169 | #define EIGEN_CHOLMOD_SPECIALIZE0(ret, name) \ |
| 170 | template<typename _StorageIndex> inline ret cm_ ## name (cholmod_common &Common) { return cholmod_ ## name (&Common); } \ |
| 171 | template<> inline ret cm_ ## name<SuiteSparse_long> (cholmod_common &Common) { return cholmod_l_ ## name (&Common); } |
| 172 | |
| 173 | #define EIGEN_CHOLMOD_SPECIALIZE1(ret, name, t1, a1) \ |
| 174 | template<typename _StorageIndex> inline ret cm_ ## name (t1& a1, cholmod_common &Common) { return cholmod_ ## name (&a1, &Common); } \ |
| 175 | template<> inline ret cm_ ## name<SuiteSparse_long> (t1& a1, cholmod_common &Common) { return cholmod_l_ ## name (&a1, &Common); } |
| 176 | |
| 177 | EIGEN_CHOLMOD_SPECIALIZE0(int, start) |
| 178 | EIGEN_CHOLMOD_SPECIALIZE0(int, finish) |
| 179 | |
| 180 | EIGEN_CHOLMOD_SPECIALIZE1(int, free_factor, cholmod_factor*, L) |
| 181 | EIGEN_CHOLMOD_SPECIALIZE1(int, free_dense, cholmod_dense*, X) |
| 182 | EIGEN_CHOLMOD_SPECIALIZE1(int, free_sparse, cholmod_sparse*, A) |
| 183 | |
| 184 | EIGEN_CHOLMOD_SPECIALIZE1(cholmod_factor*, analyze, cholmod_sparse, A) |
| 185 | |
| 186 | template<typename _StorageIndex> inline cholmod_dense* cm_solve (int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common &Common) { return cholmod_solve (sys, &L, &B, &Common); } |
| 187 | template<> inline cholmod_dense* cm_solve<SuiteSparse_long> (int sys, cholmod_factor& L, cholmod_dense& B, cholmod_common &Common) { return cholmod_l_solve (sys, &L, &B, &Common); } |
| 188 | |
| 189 | template<typename _StorageIndex> inline cholmod_sparse* cm_spsolve (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_spsolve (sys, &L, &B, &Common); } |
| 190 | template<> inline cholmod_sparse* cm_spsolve<SuiteSparse_long> (int sys, cholmod_factor& L, cholmod_sparse& B, cholmod_common &Common) { return cholmod_l_spsolve (sys, &L, &B, &Common); } |
| 191 | |
| 192 | template<typename _StorageIndex> |
| 193 | inline int cm_factorize_p (cholmod_sparse* A, double beta[2], _StorageIndex* fset, std::size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_factorize_p (A, beta, fset, fsize, L, &Common); } |
| 194 | template<> |
| 195 | inline int cm_factorize_p<SuiteSparse_long> (cholmod_sparse* A, double beta[2], SuiteSparse_long* fset, std::size_t fsize, cholmod_factor* L, cholmod_common &Common) { return cholmod_l_factorize_p (A, beta, fset, fsize, L, &Common); } |
| 196 | |
| 197 | #undef EIGEN_CHOLMOD_SPECIALIZE0 |
| 198 | #undef EIGEN_CHOLMOD_SPECIALIZE1 |
| 199 | |
| 200 | } // namespace internal |
| 201 | |
| 202 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 203 | enum CholmodMode { |
| 204 | CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt |
| 205 | }; |
| 206 | |
| 207 | |
| 208 | /** \ingroup CholmodSupport_Module |
| 209 | * \class CholmodBase |
| 210 | * \brief The base class for the direct Cholesky factorization of Cholmod |
| 211 | * \sa class CholmodSupernodalLLT, class CholmodSimplicialLDLT, class CholmodSimplicialLLT |
| 212 | */ |
| 213 | template<typename _MatrixType, int _UpLo, typename Derived> |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 214 | class CholmodBase : public SparseSolverBase<Derived> |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 215 | { |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 216 | protected: |
| 217 | typedef SparseSolverBase<Derived> Base; |
| 218 | using Base::derived; |
| 219 | using Base::m_isInitialized; |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 220 | public: |
| 221 | typedef _MatrixType MatrixType; |
| 222 | enum { UpLo = _UpLo }; |
| 223 | typedef typename MatrixType::Scalar Scalar; |
| 224 | typedef typename MatrixType::RealScalar RealScalar; |
| 225 | typedef MatrixType CholMatrixType; |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 226 | typedef typename MatrixType::StorageIndex StorageIndex; |
| 227 | enum { |
| 228 | ColsAtCompileTime = MatrixType::ColsAtCompileTime, |
| 229 | MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime |
| 230 | }; |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 231 | |
| 232 | public: |
| 233 | |
| 234 | CholmodBase() |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 235 | : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false) |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 236 | { |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 237 | EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY); |
| 238 | m_shiftOffset[0] = m_shiftOffset[1] = 0.0; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 239 | internal::cm_start<StorageIndex>(m_cholmod); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 240 | } |
| 241 | |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 242 | explicit CholmodBase(const MatrixType& matrix) |
| 243 | : m_cholmodFactor(0), m_info(Success), m_factorizationIsOk(false), m_analysisIsOk(false) |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 244 | { |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 245 | EIGEN_STATIC_ASSERT((internal::is_same<double,RealScalar>::value), CHOLMOD_SUPPORTS_DOUBLE_PRECISION_ONLY); |
| 246 | m_shiftOffset[0] = m_shiftOffset[1] = 0.0; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 247 | internal::cm_start<StorageIndex>(m_cholmod); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 248 | compute(matrix); |
| 249 | } |
| 250 | |
| 251 | ~CholmodBase() |
| 252 | { |
| 253 | if(m_cholmodFactor) |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 254 | internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod); |
| 255 | internal::cm_finish<StorageIndex>(m_cholmod); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 256 | } |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 257 | |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 258 | inline StorageIndex cols() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); } |
| 259 | inline StorageIndex rows() const { return internal::convert_index<StorageIndex, Index>(m_cholmodFactor->n); } |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 260 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 261 | /** \brief Reports whether previous computation was successful. |
| 262 | * |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 263 | * \returns \c Success if computation was successful, |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 264 | * \c NumericalIssue if the matrix.appears to be negative. |
| 265 | */ |
| 266 | ComputationInfo info() const |
| 267 | { |
| 268 | eigen_assert(m_isInitialized && "Decomposition is not initialized."); |
| 269 | return m_info; |
| 270 | } |
| 271 | |
| 272 | /** Computes the sparse Cholesky decomposition of \a matrix */ |
| 273 | Derived& compute(const MatrixType& matrix) |
| 274 | { |
| 275 | analyzePattern(matrix); |
| 276 | factorize(matrix); |
| 277 | return derived(); |
| 278 | } |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 279 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 280 | /** Performs a symbolic decomposition on the sparsity pattern of \a matrix. |
| 281 | * |
| 282 | * This function is particularly useful when solving for several problems having the same structure. |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 283 | * |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 284 | * \sa factorize() |
| 285 | */ |
| 286 | void analyzePattern(const MatrixType& matrix) |
| 287 | { |
| 288 | if(m_cholmodFactor) |
| 289 | { |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 290 | internal::cm_free_factor<StorageIndex>(m_cholmodFactor, m_cholmod); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 291 | m_cholmodFactor = 0; |
| 292 | } |
| 293 | cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>()); |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 294 | m_cholmodFactor = internal::cm_analyze<StorageIndex>(A, m_cholmod); |
| 295 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 296 | this->m_isInitialized = true; |
| 297 | this->m_info = Success; |
| 298 | m_analysisIsOk = true; |
| 299 | m_factorizationIsOk = false; |
| 300 | } |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 301 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 302 | /** Performs a numeric decomposition of \a matrix |
| 303 | * |
| 304 | * The given matrix must have the same sparsity pattern as the matrix on which the symbolic decomposition has been performed. |
| 305 | * |
| 306 | * \sa analyzePattern() |
| 307 | */ |
| 308 | void factorize(const MatrixType& matrix) |
| 309 | { |
| 310 | eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); |
| 311 | cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView<UpLo>()); |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 312 | internal::cm_factorize_p<StorageIndex>(&A, m_shiftOffset, 0, 0, m_cholmodFactor, m_cholmod); |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 313 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 314 | // If the factorization failed, minor is the column at which it did. On success minor == n. |
| 315 | this->m_info = (m_cholmodFactor->minor == m_cholmodFactor->n ? Success : NumericalIssue); |
| 316 | m_factorizationIsOk = true; |
| 317 | } |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 318 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 319 | /** Returns a reference to the Cholmod's configuration structure to get a full control over the performed operations. |
| 320 | * See the Cholmod user guide for details. */ |
| 321 | cholmod_common& cholmod() { return m_cholmod; } |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 322 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 323 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
| 324 | /** \internal */ |
| 325 | template<typename Rhs,typename Dest> |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 326 | void _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 327 | { |
| 328 | eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); |
| 329 | const Index size = m_cholmodFactor->n; |
| 330 | EIGEN_UNUSED_VARIABLE(size); |
| 331 | eigen_assert(size==b.rows()); |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 332 | |
| 333 | // Cholmod needs column-major storage without inner-stride, which corresponds to the default behavior of Ref. |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 334 | Ref<const Matrix<typename Rhs::Scalar,Dynamic,Dynamic,ColMajor> > b_ref(b.derived()); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 335 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 336 | cholmod_dense b_cd = viewAsCholmod(b_ref); |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 337 | cholmod_dense* x_cd = internal::cm_solve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cd, m_cholmod); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 338 | if(!x_cd) |
| 339 | { |
| 340 | this->m_info = NumericalIssue; |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 341 | return; |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 342 | } |
| 343 | // TODO optimize this copy by swapping when possible (be careful with alignment, etc.) |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 344 | // NOTE Actually, the copy can be avoided by calling cholmod_solve2 instead of cholmod_solve |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 345 | dest = Matrix<Scalar,Dest::RowsAtCompileTime,Dest::ColsAtCompileTime>::Map(reinterpret_cast<Scalar*>(x_cd->x),b.rows(),b.cols()); |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 346 | internal::cm_free_dense<StorageIndex>(x_cd, m_cholmod); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 347 | } |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 348 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 349 | /** \internal */ |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 350 | template<typename RhsDerived, typename DestDerived> |
| 351 | void _solve_impl(const SparseMatrixBase<RhsDerived> &b, SparseMatrixBase<DestDerived> &dest) const |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 352 | { |
| 353 | eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); |
| 354 | const Index size = m_cholmodFactor->n; |
| 355 | EIGEN_UNUSED_VARIABLE(size); |
| 356 | eigen_assert(size==b.rows()); |
| 357 | |
| 358 | // note: cs stands for Cholmod Sparse |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 359 | Ref<SparseMatrix<typename RhsDerived::Scalar,ColMajor,typename RhsDerived::StorageIndex> > b_ref(b.const_cast_derived()); |
| 360 | cholmod_sparse b_cs = viewAsCholmod(b_ref); |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 361 | cholmod_sparse* x_cs = internal::cm_spsolve<StorageIndex>(CHOLMOD_A, *m_cholmodFactor, b_cs, m_cholmod); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 362 | if(!x_cs) |
| 363 | { |
| 364 | this->m_info = NumericalIssue; |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 365 | return; |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 366 | } |
| 367 | // TODO optimize this copy by swapping when possible (be careful with alignment, etc.) |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 368 | // NOTE cholmod_spsolve in fact just calls the dense solver for blocks of 4 columns at a time (similar to Eigen's sparse solver) |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 369 | dest.derived() = viewAsEigen<typename DestDerived::Scalar,ColMajor,typename DestDerived::StorageIndex>(*x_cs); |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 370 | internal::cm_free_sparse<StorageIndex>(x_cs, m_cholmod); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 371 | } |
| 372 | #endif // EIGEN_PARSED_BY_DOXYGEN |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 373 | |
| 374 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 375 | /** Sets the shift parameter that will be used to adjust the diagonal coefficients during the numerical factorization. |
| 376 | * |
| 377 | * During the numerical factorization, an offset term is added to the diagonal coefficients:\n |
| 378 | * \c d_ii = \a offset + \c d_ii |
| 379 | * |
| 380 | * The default is \a offset=0. |
| 381 | * |
| 382 | * \returns a reference to \c *this. |
| 383 | */ |
| 384 | Derived& setShift(const RealScalar& offset) |
| 385 | { |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 386 | m_shiftOffset[0] = double(offset); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 387 | return derived(); |
| 388 | } |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 389 | |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 390 | /** \returns the determinant of the underlying matrix from the current factorization */ |
| 391 | Scalar determinant() const |
| 392 | { |
| 393 | using std::exp; |
| 394 | return exp(logDeterminant()); |
| 395 | } |
| 396 | |
| 397 | /** \returns the log determinant of the underlying matrix from the current factorization */ |
| 398 | Scalar logDeterminant() const |
| 399 | { |
| 400 | using std::log; |
| 401 | using numext::real; |
| 402 | eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); |
| 403 | |
| 404 | RealScalar logDet = 0; |
| 405 | Scalar *x = static_cast<Scalar*>(m_cholmodFactor->x); |
| 406 | if (m_cholmodFactor->is_super) |
| 407 | { |
| 408 | // Supernodal factorization stored as a packed list of dense column-major blocs, |
| 409 | // as described by the following structure: |
| 410 | |
| 411 | // super[k] == index of the first column of the j-th super node |
| 412 | StorageIndex *super = static_cast<StorageIndex*>(m_cholmodFactor->super); |
| 413 | // pi[k] == offset to the description of row indices |
| 414 | StorageIndex *pi = static_cast<StorageIndex*>(m_cholmodFactor->pi); |
| 415 | // px[k] == offset to the respective dense block |
| 416 | StorageIndex *px = static_cast<StorageIndex*>(m_cholmodFactor->px); |
| 417 | |
| 418 | Index nb_super_nodes = m_cholmodFactor->nsuper; |
| 419 | for (Index k=0; k < nb_super_nodes; ++k) |
| 420 | { |
| 421 | StorageIndex ncols = super[k + 1] - super[k]; |
| 422 | StorageIndex nrows = pi[k + 1] - pi[k]; |
| 423 | |
| 424 | Map<const Array<Scalar,1,Dynamic>, 0, InnerStride<> > sk(x + px[k], ncols, InnerStride<>(nrows+1)); |
| 425 | logDet += sk.real().log().sum(); |
| 426 | } |
| 427 | } |
| 428 | else |
| 429 | { |
| 430 | // Simplicial factorization stored as standard CSC matrix. |
| 431 | StorageIndex *p = static_cast<StorageIndex*>(m_cholmodFactor->p); |
| 432 | Index size = m_cholmodFactor->n; |
| 433 | for (Index k=0; k<size; ++k) |
| 434 | logDet += log(real( x[p[k]] )); |
| 435 | } |
| 436 | if (m_cholmodFactor->is_ll) |
| 437 | logDet *= 2.0; |
| 438 | return logDet; |
| 439 | }; |
| 440 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 441 | template<typename Stream> |
| 442 | void dumpMemory(Stream& /*s*/) |
| 443 | {} |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 444 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 445 | protected: |
| 446 | mutable cholmod_common m_cholmod; |
| 447 | cholmod_factor* m_cholmodFactor; |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 448 | double m_shiftOffset[2]; |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 449 | mutable ComputationInfo m_info; |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 450 | int m_factorizationIsOk; |
| 451 | int m_analysisIsOk; |
| 452 | }; |
| 453 | |
| 454 | /** \ingroup CholmodSupport_Module |
| 455 | * \class CholmodSimplicialLLT |
| 456 | * \brief A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod |
| 457 | * |
| 458 | * This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization |
| 459 | * using the Cholmod library. |
| 460 | * This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Therefore, it has little practical interest. |
| 461 | * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices |
| 462 | * X and B can be either dense or sparse. |
| 463 | * |
| 464 | * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
| 465 | * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower |
| 466 | * or Upper. Default is Lower. |
| 467 | * |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 468 | * \implsparsesolverconcept |
| 469 | * |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 470 | * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. |
| 471 | * |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 472 | * \warning Only double precision real and complex scalar types are supported by Cholmod. |
| 473 | * |
| 474 | * \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLLT |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 475 | */ |
| 476 | template<typename _MatrixType, int _UpLo = Lower> |
| 477 | class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT<_MatrixType, _UpLo> > |
| 478 | { |
| 479 | typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT> Base; |
| 480 | using Base::m_cholmod; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 481 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 482 | public: |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 483 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 484 | typedef _MatrixType MatrixType; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 485 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 486 | CholmodSimplicialLLT() : Base() { init(); } |
| 487 | |
| 488 | CholmodSimplicialLLT(const MatrixType& matrix) : Base() |
| 489 | { |
| 490 | init(); |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 491 | this->compute(matrix); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 492 | } |
| 493 | |
| 494 | ~CholmodSimplicialLLT() {} |
| 495 | protected: |
| 496 | void init() |
| 497 | { |
| 498 | m_cholmod.final_asis = 0; |
| 499 | m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; |
| 500 | m_cholmod.final_ll = 1; |
| 501 | } |
| 502 | }; |
| 503 | |
| 504 | |
| 505 | /** \ingroup CholmodSupport_Module |
| 506 | * \class CholmodSimplicialLDLT |
| 507 | * \brief A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod |
| 508 | * |
| 509 | * This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization |
| 510 | * using the Cholmod library. |
| 511 | * This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Therefore, it has little practical interest. |
| 512 | * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices |
| 513 | * X and B can be either dense or sparse. |
| 514 | * |
| 515 | * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
| 516 | * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower |
| 517 | * or Upper. Default is Lower. |
| 518 | * |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 519 | * \implsparsesolverconcept |
| 520 | * |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 521 | * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. |
| 522 | * |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 523 | * \warning Only double precision real and complex scalar types are supported by Cholmod. |
| 524 | * |
| 525 | * \sa \ref TutorialSparseSolverConcept, class CholmodSupernodalLLT, class SimplicialLDLT |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 526 | */ |
| 527 | template<typename _MatrixType, int _UpLo = Lower> |
| 528 | class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT<_MatrixType, _UpLo> > |
| 529 | { |
| 530 | typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT> Base; |
| 531 | using Base::m_cholmod; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 532 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 533 | public: |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 534 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 535 | typedef _MatrixType MatrixType; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 536 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 537 | CholmodSimplicialLDLT() : Base() { init(); } |
| 538 | |
| 539 | CholmodSimplicialLDLT(const MatrixType& matrix) : Base() |
| 540 | { |
| 541 | init(); |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 542 | this->compute(matrix); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 543 | } |
| 544 | |
| 545 | ~CholmodSimplicialLDLT() {} |
| 546 | protected: |
| 547 | void init() |
| 548 | { |
| 549 | m_cholmod.final_asis = 1; |
| 550 | m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; |
| 551 | } |
| 552 | }; |
| 553 | |
| 554 | /** \ingroup CholmodSupport_Module |
| 555 | * \class CholmodSupernodalLLT |
| 556 | * \brief A supernodal Cholesky (LLT) factorization and solver based on Cholmod |
| 557 | * |
| 558 | * This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization |
| 559 | * using the Cholmod library. |
| 560 | * This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM. |
| 561 | * The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices |
| 562 | * X and B can be either dense or sparse. |
| 563 | * |
| 564 | * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
| 565 | * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower |
| 566 | * or Upper. Default is Lower. |
| 567 | * |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 568 | * \implsparsesolverconcept |
| 569 | * |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 570 | * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. |
| 571 | * |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 572 | * \warning Only double precision real and complex scalar types are supported by Cholmod. |
| 573 | * |
| 574 | * \sa \ref TutorialSparseSolverConcept |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 575 | */ |
| 576 | template<typename _MatrixType, int _UpLo = Lower> |
| 577 | class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT<_MatrixType, _UpLo> > |
| 578 | { |
| 579 | typedef CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT> Base; |
| 580 | using Base::m_cholmod; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 581 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 582 | public: |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 583 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 584 | typedef _MatrixType MatrixType; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 585 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 586 | CholmodSupernodalLLT() : Base() { init(); } |
| 587 | |
| 588 | CholmodSupernodalLLT(const MatrixType& matrix) : Base() |
| 589 | { |
| 590 | init(); |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 591 | this->compute(matrix); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 592 | } |
| 593 | |
| 594 | ~CholmodSupernodalLLT() {} |
| 595 | protected: |
| 596 | void init() |
| 597 | { |
| 598 | m_cholmod.final_asis = 1; |
| 599 | m_cholmod.supernodal = CHOLMOD_SUPERNODAL; |
| 600 | } |
| 601 | }; |
| 602 | |
| 603 | /** \ingroup CholmodSupport_Module |
| 604 | * \class CholmodDecomposition |
| 605 | * \brief A general Cholesky factorization and solver based on Cholmod |
| 606 | * |
| 607 | * This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization |
| 608 | * using the Cholmod library. The sparse matrix A must be selfadjoint and positive definite. The vectors or matrices |
| 609 | * X and B can be either dense or sparse. |
| 610 | * |
| 611 | * This variant permits to change the underlying Cholesky method at runtime. |
| 612 | * On the other hand, it does not provide access to the result of the factorization. |
| 613 | * The default is to let Cholmod automatically choose between a simplicial and supernodal factorization. |
| 614 | * |
| 615 | * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
| 616 | * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower |
| 617 | * or Upper. Default is Lower. |
| 618 | * |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 619 | * \implsparsesolverconcept |
| 620 | * |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 621 | * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. |
| 622 | * |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 623 | * \warning Only double precision real and complex scalar types are supported by Cholmod. |
| 624 | * |
| 625 | * \sa \ref TutorialSparseSolverConcept |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 626 | */ |
| 627 | template<typename _MatrixType, int _UpLo = Lower> |
| 628 | class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecomposition<_MatrixType, _UpLo> > |
| 629 | { |
| 630 | typedef CholmodBase<_MatrixType, _UpLo, CholmodDecomposition> Base; |
| 631 | using Base::m_cholmod; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 632 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 633 | public: |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 634 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 635 | typedef _MatrixType MatrixType; |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 636 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 637 | CholmodDecomposition() : Base() { init(); } |
| 638 | |
| 639 | CholmodDecomposition(const MatrixType& matrix) : Base() |
| 640 | { |
| 641 | init(); |
Austin Schuh | 189376f | 2018-12-20 22:11:15 +1100 | [diff] [blame] | 642 | this->compute(matrix); |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 643 | } |
| 644 | |
| 645 | ~CholmodDecomposition() {} |
Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame^] | 646 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 647 | void setMode(CholmodMode mode) |
| 648 | { |
| 649 | switch(mode) |
| 650 | { |
| 651 | case CholmodAuto: |
| 652 | m_cholmod.final_asis = 1; |
| 653 | m_cholmod.supernodal = CHOLMOD_AUTO; |
| 654 | break; |
| 655 | case CholmodSimplicialLLt: |
| 656 | m_cholmod.final_asis = 0; |
| 657 | m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; |
| 658 | m_cholmod.final_ll = 1; |
| 659 | break; |
| 660 | case CholmodSupernodalLLt: |
| 661 | m_cholmod.final_asis = 1; |
| 662 | m_cholmod.supernodal = CHOLMOD_SUPERNODAL; |
| 663 | break; |
| 664 | case CholmodLDLt: |
| 665 | m_cholmod.final_asis = 1; |
| 666 | m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; |
| 667 | break; |
| 668 | default: |
| 669 | break; |
| 670 | } |
| 671 | } |
| 672 | protected: |
| 673 | void init() |
| 674 | { |
| 675 | m_cholmod.final_asis = 1; |
| 676 | m_cholmod.supernodal = CHOLMOD_AUTO; |
| 677 | } |
| 678 | }; |
| 679 | |
Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame] | 680 | } // end namespace Eigen |
| 681 | |
| 682 | #endif // EIGEN_CHOLMODSUPPORT_H |