CholmodSupport.h 22 KB

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