Eigen  3.4.90 (git rev 5a9f66fb35d03a4da9ef8976e67a61b30aa16dcf)
 
Loading...
Searching...
No Matches
PardisoSupport.h
1/*
2 Copyright (c) 2011, Intel Corporation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without modification,
5 are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this
8 list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice,
10 this list of conditions and the following disclaimer in the documentation
11 and/or other materials provided with the distribution.
12 * Neither the name of Intel Corporation nor the names of its contributors may
13 be used to endorse or promote products derived from this software without
14 specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 ********************************************************************************
28 * Content : Eigen bindings to Intel(R) MKL PARDISO
29 ********************************************************************************
30*/
31
32#ifndef EIGEN_PARDISOSUPPORT_H
33#define EIGEN_PARDISOSUPPORT_H
34
35// IWYU pragma: private
36#include "./InternalHeaderCheck.h"
37
38namespace Eigen {
39
40template <typename MatrixType_>
41class PardisoLU;
42template <typename MatrixType_, int Options = Upper>
43class PardisoLLT;
44template <typename MatrixType_, int Options = Upper>
45class PardisoLDLT;
46
47namespace internal {
48template <typename IndexType>
49struct pardiso_run_selector {
50 static IndexType run(_MKL_DSS_HANDLE_t pt, IndexType maxfct, IndexType mnum, IndexType type, IndexType phase,
51 IndexType n, void* a, IndexType* ia, IndexType* ja, IndexType* perm, IndexType nrhs,
52 IndexType* iparm, IndexType msglvl, void* b, void* x) {
53 IndexType error = 0;
54 ::pardiso(pt, &maxfct, &mnum, &type, &phase, &n, a, ia, ja, perm, &nrhs, iparm, &msglvl, b, x, &error);
55 return error;
56 }
57};
58template <>
59struct pardiso_run_selector<long long int> {
60 typedef long long int IndexType;
61 static IndexType run(_MKL_DSS_HANDLE_t pt, IndexType maxfct, IndexType mnum, IndexType type, IndexType phase,
62 IndexType n, void* a, IndexType* ia, IndexType* ja, IndexType* perm, IndexType nrhs,
63 IndexType* iparm, IndexType msglvl, void* b, void* x) {
64 IndexType error = 0;
65 ::pardiso_64(pt, &maxfct, &mnum, &type, &phase, &n, a, ia, ja, perm, &nrhs, iparm, &msglvl, b, x, &error);
66 return error;
67 }
68};
69
70template <class Pardiso>
71struct pardiso_traits;
72
73template <typename MatrixType_>
74struct pardiso_traits<PardisoLU<MatrixType_> > {
75 typedef MatrixType_ MatrixType;
76 typedef typename MatrixType_::Scalar Scalar;
77 typedef typename MatrixType_::RealScalar RealScalar;
78 typedef typename MatrixType_::StorageIndex StorageIndex;
79};
80
81template <typename MatrixType_, int Options>
82struct pardiso_traits<PardisoLLT<MatrixType_, Options> > {
83 typedef MatrixType_ MatrixType;
84 typedef typename MatrixType_::Scalar Scalar;
85 typedef typename MatrixType_::RealScalar RealScalar;
86 typedef typename MatrixType_::StorageIndex StorageIndex;
87};
88
89template <typename MatrixType_, int Options>
90struct pardiso_traits<PardisoLDLT<MatrixType_, Options> > {
91 typedef MatrixType_ MatrixType;
92 typedef typename MatrixType_::Scalar Scalar;
93 typedef typename MatrixType_::RealScalar RealScalar;
94 typedef typename MatrixType_::StorageIndex StorageIndex;
95};
96
97} // end namespace internal
98
99template <class Derived>
100class PardisoImpl : public SparseSolverBase<Derived> {
101 protected:
102 typedef SparseSolverBase<Derived> Base;
103 using Base::derived;
104 using Base::m_isInitialized;
105
106 typedef internal::pardiso_traits<Derived> Traits;
107
108 public:
109 using Base::_solve_impl;
110
111 typedef typename Traits::MatrixType MatrixType;
112 typedef typename Traits::Scalar Scalar;
113 typedef typename Traits::RealScalar RealScalar;
114 typedef typename Traits::StorageIndex StorageIndex;
115 typedef SparseMatrix<Scalar, RowMajor, StorageIndex> SparseMatrixType;
116 typedef Matrix<Scalar, Dynamic, 1> VectorType;
117 typedef Matrix<StorageIndex, 1, MatrixType::ColsAtCompileTime> IntRowVectorType;
118 typedef Matrix<StorageIndex, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
119 typedef Array<StorageIndex, 64, 1, DontAlign> ParameterType;
120 enum { ScalarIsComplex = NumTraits<Scalar>::IsComplex, ColsAtCompileTime = Dynamic, MaxColsAtCompileTime = Dynamic };
121
122 PardisoImpl() : m_analysisIsOk(false), m_factorizationIsOk(false) {
123 eigen_assert((sizeof(StorageIndex) >= sizeof(_INTEGER_t) && sizeof(StorageIndex) <= 8) &&
124 "Non-supported index type");
125 m_iparm.setZero();
126 m_msglvl = 0; // No output
127 m_isInitialized = false;
128 }
129
130 ~PardisoImpl() { pardisoRelease(); }
131
132 inline Index cols() const { return m_size; }
133 inline Index rows() const { return m_size; }
134
140 ComputationInfo info() const {
141 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
142 return m_info;
143 }
144
148 ParameterType& pardisoParameterArray() { return m_iparm; }
149
156 Derived& analyzePattern(const MatrixType& matrix);
157
164 Derived& factorize(const MatrixType& matrix);
165
166 Derived& compute(const MatrixType& matrix);
167
168 template <typename Rhs, typename Dest>
169 void _solve_impl(const MatrixBase<Rhs>& b, MatrixBase<Dest>& dest) const;
170
171 protected:
172 void pardisoRelease() {
173 if (m_isInitialized) // Factorization ran at least once
174 {
175 internal::pardiso_run_selector<StorageIndex>::run(m_pt, 1, 1, m_type, -1,
176 internal::convert_index<StorageIndex>(m_size), 0, 0, 0,
177 m_perm.data(), 0, m_iparm.data(), m_msglvl, NULL, NULL);
178 m_isInitialized = false;
179 }
180 }
181
182 void pardisoInit(int type) {
183 m_type = type;
184 bool symmetric = std::abs(m_type) < 10;
185 m_iparm[0] = 1; // No solver default
186 m_iparm[1] = 2; // use Metis for the ordering
187 m_iparm[2] = 0; // Reserved. Set to zero. (??Numbers of processors, value of OMP_NUM_THREADS??)
188 m_iparm[3] = 0; // No iterative-direct algorithm
189 m_iparm[4] = 0; // No user fill-in reducing permutation
190 m_iparm[5] = 0; // Write solution into x, b is left unchanged
191 m_iparm[6] = 0; // Not in use
192 m_iparm[7] = 2; // Max numbers of iterative refinement steps
193 m_iparm[8] = 0; // Not in use
194 m_iparm[9] = 13; // Perturb the pivot elements with 1E-13
195 m_iparm[10] = symmetric ? 0 : 1; // Use nonsymmetric permutation and scaling MPS
196 m_iparm[11] = 0; // Not in use
197 m_iparm[12] = symmetric ? 0 : 1; // Maximum weighted matching algorithm is switched-off (default for symmetric).
198 // Try m_iparm[12] = 1 in case of inappropriate accuracy
199 m_iparm[13] = 0; // Output: Number of perturbed pivots
200 m_iparm[14] = 0; // Not in use
201 m_iparm[15] = 0; // Not in use
202 m_iparm[16] = 0; // Not in use
203 m_iparm[17] = -1; // Output: Number of nonzeros in the factor LU
204 m_iparm[18] = -1; // Output: Mflops for LU factorization
205 m_iparm[19] = 0; // Output: Numbers of CG Iterations
206
207 m_iparm[20] = 0; // 1x1 pivoting
208 m_iparm[26] = 0; // No matrix checker
209 m_iparm[27] = (sizeof(RealScalar) == 4) ? 1 : 0;
210 m_iparm[34] = 1; // C indexing
211 m_iparm[36] = 0; // CSR
212 m_iparm[59] = 0; // 0 - In-Core ; 1 - Automatic switch between In-Core and Out-of-Core modes ; 2 - Out-of-Core
213
214 memset(m_pt, 0, sizeof(m_pt));
215 }
216
217 protected:
218 // cached data to reduce reallocation, etc.
219
220 void manageErrorCode(Index error) const {
221 switch (error) {
222 case 0:
223 m_info = Success;
224 break;
225 case -4:
226 case -7:
227 m_info = NumericalIssue;
228 break;
229 default:
230 m_info = InvalidInput;
231 }
232 }
233
234 mutable SparseMatrixType m_matrix;
235 mutable ComputationInfo m_info;
236 bool m_analysisIsOk, m_factorizationIsOk;
237 StorageIndex m_type, m_msglvl;
238 mutable void* m_pt[64];
239 mutable ParameterType m_iparm;
240 mutable IntColVectorType m_perm;
241 Index m_size;
242};
243
244template <class Derived>
245Derived& PardisoImpl<Derived>::compute(const MatrixType& a) {
246 m_size = a.rows();
247 eigen_assert(a.rows() == a.cols());
248
249 pardisoRelease();
250 m_perm.setZero(m_size);
251 derived().getMatrix(a);
252
253 Index error;
254 error = internal::pardiso_run_selector<StorageIndex>::run(
255 m_pt, 1, 1, m_type, 12, internal::convert_index<StorageIndex>(m_size), m_matrix.valuePtr(),
256 m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), m_perm.data(), 0, m_iparm.data(), m_msglvl, NULL, NULL);
257 manageErrorCode(error);
258 m_analysisIsOk = m_info == Eigen::Success;
259 m_factorizationIsOk = m_info == Eigen::Success;
260 m_isInitialized = true;
261 return derived();
262}
263
264template <class Derived>
265Derived& PardisoImpl<Derived>::analyzePattern(const MatrixType& a) {
266 m_size = a.rows();
267 eigen_assert(m_size == a.cols());
268
269 pardisoRelease();
270 m_perm.setZero(m_size);
271 derived().getMatrix(a);
272
273 Index error;
274 error = internal::pardiso_run_selector<StorageIndex>::run(
275 m_pt, 1, 1, m_type, 11, internal::convert_index<StorageIndex>(m_size), m_matrix.valuePtr(),
276 m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), m_perm.data(), 0, m_iparm.data(), m_msglvl, NULL, NULL);
277
278 manageErrorCode(error);
279 m_analysisIsOk = m_info == Eigen::Success;
280 m_factorizationIsOk = false;
281 m_isInitialized = true;
282 return derived();
283}
284
285template <class Derived>
286Derived& PardisoImpl<Derived>::factorize(const MatrixType& a) {
287 eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
288 eigen_assert(m_size == a.rows() && m_size == a.cols());
289
290 derived().getMatrix(a);
291
292 Index error;
293 error = internal::pardiso_run_selector<StorageIndex>::run(
294 m_pt, 1, 1, m_type, 22, internal::convert_index<StorageIndex>(m_size), m_matrix.valuePtr(),
295 m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), m_perm.data(), 0, m_iparm.data(), m_msglvl, NULL, NULL);
296
297 manageErrorCode(error);
298 m_factorizationIsOk = m_info == Eigen::Success;
299 return derived();
300}
301
302template <class Derived>
303template <typename BDerived, typename XDerived>
304void PardisoImpl<Derived>::_solve_impl(const MatrixBase<BDerived>& b, MatrixBase<XDerived>& x) const {
305 if (m_iparm[0] == 0) // Factorization was not computed
306 {
307 m_info = InvalidInput;
308 return;
309 }
310
311 // Index n = m_matrix.rows();
312 Index nrhs = Index(b.cols());
313 eigen_assert(m_size == b.rows());
314 eigen_assert(((MatrixBase<BDerived>::Flags & RowMajorBit) == 0 || nrhs == 1) &&
315 "Row-major right hand sides are not supported");
316 eigen_assert(((MatrixBase<XDerived>::Flags & RowMajorBit) == 0 || nrhs == 1) &&
317 "Row-major matrices of unknowns are not supported");
318 eigen_assert(((nrhs == 1) || b.outerStride() == b.rows()));
319
320 // switch (transposed) {
321 // case SvNoTrans : m_iparm[11] = 0 ; break;
322 // case SvTranspose : m_iparm[11] = 2 ; break;
323 // case SvAdjoint : m_iparm[11] = 1 ; break;
324 // default:
325 // //std::cerr << "Eigen: transposition option \"" << transposed << "\" not supported by the PARDISO backend\n";
326 // m_iparm[11] = 0;
327 // }
328
329 Scalar* rhs_ptr = const_cast<Scalar*>(b.derived().data());
330 Matrix<Scalar, Dynamic, Dynamic, ColMajor> tmp;
331
332 // Pardiso cannot solve in-place
333 if (rhs_ptr == x.derived().data()) {
334 tmp = b;
335 rhs_ptr = tmp.data();
336 }
337
338 Index error;
339 error = internal::pardiso_run_selector<StorageIndex>::run(
340 m_pt, 1, 1, m_type, 33, internal::convert_index<StorageIndex>(m_size), m_matrix.valuePtr(),
341 m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), m_perm.data(), internal::convert_index<StorageIndex>(nrhs),
342 m_iparm.data(), m_msglvl, rhs_ptr, x.derived().data());
343
344 manageErrorCode(error);
345}
346
364template <typename MatrixType>
365class PardisoLU : public PardisoImpl<PardisoLU<MatrixType> > {
366 protected:
367 typedef PardisoImpl<PardisoLU> Base;
368 using Base::m_matrix;
369 using Base::pardisoInit;
370 friend class PardisoImpl<PardisoLU<MatrixType> >;
371
372 public:
373 typedef typename Base::Scalar Scalar;
374 typedef typename Base::RealScalar RealScalar;
375
376 using Base::compute;
377 using Base::solve;
378
379 PardisoLU() : Base() { pardisoInit(Base::ScalarIsComplex ? 13 : 11); }
380
381 explicit PardisoLU(const MatrixType& matrix) : Base() {
382 pardisoInit(Base::ScalarIsComplex ? 13 : 11);
383 compute(matrix);
384 }
385
386 protected:
387 void getMatrix(const MatrixType& matrix) {
388 m_matrix = matrix;
389 m_matrix.makeCompressed();
390 }
391};
392
412template <typename MatrixType, int UpLo_>
413class PardisoLLT : public PardisoImpl<PardisoLLT<MatrixType, UpLo_> > {
414 protected:
415 typedef PardisoImpl<PardisoLLT<MatrixType, UpLo_> > Base;
416 using Base::m_matrix;
417 using Base::pardisoInit;
418 friend class PardisoImpl<PardisoLLT<MatrixType, UpLo_> >;
419
420 public:
421 typedef typename Base::Scalar Scalar;
422 typedef typename Base::RealScalar RealScalar;
423 typedef typename Base::StorageIndex StorageIndex;
424 enum { UpLo = UpLo_ };
425 using Base::compute;
426
427 PardisoLLT() : Base() { pardisoInit(Base::ScalarIsComplex ? 4 : 2); }
428
429 explicit PardisoLLT(const MatrixType& matrix) : Base() {
430 pardisoInit(Base::ScalarIsComplex ? 4 : 2);
431 compute(matrix);
432 }
433
434 protected:
435 void getMatrix(const MatrixType& matrix) {
436 // PARDISO supports only upper, row-major matrices
438 m_matrix.resize(matrix.rows(), matrix.cols());
439 m_matrix.template selfadjointView<Upper>() = matrix.template selfadjointView<UpLo>().twistedBy(p_null);
440 m_matrix.makeCompressed();
441 }
442};
443
466template <typename MatrixType, int Options>
467class PardisoLDLT : public PardisoImpl<PardisoLDLT<MatrixType, Options> > {
468 protected:
469 typedef PardisoImpl<PardisoLDLT<MatrixType, Options> > Base;
470 using Base::m_matrix;
471 using Base::pardisoInit;
472 friend class PardisoImpl<PardisoLDLT<MatrixType, Options> >;
473
474 public:
475 typedef typename Base::Scalar Scalar;
476 typedef typename Base::RealScalar RealScalar;
477 typedef typename Base::StorageIndex StorageIndex;
478 using Base::compute;
479 enum { UpLo = Options & (Upper | Lower) };
480
481 PardisoLDLT() : Base() { pardisoInit(Base::ScalarIsComplex ? (bool(Options & Symmetric) ? 6 : -4) : -2); }
482
483 explicit PardisoLDLT(const MatrixType& matrix) : Base() {
484 pardisoInit(Base::ScalarIsComplex ? (bool(Options & Symmetric) ? 6 : -4) : -2);
485 compute(matrix);
486 }
487
488 void getMatrix(const MatrixType& matrix) {
489 // PARDISO supports only upper, row-major matrices
491 m_matrix.resize(matrix.rows(), matrix.cols());
492 m_matrix.template selfadjointView<Upper>() = matrix.template selfadjointView<UpLo>().twistedBy(p_null);
493 m_matrix.makeCompressed();
494 }
495};
496
497} // end namespace Eigen
498
499#endif // EIGEN_PARDISOSUPPORT_H
A sparse direct Cholesky (LDLT) factorization and solver based on the PARDISO library.
Definition PardisoSupport.h:467
A sparse direct Cholesky (LLT) factorization and solver based on the PARDISO library.
Definition PardisoSupport.h:413
A sparse direct LU factorization and solver based on the PARDISO library.
Definition PardisoSupport.h:365
Permutation matrix.
Definition PermutationMatrix.h:280
Derived & setZero(Index size)
Definition CwiseNullaryOp.h:563
const Scalar * data() const
Definition PlainObjectBase.h:273
SparseSymmetricPermutationProduct< Derived, Upper|Lower > twistedBy(const PermutationMatrix< Dynamic, Dynamic, StorageIndex > &perm) const
Definition SparseMatrixBase.h:325
void makeCompressed()
Definition SparseMatrix.h:588
void resize(Index rows, Index cols)
Definition SparseMatrix.h:730
const Solve< Derived, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition SparseSolverBase.h:84
SparseSolverBase()
Definition SparseSolverBase.h:70
@ Symmetric
Definition Constants.h:229
@ Lower
Definition Constants.h:211
@ Upper
Definition Constants.h:213
@ NumericalIssue
Definition Constants.h:442
@ InvalidInput
Definition Constants.h:447
@ Success
Definition Constants.h:440
Namespace containing all symbols from the Eigen library.
Definition Core:137
const int Dynamic
Definition Constants.h:25