1 | // This file is part of Eigen, a lightweight C++ template library |
---|
2 | // for linear algebra. |
---|
3 | // |
---|
4 | // Copyright (C) 2008-2011 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_SUPERLUSUPPORT_H |
---|
11 | #define EIGEN_SUPERLUSUPPORT_H |
---|
12 | |
---|
13 | namespace Eigen { |
---|
14 | |
---|
15 | #define DECL_GSSVX(PREFIX,FLOATTYPE,KEYTYPE) \ |
---|
16 | extern "C" { \ |
---|
17 | typedef struct { FLOATTYPE for_lu; FLOATTYPE total_needed; int expansions; } PREFIX##mem_usage_t; \ |
---|
18 | extern void PREFIX##gssvx(superlu_options_t *, SuperMatrix *, int *, int *, int *, \ |
---|
19 | char *, FLOATTYPE *, FLOATTYPE *, SuperMatrix *, SuperMatrix *, \ |
---|
20 | void *, int, SuperMatrix *, SuperMatrix *, \ |
---|
21 | FLOATTYPE *, FLOATTYPE *, FLOATTYPE *, FLOATTYPE *, \ |
---|
22 | PREFIX##mem_usage_t *, SuperLUStat_t *, int *); \ |
---|
23 | } \ |
---|
24 | inline float SuperLU_gssvx(superlu_options_t *options, SuperMatrix *A, \ |
---|
25 | int *perm_c, int *perm_r, int *etree, char *equed, \ |
---|
26 | FLOATTYPE *R, FLOATTYPE *C, SuperMatrix *L, \ |
---|
27 | SuperMatrix *U, void *work, int lwork, \ |
---|
28 | SuperMatrix *B, SuperMatrix *X, \ |
---|
29 | FLOATTYPE *recip_pivot_growth, \ |
---|
30 | FLOATTYPE *rcond, FLOATTYPE *ferr, FLOATTYPE *berr, \ |
---|
31 | SuperLUStat_t *stats, int *info, KEYTYPE) { \ |
---|
32 | PREFIX##mem_usage_t mem_usage; \ |
---|
33 | PREFIX##gssvx(options, A, perm_c, perm_r, etree, equed, R, C, L, \ |
---|
34 | U, work, lwork, B, X, recip_pivot_growth, rcond, \ |
---|
35 | ferr, berr, &mem_usage, stats, info); \ |
---|
36 | return mem_usage.for_lu; /* bytes used by the factor storage */ \ |
---|
37 | } |
---|
38 | |
---|
39 | DECL_GSSVX(s,float,float) |
---|
40 | DECL_GSSVX(c,float,std::complex<float>) |
---|
41 | DECL_GSSVX(d,double,double) |
---|
42 | DECL_GSSVX(z,double,std::complex<double>) |
---|
43 | |
---|
44 | #ifdef MILU_ALPHA |
---|
45 | #define EIGEN_SUPERLU_HAS_ILU |
---|
46 | #endif |
---|
47 | |
---|
48 | #ifdef EIGEN_SUPERLU_HAS_ILU |
---|
49 | |
---|
50 | // similarly for the incomplete factorization using gsisx |
---|
51 | #define DECL_GSISX(PREFIX,FLOATTYPE,KEYTYPE) \ |
---|
52 | extern "C" { \ |
---|
53 | extern void PREFIX##gsisx(superlu_options_t *, SuperMatrix *, int *, int *, int *, \ |
---|
54 | char *, FLOATTYPE *, FLOATTYPE *, SuperMatrix *, SuperMatrix *, \ |
---|
55 | void *, int, SuperMatrix *, SuperMatrix *, FLOATTYPE *, FLOATTYPE *, \ |
---|
56 | PREFIX##mem_usage_t *, SuperLUStat_t *, int *); \ |
---|
57 | } \ |
---|
58 | inline float SuperLU_gsisx(superlu_options_t *options, SuperMatrix *A, \ |
---|
59 | int *perm_c, int *perm_r, int *etree, char *equed, \ |
---|
60 | FLOATTYPE *R, FLOATTYPE *C, SuperMatrix *L, \ |
---|
61 | SuperMatrix *U, void *work, int lwork, \ |
---|
62 | SuperMatrix *B, SuperMatrix *X, \ |
---|
63 | FLOATTYPE *recip_pivot_growth, \ |
---|
64 | FLOATTYPE *rcond, \ |
---|
65 | SuperLUStat_t *stats, int *info, KEYTYPE) { \ |
---|
66 | PREFIX##mem_usage_t mem_usage; \ |
---|
67 | PREFIX##gsisx(options, A, perm_c, perm_r, etree, equed, R, C, L, \ |
---|
68 | U, work, lwork, B, X, recip_pivot_growth, rcond, \ |
---|
69 | &mem_usage, stats, info); \ |
---|
70 | return mem_usage.for_lu; /* bytes used by the factor storage */ \ |
---|
71 | } |
---|
72 | |
---|
73 | DECL_GSISX(s,float,float) |
---|
74 | DECL_GSISX(c,float,std::complex<float>) |
---|
75 | DECL_GSISX(d,double,double) |
---|
76 | DECL_GSISX(z,double,std::complex<double>) |
---|
77 | |
---|
78 | #endif |
---|
79 | |
---|
80 | template<typename MatrixType> |
---|
81 | struct SluMatrixMapHelper; |
---|
82 | |
---|
83 | /** \internal |
---|
84 | * |
---|
85 | * A wrapper class for SuperLU matrices. It supports only compressed sparse matrices |
---|
86 | * and dense matrices. Supernodal and other fancy format are not supported by this wrapper. |
---|
87 | * |
---|
88 | * This wrapper class mainly aims to avoids the need of dynamic allocation of the storage structure. |
---|
89 | */ |
---|
90 | struct SluMatrix : SuperMatrix |
---|
91 | { |
---|
92 | SluMatrix() |
---|
93 | { |
---|
94 | Store = &storage; |
---|
95 | } |
---|
96 | |
---|
97 | SluMatrix(const SluMatrix& other) |
---|
98 | : SuperMatrix(other) |
---|
99 | { |
---|
100 | Store = &storage; |
---|
101 | storage = other.storage; |
---|
102 | } |
---|
103 | |
---|
104 | SluMatrix& operator=(const SluMatrix& other) |
---|
105 | { |
---|
106 | SuperMatrix::operator=(static_cast<const SuperMatrix&>(other)); |
---|
107 | Store = &storage; |
---|
108 | storage = other.storage; |
---|
109 | return *this; |
---|
110 | } |
---|
111 | |
---|
112 | struct |
---|
113 | { |
---|
114 | union {int nnz;int lda;}; |
---|
115 | void *values; |
---|
116 | int *innerInd; |
---|
117 | int *outerInd; |
---|
118 | } storage; |
---|
119 | |
---|
120 | void setStorageType(Stype_t t) |
---|
121 | { |
---|
122 | Stype = t; |
---|
123 | if (t==SLU_NC || t==SLU_NR || t==SLU_DN) |
---|
124 | Store = &storage; |
---|
125 | else |
---|
126 | { |
---|
127 | eigen_assert(false && "storage type not supported"); |
---|
128 | Store = 0; |
---|
129 | } |
---|
130 | } |
---|
131 | |
---|
132 | template<typename Scalar> |
---|
133 | void setScalarType() |
---|
134 | { |
---|
135 | if (internal::is_same<Scalar,float>::value) |
---|
136 | Dtype = SLU_S; |
---|
137 | else if (internal::is_same<Scalar,double>::value) |
---|
138 | Dtype = SLU_D; |
---|
139 | else if (internal::is_same<Scalar,std::complex<float> >::value) |
---|
140 | Dtype = SLU_C; |
---|
141 | else if (internal::is_same<Scalar,std::complex<double> >::value) |
---|
142 | Dtype = SLU_Z; |
---|
143 | else |
---|
144 | { |
---|
145 | eigen_assert(false && "Scalar type not supported by SuperLU"); |
---|
146 | } |
---|
147 | } |
---|
148 | |
---|
149 | template<typename MatrixType> |
---|
150 | static SluMatrix Map(MatrixBase<MatrixType>& _mat) |
---|
151 | { |
---|
152 | MatrixType& mat(_mat.derived()); |
---|
153 | eigen_assert( ((MatrixType::Flags&RowMajorBit)!=RowMajorBit) && "row-major dense matrices are not supported by SuperLU"); |
---|
154 | SluMatrix res; |
---|
155 | res.setStorageType(SLU_DN); |
---|
156 | res.setScalarType<typename MatrixType::Scalar>(); |
---|
157 | res.Mtype = SLU_GE; |
---|
158 | |
---|
159 | res.nrow = mat.rows(); |
---|
160 | res.ncol = mat.cols(); |
---|
161 | |
---|
162 | res.storage.lda = MatrixType::IsVectorAtCompileTime ? mat.size() : mat.outerStride(); |
---|
163 | res.storage.values = mat.data(); |
---|
164 | return res; |
---|
165 | } |
---|
166 | |
---|
167 | template<typename MatrixType> |
---|
168 | static SluMatrix Map(SparseMatrixBase<MatrixType>& mat) |
---|
169 | { |
---|
170 | SluMatrix res; |
---|
171 | if ((MatrixType::Flags&RowMajorBit)==RowMajorBit) |
---|
172 | { |
---|
173 | res.setStorageType(SLU_NR); |
---|
174 | res.nrow = mat.cols(); |
---|
175 | res.ncol = mat.rows(); |
---|
176 | } |
---|
177 | else |
---|
178 | { |
---|
179 | res.setStorageType(SLU_NC); |
---|
180 | res.nrow = mat.rows(); |
---|
181 | res.ncol = mat.cols(); |
---|
182 | } |
---|
183 | |
---|
184 | res.Mtype = SLU_GE; |
---|
185 | |
---|
186 | res.storage.nnz = mat.nonZeros(); |
---|
187 | res.storage.values = mat.derived().valuePtr(); |
---|
188 | res.storage.innerInd = mat.derived().innerIndexPtr(); |
---|
189 | res.storage.outerInd = mat.derived().outerIndexPtr(); |
---|
190 | |
---|
191 | res.setScalarType<typename MatrixType::Scalar>(); |
---|
192 | |
---|
193 | // FIXME the following is not very accurate |
---|
194 | if (MatrixType::Flags & Upper) |
---|
195 | res.Mtype = SLU_TRU; |
---|
196 | if (MatrixType::Flags & Lower) |
---|
197 | res.Mtype = SLU_TRL; |
---|
198 | |
---|
199 | eigen_assert(((MatrixType::Flags & SelfAdjoint)==0) && "SelfAdjoint matrix shape not supported by SuperLU"); |
---|
200 | |
---|
201 | return res; |
---|
202 | } |
---|
203 | }; |
---|
204 | |
---|
205 | template<typename Scalar, int Rows, int Cols, int Options, int MRows, int MCols> |
---|
206 | struct SluMatrixMapHelper<Matrix<Scalar,Rows,Cols,Options,MRows,MCols> > |
---|
207 | { |
---|
208 | typedef Matrix<Scalar,Rows,Cols,Options,MRows,MCols> MatrixType; |
---|
209 | static void run(MatrixType& mat, SluMatrix& res) |
---|
210 | { |
---|
211 | eigen_assert( ((Options&RowMajor)!=RowMajor) && "row-major dense matrices is not supported by SuperLU"); |
---|
212 | res.setStorageType(SLU_DN); |
---|
213 | res.setScalarType<Scalar>(); |
---|
214 | res.Mtype = SLU_GE; |
---|
215 | |
---|
216 | res.nrow = mat.rows(); |
---|
217 | res.ncol = mat.cols(); |
---|
218 | |
---|
219 | res.storage.lda = mat.outerStride(); |
---|
220 | res.storage.values = mat.data(); |
---|
221 | } |
---|
222 | }; |
---|
223 | |
---|
224 | template<typename Derived> |
---|
225 | struct SluMatrixMapHelper<SparseMatrixBase<Derived> > |
---|
226 | { |
---|
227 | typedef Derived MatrixType; |
---|
228 | static void run(MatrixType& mat, SluMatrix& res) |
---|
229 | { |
---|
230 | if ((MatrixType::Flags&RowMajorBit)==RowMajorBit) |
---|
231 | { |
---|
232 | res.setStorageType(SLU_NR); |
---|
233 | res.nrow = mat.cols(); |
---|
234 | res.ncol = mat.rows(); |
---|
235 | } |
---|
236 | else |
---|
237 | { |
---|
238 | res.setStorageType(SLU_NC); |
---|
239 | res.nrow = mat.rows(); |
---|
240 | res.ncol = mat.cols(); |
---|
241 | } |
---|
242 | |
---|
243 | res.Mtype = SLU_GE; |
---|
244 | |
---|
245 | res.storage.nnz = mat.nonZeros(); |
---|
246 | res.storage.values = mat.valuePtr(); |
---|
247 | res.storage.innerInd = mat.innerIndexPtr(); |
---|
248 | res.storage.outerInd = mat.outerIndexPtr(); |
---|
249 | |
---|
250 | res.setScalarType<typename MatrixType::Scalar>(); |
---|
251 | |
---|
252 | // FIXME the following is not very accurate |
---|
253 | if (MatrixType::Flags & Upper) |
---|
254 | res.Mtype = SLU_TRU; |
---|
255 | if (MatrixType::Flags & Lower) |
---|
256 | res.Mtype = SLU_TRL; |
---|
257 | |
---|
258 | eigen_assert(((MatrixType::Flags & SelfAdjoint)==0) && "SelfAdjoint matrix shape not supported by SuperLU"); |
---|
259 | } |
---|
260 | }; |
---|
261 | |
---|
262 | namespace internal { |
---|
263 | |
---|
264 | template<typename MatrixType> |
---|
265 | SluMatrix asSluMatrix(MatrixType& mat) |
---|
266 | { |
---|
267 | return SluMatrix::Map(mat); |
---|
268 | } |
---|
269 | |
---|
270 | /** View a Super LU matrix as an Eigen expression */ |
---|
271 | template<typename Scalar, int Flags, typename Index> |
---|
272 | MappedSparseMatrix<Scalar,Flags,Index> map_superlu(SluMatrix& sluMat) |
---|
273 | { |
---|
274 | eigen_assert((Flags&RowMajor)==RowMajor && sluMat.Stype == SLU_NR |
---|
275 | || (Flags&ColMajor)==ColMajor && sluMat.Stype == SLU_NC); |
---|
276 | |
---|
277 | Index outerSize = (Flags&RowMajor)==RowMajor ? sluMat.ncol : sluMat.nrow; |
---|
278 | |
---|
279 | return MappedSparseMatrix<Scalar,Flags,Index>( |
---|
280 | sluMat.nrow, sluMat.ncol, sluMat.storage.outerInd[outerSize], |
---|
281 | sluMat.storage.outerInd, sluMat.storage.innerInd, reinterpret_cast<Scalar*>(sluMat.storage.values) ); |
---|
282 | } |
---|
283 | |
---|
284 | } // end namespace internal |
---|
285 | |
---|
286 | /** \ingroup SuperLUSupport_Module |
---|
287 | * \class SuperLUBase |
---|
288 | * \brief The base class for the direct and incomplete LU factorization of SuperLU |
---|
289 | */ |
---|
290 | template<typename _MatrixType, typename Derived> |
---|
291 | class SuperLUBase : internal::noncopyable |
---|
292 | { |
---|
293 | public: |
---|
294 | typedef _MatrixType MatrixType; |
---|
295 | typedef typename MatrixType::Scalar Scalar; |
---|
296 | typedef typename MatrixType::RealScalar RealScalar; |
---|
297 | typedef typename MatrixType::Index Index; |
---|
298 | typedef Matrix<Scalar,Dynamic,1> Vector; |
---|
299 | typedef Matrix<int, 1, MatrixType::ColsAtCompileTime> IntRowVectorType; |
---|
300 | typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType; |
---|
301 | typedef SparseMatrix<Scalar> LUMatrixType; |
---|
302 | |
---|
303 | public: |
---|
304 | |
---|
305 | SuperLUBase() {} |
---|
306 | |
---|
307 | ~SuperLUBase() |
---|
308 | { |
---|
309 | clearFactors(); |
---|
310 | } |
---|
311 | |
---|
312 | Derived& derived() { return *static_cast<Derived*>(this); } |
---|
313 | const Derived& derived() const { return *static_cast<const Derived*>(this); } |
---|
314 | |
---|
315 | inline Index rows() const { return m_matrix.rows(); } |
---|
316 | inline Index cols() const { return m_matrix.cols(); } |
---|
317 | |
---|
318 | /** \returns a reference to the Super LU option object to configure the Super LU algorithms. */ |
---|
319 | inline superlu_options_t& options() { return m_sluOptions; } |
---|
320 | |
---|
321 | /** \brief Reports whether previous computation was successful. |
---|
322 | * |
---|
323 | * \returns \c Success if computation was succesful, |
---|
324 | * \c NumericalIssue if the matrix.appears to be negative. |
---|
325 | */ |
---|
326 | ComputationInfo info() const |
---|
327 | { |
---|
328 | eigen_assert(m_isInitialized && "Decomposition is not initialized."); |
---|
329 | return m_info; |
---|
330 | } |
---|
331 | |
---|
332 | /** Computes the sparse Cholesky decomposition of \a matrix */ |
---|
333 | void compute(const MatrixType& matrix) |
---|
334 | { |
---|
335 | derived().analyzePattern(matrix); |
---|
336 | derived().factorize(matrix); |
---|
337 | } |
---|
338 | |
---|
339 | /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. |
---|
340 | * |
---|
341 | * \sa compute() |
---|
342 | */ |
---|
343 | template<typename Rhs> |
---|
344 | inline const internal::solve_retval<SuperLUBase, Rhs> solve(const MatrixBase<Rhs>& b) const |
---|
345 | { |
---|
346 | eigen_assert(m_isInitialized && "SuperLU is not initialized."); |
---|
347 | eigen_assert(rows()==b.rows() |
---|
348 | && "SuperLU::solve(): invalid number of rows of the right hand side matrix b"); |
---|
349 | return internal::solve_retval<SuperLUBase, Rhs>(*this, b.derived()); |
---|
350 | } |
---|
351 | |
---|
352 | /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. |
---|
353 | * |
---|
354 | * \sa compute() |
---|
355 | */ |
---|
356 | // template<typename Rhs> |
---|
357 | // inline const internal::sparse_solve_retval<SuperLU, Rhs> solve(const SparseMatrixBase<Rhs>& b) const |
---|
358 | // { |
---|
359 | // eigen_assert(m_isInitialized && "SuperLU is not initialized."); |
---|
360 | // eigen_assert(rows()==b.rows() |
---|
361 | // && "SuperLU::solve(): invalid number of rows of the right hand side matrix b"); |
---|
362 | // return internal::sparse_solve_retval<SuperLU, Rhs>(*this, b.derived()); |
---|
363 | // } |
---|
364 | |
---|
365 | /** Performs a symbolic decomposition on the sparcity of \a matrix. |
---|
366 | * |
---|
367 | * This function is particularly useful when solving for several problems having the same structure. |
---|
368 | * |
---|
369 | * \sa factorize() |
---|
370 | */ |
---|
371 | void analyzePattern(const MatrixType& /*matrix*/) |
---|
372 | { |
---|
373 | m_isInitialized = true; |
---|
374 | m_info = Success; |
---|
375 | m_analysisIsOk = true; |
---|
376 | m_factorizationIsOk = false; |
---|
377 | } |
---|
378 | |
---|
379 | template<typename Stream> |
---|
380 | void dumpMemory(Stream& s) |
---|
381 | {} |
---|
382 | |
---|
383 | protected: |
---|
384 | |
---|
385 | void initFactorization(const MatrixType& a) |
---|
386 | { |
---|
387 | set_default_options(&this->m_sluOptions); |
---|
388 | |
---|
389 | const int size = a.rows(); |
---|
390 | m_matrix = a; |
---|
391 | |
---|
392 | m_sluA = internal::asSluMatrix(m_matrix); |
---|
393 | clearFactors(); |
---|
394 | |
---|
395 | m_p.resize(size); |
---|
396 | m_q.resize(size); |
---|
397 | m_sluRscale.resize(size); |
---|
398 | m_sluCscale.resize(size); |
---|
399 | m_sluEtree.resize(size); |
---|
400 | |
---|
401 | // set empty B and X |
---|
402 | m_sluB.setStorageType(SLU_DN); |
---|
403 | m_sluB.setScalarType<Scalar>(); |
---|
404 | m_sluB.Mtype = SLU_GE; |
---|
405 | m_sluB.storage.values = 0; |
---|
406 | m_sluB.nrow = 0; |
---|
407 | m_sluB.ncol = 0; |
---|
408 | m_sluB.storage.lda = size; |
---|
409 | m_sluX = m_sluB; |
---|
410 | |
---|
411 | m_extractedDataAreDirty = true; |
---|
412 | } |
---|
413 | |
---|
414 | void init() |
---|
415 | { |
---|
416 | m_info = InvalidInput; |
---|
417 | m_isInitialized = false; |
---|
418 | m_sluL.Store = 0; |
---|
419 | m_sluU.Store = 0; |
---|
420 | } |
---|
421 | |
---|
422 | void extractData() const; |
---|
423 | |
---|
424 | void clearFactors() |
---|
425 | { |
---|
426 | if(m_sluL.Store) |
---|
427 | Destroy_SuperNode_Matrix(&m_sluL); |
---|
428 | if(m_sluU.Store) |
---|
429 | Destroy_CompCol_Matrix(&m_sluU); |
---|
430 | |
---|
431 | m_sluL.Store = 0; |
---|
432 | m_sluU.Store = 0; |
---|
433 | |
---|
434 | memset(&m_sluL,0,sizeof m_sluL); |
---|
435 | memset(&m_sluU,0,sizeof m_sluU); |
---|
436 | } |
---|
437 | |
---|
438 | // cached data to reduce reallocation, etc. |
---|
439 | mutable LUMatrixType m_l; |
---|
440 | mutable LUMatrixType m_u; |
---|
441 | mutable IntColVectorType m_p; |
---|
442 | mutable IntRowVectorType m_q; |
---|
443 | |
---|
444 | mutable LUMatrixType m_matrix; // copy of the factorized matrix |
---|
445 | mutable SluMatrix m_sluA; |
---|
446 | mutable SuperMatrix m_sluL, m_sluU; |
---|
447 | mutable SluMatrix m_sluB, m_sluX; |
---|
448 | mutable SuperLUStat_t m_sluStat; |
---|
449 | mutable superlu_options_t m_sluOptions; |
---|
450 | mutable std::vector<int> m_sluEtree; |
---|
451 | mutable Matrix<RealScalar,Dynamic,1> m_sluRscale, m_sluCscale; |
---|
452 | mutable Matrix<RealScalar,Dynamic,1> m_sluFerr, m_sluBerr; |
---|
453 | mutable char m_sluEqued; |
---|
454 | |
---|
455 | mutable ComputationInfo m_info; |
---|
456 | bool m_isInitialized; |
---|
457 | int m_factorizationIsOk; |
---|
458 | int m_analysisIsOk; |
---|
459 | mutable bool m_extractedDataAreDirty; |
---|
460 | |
---|
461 | private: |
---|
462 | SuperLUBase(SuperLUBase& ) { } |
---|
463 | }; |
---|
464 | |
---|
465 | |
---|
466 | /** \ingroup SuperLUSupport_Module |
---|
467 | * \class SuperLU |
---|
468 | * \brief A sparse direct LU factorization and solver based on the SuperLU library |
---|
469 | * |
---|
470 | * This class allows to solve for A.X = B sparse linear problems via a direct LU factorization |
---|
471 | * using the SuperLU library. The sparse matrix A must be squared and invertible. The vectors or matrices |
---|
472 | * X and B can be either dense or sparse. |
---|
473 | * |
---|
474 | * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
---|
475 | * |
---|
476 | * \sa \ref TutorialSparseDirectSolvers |
---|
477 | */ |
---|
478 | template<typename _MatrixType> |
---|
479 | class SuperLU : public SuperLUBase<_MatrixType,SuperLU<_MatrixType> > |
---|
480 | { |
---|
481 | public: |
---|
482 | typedef SuperLUBase<_MatrixType,SuperLU> Base; |
---|
483 | typedef _MatrixType MatrixType; |
---|
484 | typedef typename Base::Scalar Scalar; |
---|
485 | typedef typename Base::RealScalar RealScalar; |
---|
486 | typedef typename Base::Index Index; |
---|
487 | typedef typename Base::IntRowVectorType IntRowVectorType; |
---|
488 | typedef typename Base::IntColVectorType IntColVectorType; |
---|
489 | typedef typename Base::LUMatrixType LUMatrixType; |
---|
490 | typedef TriangularView<LUMatrixType, Lower|UnitDiag> LMatrixType; |
---|
491 | typedef TriangularView<LUMatrixType, Upper> UMatrixType; |
---|
492 | |
---|
493 | public: |
---|
494 | |
---|
495 | SuperLU() : Base() { init(); } |
---|
496 | |
---|
497 | SuperLU(const MatrixType& matrix) : Base() |
---|
498 | { |
---|
499 | init(); |
---|
500 | Base::compute(matrix); |
---|
501 | } |
---|
502 | |
---|
503 | ~SuperLU() |
---|
504 | { |
---|
505 | } |
---|
506 | |
---|
507 | /** Performs a symbolic decomposition on the sparcity of \a matrix. |
---|
508 | * |
---|
509 | * This function is particularly useful when solving for several problems having the same structure. |
---|
510 | * |
---|
511 | * \sa factorize() |
---|
512 | */ |
---|
513 | void analyzePattern(const MatrixType& matrix) |
---|
514 | { |
---|
515 | m_info = InvalidInput; |
---|
516 | m_isInitialized = false; |
---|
517 | Base::analyzePattern(matrix); |
---|
518 | } |
---|
519 | |
---|
520 | /** Performs a numeric decomposition of \a matrix |
---|
521 | * |
---|
522 | * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. |
---|
523 | * |
---|
524 | * \sa analyzePattern() |
---|
525 | */ |
---|
526 | void factorize(const MatrixType& matrix); |
---|
527 | |
---|
528 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
---|
529 | /** \internal */ |
---|
530 | template<typename Rhs,typename Dest> |
---|
531 | void _solve(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const; |
---|
532 | #endif // EIGEN_PARSED_BY_DOXYGEN |
---|
533 | |
---|
534 | inline const LMatrixType& matrixL() const |
---|
535 | { |
---|
536 | if (m_extractedDataAreDirty) this->extractData(); |
---|
537 | return m_l; |
---|
538 | } |
---|
539 | |
---|
540 | inline const UMatrixType& matrixU() const |
---|
541 | { |
---|
542 | if (m_extractedDataAreDirty) this->extractData(); |
---|
543 | return m_u; |
---|
544 | } |
---|
545 | |
---|
546 | inline const IntColVectorType& permutationP() const |
---|
547 | { |
---|
548 | if (m_extractedDataAreDirty) this->extractData(); |
---|
549 | return m_p; |
---|
550 | } |
---|
551 | |
---|
552 | inline const IntRowVectorType& permutationQ() const |
---|
553 | { |
---|
554 | if (m_extractedDataAreDirty) this->extractData(); |
---|
555 | return m_q; |
---|
556 | } |
---|
557 | |
---|
558 | Scalar determinant() const; |
---|
559 | |
---|
560 | protected: |
---|
561 | |
---|
562 | using Base::m_matrix; |
---|
563 | using Base::m_sluOptions; |
---|
564 | using Base::m_sluA; |
---|
565 | using Base::m_sluB; |
---|
566 | using Base::m_sluX; |
---|
567 | using Base::m_p; |
---|
568 | using Base::m_q; |
---|
569 | using Base::m_sluEtree; |
---|
570 | using Base::m_sluEqued; |
---|
571 | using Base::m_sluRscale; |
---|
572 | using Base::m_sluCscale; |
---|
573 | using Base::m_sluL; |
---|
574 | using Base::m_sluU; |
---|
575 | using Base::m_sluStat; |
---|
576 | using Base::m_sluFerr; |
---|
577 | using Base::m_sluBerr; |
---|
578 | using Base::m_l; |
---|
579 | using Base::m_u; |
---|
580 | |
---|
581 | using Base::m_analysisIsOk; |
---|
582 | using Base::m_factorizationIsOk; |
---|
583 | using Base::m_extractedDataAreDirty; |
---|
584 | using Base::m_isInitialized; |
---|
585 | using Base::m_info; |
---|
586 | |
---|
587 | void init() |
---|
588 | { |
---|
589 | Base::init(); |
---|
590 | |
---|
591 | set_default_options(&this->m_sluOptions); |
---|
592 | m_sluOptions.PrintStat = NO; |
---|
593 | m_sluOptions.ConditionNumber = NO; |
---|
594 | m_sluOptions.Trans = NOTRANS; |
---|
595 | m_sluOptions.ColPerm = COLAMD; |
---|
596 | } |
---|
597 | |
---|
598 | |
---|
599 | private: |
---|
600 | SuperLU(SuperLU& ) { } |
---|
601 | }; |
---|
602 | |
---|
603 | template<typename MatrixType> |
---|
604 | void SuperLU<MatrixType>::factorize(const MatrixType& a) |
---|
605 | { |
---|
606 | eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); |
---|
607 | if(!m_analysisIsOk) |
---|
608 | { |
---|
609 | m_info = InvalidInput; |
---|
610 | return; |
---|
611 | } |
---|
612 | |
---|
613 | this->initFactorization(a); |
---|
614 | |
---|
615 | int info = 0; |
---|
616 | RealScalar recip_pivot_growth, rcond; |
---|
617 | RealScalar ferr, berr; |
---|
618 | |
---|
619 | StatInit(&m_sluStat); |
---|
620 | SuperLU_gssvx(&m_sluOptions, &m_sluA, m_q.data(), m_p.data(), &m_sluEtree[0], |
---|
621 | &m_sluEqued, &m_sluRscale[0], &m_sluCscale[0], |
---|
622 | &m_sluL, &m_sluU, |
---|
623 | NULL, 0, |
---|
624 | &m_sluB, &m_sluX, |
---|
625 | &recip_pivot_growth, &rcond, |
---|
626 | &ferr, &berr, |
---|
627 | &m_sluStat, &info, Scalar()); |
---|
628 | StatFree(&m_sluStat); |
---|
629 | |
---|
630 | m_extractedDataAreDirty = true; |
---|
631 | |
---|
632 | // FIXME how to better check for errors ??? |
---|
633 | m_info = info == 0 ? Success : NumericalIssue; |
---|
634 | m_factorizationIsOk = true; |
---|
635 | } |
---|
636 | |
---|
637 | template<typename MatrixType> |
---|
638 | template<typename Rhs,typename Dest> |
---|
639 | void SuperLU<MatrixType>::_solve(const MatrixBase<Rhs> &b, MatrixBase<Dest>& x) const |
---|
640 | { |
---|
641 | eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or analyzePattern()/factorize()"); |
---|
642 | |
---|
643 | const int size = m_matrix.rows(); |
---|
644 | const int rhsCols = b.cols(); |
---|
645 | eigen_assert(size==b.rows()); |
---|
646 | |
---|
647 | m_sluOptions.Trans = NOTRANS; |
---|
648 | m_sluOptions.Fact = FACTORED; |
---|
649 | m_sluOptions.IterRefine = NOREFINE; |
---|
650 | |
---|
651 | |
---|
652 | m_sluFerr.resize(rhsCols); |
---|
653 | m_sluBerr.resize(rhsCols); |
---|
654 | m_sluB = SluMatrix::Map(b.const_cast_derived()); |
---|
655 | m_sluX = SluMatrix::Map(x.derived()); |
---|
656 | |
---|
657 | typename Rhs::PlainObject b_cpy; |
---|
658 | if(m_sluEqued!='N') |
---|
659 | { |
---|
660 | b_cpy = b; |
---|
661 | m_sluB = SluMatrix::Map(b_cpy.const_cast_derived()); |
---|
662 | } |
---|
663 | |
---|
664 | StatInit(&m_sluStat); |
---|
665 | int info = 0; |
---|
666 | RealScalar recip_pivot_growth, rcond; |
---|
667 | SuperLU_gssvx(&m_sluOptions, &m_sluA, |
---|
668 | m_q.data(), m_p.data(), |
---|
669 | &m_sluEtree[0], &m_sluEqued, |
---|
670 | &m_sluRscale[0], &m_sluCscale[0], |
---|
671 | &m_sluL, &m_sluU, |
---|
672 | NULL, 0, |
---|
673 | &m_sluB, &m_sluX, |
---|
674 | &recip_pivot_growth, &rcond, |
---|
675 | &m_sluFerr[0], &m_sluBerr[0], |
---|
676 | &m_sluStat, &info, Scalar()); |
---|
677 | StatFree(&m_sluStat); |
---|
678 | m_info = info==0 ? Success : NumericalIssue; |
---|
679 | } |
---|
680 | |
---|
681 | // the code of this extractData() function has been adapted from the SuperLU's Matlab support code, |
---|
682 | // |
---|
683 | // Copyright (c) 1994 by Xerox Corporation. All rights reserved. |
---|
684 | // |
---|
685 | // THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY |
---|
686 | // EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. |
---|
687 | // |
---|
688 | template<typename MatrixType, typename Derived> |
---|
689 | void SuperLUBase<MatrixType,Derived>::extractData() const |
---|
690 | { |
---|
691 | eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for extracting factors, you must first call either compute() or analyzePattern()/factorize()"); |
---|
692 | if (m_extractedDataAreDirty) |
---|
693 | { |
---|
694 | int upper; |
---|
695 | int fsupc, istart, nsupr; |
---|
696 | int lastl = 0, lastu = 0; |
---|
697 | SCformat *Lstore = static_cast<SCformat*>(m_sluL.Store); |
---|
698 | NCformat *Ustore = static_cast<NCformat*>(m_sluU.Store); |
---|
699 | Scalar *SNptr; |
---|
700 | |
---|
701 | const int size = m_matrix.rows(); |
---|
702 | m_l.resize(size,size); |
---|
703 | m_l.resizeNonZeros(Lstore->nnz); |
---|
704 | m_u.resize(size,size); |
---|
705 | m_u.resizeNonZeros(Ustore->nnz); |
---|
706 | |
---|
707 | int* Lcol = m_l.outerIndexPtr(); |
---|
708 | int* Lrow = m_l.innerIndexPtr(); |
---|
709 | Scalar* Lval = m_l.valuePtr(); |
---|
710 | |
---|
711 | int* Ucol = m_u.outerIndexPtr(); |
---|
712 | int* Urow = m_u.innerIndexPtr(); |
---|
713 | Scalar* Uval = m_u.valuePtr(); |
---|
714 | |
---|
715 | Ucol[0] = 0; |
---|
716 | Ucol[0] = 0; |
---|
717 | |
---|
718 | /* for each supernode */ |
---|
719 | for (int k = 0; k <= Lstore->nsuper; ++k) |
---|
720 | { |
---|
721 | fsupc = L_FST_SUPC(k); |
---|
722 | istart = L_SUB_START(fsupc); |
---|
723 | nsupr = L_SUB_START(fsupc+1) - istart; |
---|
724 | upper = 1; |
---|
725 | |
---|
726 | /* for each column in the supernode */ |
---|
727 | for (int j = fsupc; j < L_FST_SUPC(k+1); ++j) |
---|
728 | { |
---|
729 | SNptr = &((Scalar*)Lstore->nzval)[L_NZ_START(j)]; |
---|
730 | |
---|
731 | /* Extract U */ |
---|
732 | for (int i = U_NZ_START(j); i < U_NZ_START(j+1); ++i) |
---|
733 | { |
---|
734 | Uval[lastu] = ((Scalar*)Ustore->nzval)[i]; |
---|
735 | /* Matlab doesn't like explicit zero. */ |
---|
736 | if (Uval[lastu] != 0.0) |
---|
737 | Urow[lastu++] = U_SUB(i); |
---|
738 | } |
---|
739 | for (int i = 0; i < upper; ++i) |
---|
740 | { |
---|
741 | /* upper triangle in the supernode */ |
---|
742 | Uval[lastu] = SNptr[i]; |
---|
743 | /* Matlab doesn't like explicit zero. */ |
---|
744 | if (Uval[lastu] != 0.0) |
---|
745 | Urow[lastu++] = L_SUB(istart+i); |
---|
746 | } |
---|
747 | Ucol[j+1] = lastu; |
---|
748 | |
---|
749 | /* Extract L */ |
---|
750 | Lval[lastl] = 1.0; /* unit diagonal */ |
---|
751 | Lrow[lastl++] = L_SUB(istart + upper - 1); |
---|
752 | for (int i = upper; i < nsupr; ++i) |
---|
753 | { |
---|
754 | Lval[lastl] = SNptr[i]; |
---|
755 | /* Matlab doesn't like explicit zero. */ |
---|
756 | if (Lval[lastl] != 0.0) |
---|
757 | Lrow[lastl++] = L_SUB(istart+i); |
---|
758 | } |
---|
759 | Lcol[j+1] = lastl; |
---|
760 | |
---|
761 | ++upper; |
---|
762 | } /* for j ... */ |
---|
763 | |
---|
764 | } /* for k ... */ |
---|
765 | |
---|
766 | // squeeze the matrices : |
---|
767 | m_l.resizeNonZeros(lastl); |
---|
768 | m_u.resizeNonZeros(lastu); |
---|
769 | |
---|
770 | m_extractedDataAreDirty = false; |
---|
771 | } |
---|
772 | } |
---|
773 | |
---|
774 | template<typename MatrixType> |
---|
775 | typename SuperLU<MatrixType>::Scalar SuperLU<MatrixType>::determinant() const |
---|
776 | { |
---|
777 | eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for computing the determinant, you must first call either compute() or analyzePattern()/factorize()"); |
---|
778 | |
---|
779 | if (m_extractedDataAreDirty) |
---|
780 | this->extractData(); |
---|
781 | |
---|
782 | Scalar det = Scalar(1); |
---|
783 | for (int j=0; j<m_u.cols(); ++j) |
---|
784 | { |
---|
785 | if (m_u.outerIndexPtr()[j+1]-m_u.outerIndexPtr()[j] > 0) |
---|
786 | { |
---|
787 | int lastId = m_u.outerIndexPtr()[j+1]-1; |
---|
788 | eigen_assert(m_u.innerIndexPtr()[lastId]<=j); |
---|
789 | if (m_u.innerIndexPtr()[lastId]==j) |
---|
790 | det *= m_u.valuePtr()[lastId]; |
---|
791 | } |
---|
792 | } |
---|
793 | if(m_sluEqued!='N') |
---|
794 | return det/m_sluRscale.prod()/m_sluCscale.prod(); |
---|
795 | else |
---|
796 | return det; |
---|
797 | } |
---|
798 | |
---|
799 | #ifdef EIGEN_PARSED_BY_DOXYGEN |
---|
800 | #define EIGEN_SUPERLU_HAS_ILU |
---|
801 | #endif |
---|
802 | |
---|
803 | #ifdef EIGEN_SUPERLU_HAS_ILU |
---|
804 | |
---|
805 | /** \ingroup SuperLUSupport_Module |
---|
806 | * \class SuperILU |
---|
807 | * \brief A sparse direct \b incomplete LU factorization and solver based on the SuperLU library |
---|
808 | * |
---|
809 | * This class allows to solve for an approximate solution of A.X = B sparse linear problems via an incomplete LU factorization |
---|
810 | * using the SuperLU library. This class is aimed to be used as a preconditioner of the iterative linear solvers. |
---|
811 | * |
---|
812 | * \warning This class requires SuperLU 4 or later. |
---|
813 | * |
---|
814 | * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> |
---|
815 | * |
---|
816 | * \sa \ref TutorialSparseDirectSolvers, class ConjugateGradient, class BiCGSTAB |
---|
817 | */ |
---|
818 | |
---|
819 | template<typename _MatrixType> |
---|
820 | class SuperILU : public SuperLUBase<_MatrixType,SuperILU<_MatrixType> > |
---|
821 | { |
---|
822 | public: |
---|
823 | typedef SuperLUBase<_MatrixType,SuperILU> Base; |
---|
824 | typedef _MatrixType MatrixType; |
---|
825 | typedef typename Base::Scalar Scalar; |
---|
826 | typedef typename Base::RealScalar RealScalar; |
---|
827 | typedef typename Base::Index Index; |
---|
828 | |
---|
829 | public: |
---|
830 | |
---|
831 | SuperILU() : Base() { init(); } |
---|
832 | |
---|
833 | SuperILU(const MatrixType& matrix) : Base() |
---|
834 | { |
---|
835 | init(); |
---|
836 | Base::compute(matrix); |
---|
837 | } |
---|
838 | |
---|
839 | ~SuperILU() |
---|
840 | { |
---|
841 | } |
---|
842 | |
---|
843 | /** Performs a symbolic decomposition on the sparcity of \a matrix. |
---|
844 | * |
---|
845 | * This function is particularly useful when solving for several problems having the same structure. |
---|
846 | * |
---|
847 | * \sa factorize() |
---|
848 | */ |
---|
849 | void analyzePattern(const MatrixType& matrix) |
---|
850 | { |
---|
851 | Base::analyzePattern(matrix); |
---|
852 | } |
---|
853 | |
---|
854 | /** Performs a numeric decomposition of \a matrix |
---|
855 | * |
---|
856 | * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. |
---|
857 | * |
---|
858 | * \sa analyzePattern() |
---|
859 | */ |
---|
860 | void factorize(const MatrixType& matrix); |
---|
861 | |
---|
862 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
---|
863 | /** \internal */ |
---|
864 | template<typename Rhs,typename Dest> |
---|
865 | void _solve(const MatrixBase<Rhs> &b, MatrixBase<Dest> &dest) const; |
---|
866 | #endif // EIGEN_PARSED_BY_DOXYGEN |
---|
867 | |
---|
868 | protected: |
---|
869 | |
---|
870 | using Base::m_matrix; |
---|
871 | using Base::m_sluOptions; |
---|
872 | using Base::m_sluA; |
---|
873 | using Base::m_sluB; |
---|
874 | using Base::m_sluX; |
---|
875 | using Base::m_p; |
---|
876 | using Base::m_q; |
---|
877 | using Base::m_sluEtree; |
---|
878 | using Base::m_sluEqued; |
---|
879 | using Base::m_sluRscale; |
---|
880 | using Base::m_sluCscale; |
---|
881 | using Base::m_sluL; |
---|
882 | using Base::m_sluU; |
---|
883 | using Base::m_sluStat; |
---|
884 | using Base::m_sluFerr; |
---|
885 | using Base::m_sluBerr; |
---|
886 | using Base::m_l; |
---|
887 | using Base::m_u; |
---|
888 | |
---|
889 | using Base::m_analysisIsOk; |
---|
890 | using Base::m_factorizationIsOk; |
---|
891 | using Base::m_extractedDataAreDirty; |
---|
892 | using Base::m_isInitialized; |
---|
893 | using Base::m_info; |
---|
894 | |
---|
895 | void init() |
---|
896 | { |
---|
897 | Base::init(); |
---|
898 | |
---|
899 | ilu_set_default_options(&m_sluOptions); |
---|
900 | m_sluOptions.PrintStat = NO; |
---|
901 | m_sluOptions.ConditionNumber = NO; |
---|
902 | m_sluOptions.Trans = NOTRANS; |
---|
903 | m_sluOptions.ColPerm = MMD_AT_PLUS_A; |
---|
904 | |
---|
905 | // no attempt to preserve column sum |
---|
906 | m_sluOptions.ILU_MILU = SILU; |
---|
907 | // only basic ILU(k) support -- no direct control over memory consumption |
---|
908 | // better to use ILU_DropRule = DROP_BASIC | DROP_AREA |
---|
909 | // and set ILU_FillFactor to max memory growth |
---|
910 | m_sluOptions.ILU_DropRule = DROP_BASIC; |
---|
911 | m_sluOptions.ILU_DropTol = NumTraits<Scalar>::dummy_precision()*10; |
---|
912 | } |
---|
913 | |
---|
914 | private: |
---|
915 | SuperILU(SuperILU& ) { } |
---|
916 | }; |
---|
917 | |
---|
918 | template<typename MatrixType> |
---|
919 | void SuperILU<MatrixType>::factorize(const MatrixType& a) |
---|
920 | { |
---|
921 | eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); |
---|
922 | if(!m_analysisIsOk) |
---|
923 | { |
---|
924 | m_info = InvalidInput; |
---|
925 | return; |
---|
926 | } |
---|
927 | |
---|
928 | this->initFactorization(a); |
---|
929 | |
---|
930 | int info = 0; |
---|
931 | RealScalar recip_pivot_growth, rcond; |
---|
932 | |
---|
933 | StatInit(&m_sluStat); |
---|
934 | SuperLU_gsisx(&m_sluOptions, &m_sluA, m_q.data(), m_p.data(), &m_sluEtree[0], |
---|
935 | &m_sluEqued, &m_sluRscale[0], &m_sluCscale[0], |
---|
936 | &m_sluL, &m_sluU, |
---|
937 | NULL, 0, |
---|
938 | &m_sluB, &m_sluX, |
---|
939 | &recip_pivot_growth, &rcond, |
---|
940 | &m_sluStat, &info, Scalar()); |
---|
941 | StatFree(&m_sluStat); |
---|
942 | |
---|
943 | // FIXME how to better check for errors ??? |
---|
944 | m_info = info == 0 ? Success : NumericalIssue; |
---|
945 | m_factorizationIsOk = true; |
---|
946 | } |
---|
947 | |
---|
948 | template<typename MatrixType> |
---|
949 | template<typename Rhs,typename Dest> |
---|
950 | void SuperILU<MatrixType>::_solve(const MatrixBase<Rhs> &b, MatrixBase<Dest>& x) const |
---|
951 | { |
---|
952 | eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or analyzePattern()/factorize()"); |
---|
953 | |
---|
954 | const int size = m_matrix.rows(); |
---|
955 | const int rhsCols = b.cols(); |
---|
956 | eigen_assert(size==b.rows()); |
---|
957 | |
---|
958 | m_sluOptions.Trans = NOTRANS; |
---|
959 | m_sluOptions.Fact = FACTORED; |
---|
960 | m_sluOptions.IterRefine = NOREFINE; |
---|
961 | |
---|
962 | m_sluFerr.resize(rhsCols); |
---|
963 | m_sluBerr.resize(rhsCols); |
---|
964 | m_sluB = SluMatrix::Map(b.const_cast_derived()); |
---|
965 | m_sluX = SluMatrix::Map(x.derived()); |
---|
966 | |
---|
967 | typename Rhs::PlainObject b_cpy; |
---|
968 | if(m_sluEqued!='N') |
---|
969 | { |
---|
970 | b_cpy = b; |
---|
971 | m_sluB = SluMatrix::Map(b_cpy.const_cast_derived()); |
---|
972 | } |
---|
973 | |
---|
974 | int info = 0; |
---|
975 | RealScalar recip_pivot_growth, rcond; |
---|
976 | |
---|
977 | StatInit(&m_sluStat); |
---|
978 | SuperLU_gsisx(&m_sluOptions, &m_sluA, |
---|
979 | m_q.data(), m_p.data(), |
---|
980 | &m_sluEtree[0], &m_sluEqued, |
---|
981 | &m_sluRscale[0], &m_sluCscale[0], |
---|
982 | &m_sluL, &m_sluU, |
---|
983 | NULL, 0, |
---|
984 | &m_sluB, &m_sluX, |
---|
985 | &recip_pivot_growth, &rcond, |
---|
986 | &m_sluStat, &info, Scalar()); |
---|
987 | StatFree(&m_sluStat); |
---|
988 | |
---|
989 | m_info = info==0 ? Success : NumericalIssue; |
---|
990 | } |
---|
991 | #endif |
---|
992 | |
---|
993 | namespace internal { |
---|
994 | |
---|
995 | template<typename _MatrixType, typename Derived, typename Rhs> |
---|
996 | struct solve_retval<SuperLUBase<_MatrixType,Derived>, Rhs> |
---|
997 | : solve_retval_base<SuperLUBase<_MatrixType,Derived>, Rhs> |
---|
998 | { |
---|
999 | typedef SuperLUBase<_MatrixType,Derived> Dec; |
---|
1000 | EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) |
---|
1001 | |
---|
1002 | template<typename Dest> void evalTo(Dest& dst) const |
---|
1003 | { |
---|
1004 | dec().derived()._solve(rhs(),dst); |
---|
1005 | } |
---|
1006 | }; |
---|
1007 | |
---|
1008 | template<typename _MatrixType, typename Derived, typename Rhs> |
---|
1009 | struct sparse_solve_retval<SuperLUBase<_MatrixType,Derived>, Rhs> |
---|
1010 | : sparse_solve_retval_base<SuperLUBase<_MatrixType,Derived>, Rhs> |
---|
1011 | { |
---|
1012 | typedef SuperLUBase<_MatrixType,Derived> Dec; |
---|
1013 | EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs) |
---|
1014 | |
---|
1015 | template<typename Dest> void evalTo(Dest& dst) const |
---|
1016 | { |
---|
1017 | dec().derived()._solve(rhs(),dst); |
---|
1018 | } |
---|
1019 | }; |
---|
1020 | |
---|
1021 | } // end namespace internal |
---|
1022 | |
---|
1023 | } // end namespace Eigen |
---|
1024 | |
---|
1025 | #endif // EIGEN_SUPERLUSUPPORT_H |
---|