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