Eigen  5.0.1
 
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// SPDX-License-Identifier: BSD-3-Clause
32
33#ifndef EIGEN_PARDISOSUPPORT_H
34#define EIGEN_PARDISOSUPPORT_H
35
36// IWYU pragma: private
37#include "./InternalHeaderCheck.h"
38
39namespace Eigen {
40
41template <typename MatrixType_>
42class PardisoLU;
43template <typename MatrixType_, int Options = Upper>
44class PardisoLLT;
45template <typename MatrixType_, int Options = Upper>
46class PardisoLDLT;
47
48namespace internal {
49template <typename IndexType>
50struct pardiso_run_selector {
51 static IndexType run(_MKL_DSS_HANDLE_t pt, IndexType maxfct, IndexType mnum, IndexType type, IndexType phase,
52 IndexType n, void* a, IndexType* ia, IndexType* ja, IndexType* perm, IndexType nrhs,
53 IndexType* iparm, IndexType msglvl, void* b, void* x) {
54 IndexType error = 0;
55 ::pardiso(pt, &maxfct, &mnum, &type, &phase, &n, a, ia, ja, perm, &nrhs, iparm, &msglvl, b, x, &error);
56 return error;
57 }
58};
59template <>
60struct pardiso_run_selector<long long int> {
61 typedef long long int IndexType;
62 static IndexType run(_MKL_DSS_HANDLE_t pt, IndexType maxfct, IndexType mnum, IndexType type, IndexType phase,
63 IndexType n, void* a, IndexType* ia, IndexType* ja, IndexType* perm, IndexType nrhs,
64 IndexType* iparm, IndexType msglvl, void* b, void* x) {
65 IndexType error = 0;
66 ::pardiso_64(pt, &maxfct, &mnum, &type, &phase, &n, a, ia, ja, perm, &nrhs, iparm, &msglvl, b, x, &error);
67 return error;
68 }
69};
70
71template <class Pardiso>
72struct pardiso_traits;
73
74template <typename MatrixType_>
75struct pardiso_traits<PardisoLU<MatrixType_> > {
76 typedef MatrixType_ MatrixType;
77 typedef typename MatrixType_::Scalar Scalar;
78 typedef typename MatrixType_::RealScalar RealScalar;
79 typedef typename MatrixType_::StorageIndex StorageIndex;
80};
81
82template <typename MatrixType_, int Options>
83struct pardiso_traits<PardisoLLT<MatrixType_, Options> > {
84 typedef MatrixType_ MatrixType;
85 typedef typename MatrixType_::Scalar Scalar;
86 typedef typename MatrixType_::RealScalar RealScalar;
87 typedef typename MatrixType_::StorageIndex StorageIndex;
88};
89
90template <typename MatrixType_, int Options>
91struct pardiso_traits<PardisoLDLT<MatrixType_, Options> > {
92 typedef MatrixType_ MatrixType;
93 typedef typename MatrixType_::Scalar Scalar;
94 typedef typename MatrixType_::RealScalar RealScalar;
95 typedef typename MatrixType_::StorageIndex StorageIndex;
96};
97
98} // end namespace internal
99
100template <class Derived>
101class PardisoImpl : public SparseSolverBase<Derived> {
102 protected:
103 typedef SparseSolverBase<Derived> Base;
104 using Base::derived;
105 using Base::m_isInitialized;
106
107 typedef internal::pardiso_traits<Derived> Traits;
108
109 public:
110 using Base::_solve_impl;
111
112 typedef typename Traits::MatrixType MatrixType;
113 typedef typename Traits::Scalar Scalar;
114 typedef typename Traits::RealScalar RealScalar;
115 typedef typename Traits::StorageIndex StorageIndex;
116 typedef SparseMatrix<Scalar, RowMajor, StorageIndex> SparseMatrixType;
117 typedef Matrix<Scalar, Dynamic, 1> VectorType;
118 typedef Matrix<StorageIndex, 1, MatrixType::ColsAtCompileTime> IntRowVectorType;
119 typedef Matrix<StorageIndex, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
120 typedef Array<StorageIndex, 64, 1, DontAlign> ParameterType;
121 enum { ScalarIsComplex = NumTraits<Scalar>::IsComplex, ColsAtCompileTime = Dynamic, MaxColsAtCompileTime = Dynamic };
122
123 PardisoImpl() : m_analysisIsOk(false), m_factorizationIsOk(false) {
124 eigen_assert((sizeof(StorageIndex) >= sizeof(_INTEGER_t) && sizeof(StorageIndex) <= 8) &&
125 "Non-supported index type");
126 m_iparm.setZero();
127 m_msglvl = 0; // No output
128 m_isInitialized = false;
129 }
130
131 ~PardisoImpl() { pardisoRelease(); }
132
133 inline Index cols() const { return m_size; }
134 inline Index rows() const { return m_size; }
135
141 ComputationInfo info() const {
142 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
143 return m_info;
144 }
145
149 ParameterType& pardisoParameterArray() { return m_iparm; }
150
157 Derived& analyzePattern(const MatrixType& matrix);
158
166 Derived& factorize(const MatrixType& matrix);
167
168 Derived& compute(const MatrixType& matrix);
169
170 template <typename Rhs, typename Dest>
171 void _solve_impl(const MatrixBase<Rhs>& b, MatrixBase<Dest>& dest) const;
172
173 protected:
174 void pardisoRelease() {
175 if (m_isInitialized) // Factorization ran at least once
176 {
177 internal::pardiso_run_selector<StorageIndex>::run(m_pt, 1, 1, m_type, -1,
178 internal::convert_index<StorageIndex>(m_size), 0, 0, 0,
179 m_perm.data(), 0, m_iparm.data(), m_msglvl, nullptr, nullptr);
180 m_isInitialized = false;
181 }
182 }
183
184 void pardisoInit(int type) {
185 m_type = type;
186 bool symmetric = numext::abs(m_type) < 10;
187 m_iparm[0] = 1; // No solver default
188 m_iparm[1] = 2; // use Metis for the ordering
189 m_iparm[2] = 0; // Reserved. Set to zero. (Was number of processors / OMP_NUM_THREADS.)
190 m_iparm[3] = 0; // No iterative-direct algorithm
191 m_iparm[4] = 0; // No user fill-in reducing permutation
192 m_iparm[5] = 0; // Write solution into x, b is left unchanged
193 m_iparm[6] = 0; // Not in use
194 m_iparm[7] = 2; // Max numbers of iterative refinement steps
195 m_iparm[8] = 0; // Not in use
196 m_iparm[9] = 13; // Perturb the pivot elements with 1E-13
197 m_iparm[10] = symmetric ? 0 : 1; // Use nonsymmetric permutation and scaling MPS
198 m_iparm[11] = 0; // Not in use
199 m_iparm[12] = symmetric ? 0 : 1; // Maximum weighted matching algorithm is switched-off (default for symmetric).
200 // Try m_iparm[12] = 1 in case of inappropriate accuracy
201 m_iparm[13] = 0; // Output: Number of perturbed pivots
202 m_iparm[14] = 0; // Not in use
203 m_iparm[15] = 0; // Not in use
204 m_iparm[16] = 0; // Not in use
205 m_iparm[17] = -1; // Output: Number of nonzeros in the factor LU
206 m_iparm[18] = -1; // Output: Mflops for LU factorization
207 m_iparm[19] = 0; // Output: Numbers of CG Iterations
208
209 m_iparm[20] = 0; // 1x1 pivoting
210 m_iparm[26] = 0; // No matrix checker
211 m_iparm[27] = (sizeof(RealScalar) == 4) ? 1 : 0;
212 m_iparm[34] = 1; // C indexing
213 m_iparm[36] = 0; // CSR
214 m_iparm[59] = 0; // 0 - In-Core ; 1 - Automatic switch between In-Core and Out-of-Core modes ; 2 - Out-of-Core
215
216 memset(m_pt, 0, sizeof(m_pt));
217 }
218
219 protected:
220 // cached data to reduce reallocation, etc.
221
222 void manageErrorCode(Index error) const {
223 switch (error) {
224 case 0:
225 m_info = Success;
226 break;
227 case -4:
228 case -7:
229 m_info = NumericalIssue;
230 break;
231 default:
232 m_info = InvalidInput;
233 }
234 }
235
236 mutable SparseMatrixType m_matrix;
237 mutable ComputationInfo m_info;
238 bool m_analysisIsOk, m_factorizationIsOk;
239 StorageIndex m_type, m_msglvl;
240 mutable void* m_pt[64];
241 mutable ParameterType m_iparm;
242 mutable IntColVectorType m_perm;
243 Index m_size;
244};
245
246template <class Derived>
247Derived& PardisoImpl<Derived>::compute(const MatrixType& a) {
248 m_size = a.rows();
249 eigen_assert(a.rows() == a.cols());
250
251 pardisoRelease();
252 m_perm.setZero(m_size);
253 derived().getMatrix(a);
254
255 Index error;
256 error = internal::pardiso_run_selector<StorageIndex>::run(
257 m_pt, 1, 1, m_type, 12, internal::convert_index<StorageIndex>(m_size), m_matrix.valuePtr(),
258 m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), m_perm.data(), 0, m_iparm.data(), m_msglvl, nullptr, nullptr);
259 manageErrorCode(error);
260 m_analysisIsOk = m_info == Eigen::Success;
261 m_factorizationIsOk = m_info == Eigen::Success;
262 m_isInitialized = true;
263 return derived();
264}
265
266template <class Derived>
267Derived& PardisoImpl<Derived>::analyzePattern(const MatrixType& a) {
268 m_size = a.rows();
269 eigen_assert(m_size == a.cols());
270
271 pardisoRelease();
272 m_perm.setZero(m_size);
273 derived().getMatrix(a);
274
275 Index error;
276 error = internal::pardiso_run_selector<StorageIndex>::run(
277 m_pt, 1, 1, m_type, 11, internal::convert_index<StorageIndex>(m_size), m_matrix.valuePtr(),
278 m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), m_perm.data(), 0, m_iparm.data(), m_msglvl, nullptr, nullptr);
279
280 manageErrorCode(error);
281 m_analysisIsOk = m_info == Eigen::Success;
282 m_factorizationIsOk = false;
283 m_isInitialized = true;
284 return derived();
285}
286
287template <class Derived>
288Derived& PardisoImpl<Derived>::factorize(const MatrixType& a) {
289 eigen_assert(m_analysisIsOk && "You must first call analyzePattern()");
290 eigen_assert(m_size == a.rows() && m_size == a.cols());
291
292 derived().getMatrix(a);
293
294 Index error;
295 error = internal::pardiso_run_selector<StorageIndex>::run(
296 m_pt, 1, 1, m_type, 22, internal::convert_index<StorageIndex>(m_size), m_matrix.valuePtr(),
297 m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), m_perm.data(), 0, m_iparm.data(), m_msglvl, nullptr, nullptr);
298
299 manageErrorCode(error);
300 m_factorizationIsOk = m_info == Eigen::Success;
301 return derived();
302}
303
304template <class Derived>
305template <typename BDerived, typename XDerived>
306void PardisoImpl<Derived>::_solve_impl(const MatrixBase<BDerived>& b, MatrixBase<XDerived>& x) const {
307 if (m_iparm[0] == 0) // Factorization was not computed
308 {
309 m_info = InvalidInput;
310 return;
311 }
312
313 Index nrhs = Index(b.cols());
314 eigen_assert(m_size == b.rows());
315 eigen_assert(((MatrixBase<BDerived>::Flags & RowMajorBit) == 0 || nrhs == 1) &&
316 "Row-major right hand sides are not supported");
317 eigen_assert(((MatrixBase<XDerived>::Flags & RowMajorBit) == 0 || nrhs == 1) &&
318 "Row-major matrices of unknowns are not supported");
319 eigen_assert(((nrhs == 1) || b.outerStride() == b.rows()));
320
321 // switch (transposed) {
322 // case SvNoTrans : m_iparm[11] = 0 ; break;
323 // case SvTranspose : m_iparm[11] = 2 ; break;
324 // case SvAdjoint : m_iparm[11] = 1 ; break;
325 // default:
326 // //std::cerr << "Eigen: transposition option \"" << transposed << "\" not supported by the PARDISO backend\n";
327 // m_iparm[11] = 0;
328 // }
329
330 Scalar* rhs_ptr = const_cast<Scalar*>(b.derived().data());
332
333 // Pardiso cannot solve in-place
334 if (rhs_ptr == x.derived().data()) {
335 tmp = b;
336 rhs_ptr = tmp.data();
337 }
338
339 Index error;
340 error = internal::pardiso_run_selector<StorageIndex>::run(
341 m_pt, 1, 1, m_type, 33, internal::convert_index<StorageIndex>(m_size), m_matrix.valuePtr(),
342 m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), m_perm.data(), internal::convert_index<StorageIndex>(nrhs),
343 m_iparm.data(), m_msglvl, rhs_ptr, x.derived().data());
344
345 manageErrorCode(error);
346}
347
365template <typename MatrixType>
366class PardisoLU : public PardisoImpl<PardisoLU<MatrixType> > {
367 protected:
368 typedef PardisoImpl<PardisoLU> Base;
369 using Base::m_matrix;
370 using Base::pardisoInit;
371 friend class PardisoImpl<PardisoLU<MatrixType> >;
372
373 public:
374 typedef typename Base::Scalar Scalar;
375 typedef typename Base::RealScalar RealScalar;
376
377 using Base::compute;
378 using Base::solve;
379
380 PardisoLU() : Base() { pardisoInit(Base::ScalarIsComplex ? 13 : 11); }
381
382 explicit PardisoLU(const MatrixType& matrix) : Base() {
383 pardisoInit(Base::ScalarIsComplex ? 13 : 11);
384 compute(matrix);
385 }
386
387 protected:
388 void getMatrix(const MatrixType& matrix) {
389 m_matrix = matrix;
390 m_matrix.makeCompressed();
391 }
392};
393
413template <typename MatrixType, int UpLo_>
414class PardisoLLT : public PardisoImpl<PardisoLLT<MatrixType, UpLo_> > {
415 protected:
416 typedef PardisoImpl<PardisoLLT<MatrixType, UpLo_> > Base;
417 using Base::m_matrix;
418 using Base::pardisoInit;
419 friend class PardisoImpl<PardisoLLT<MatrixType, UpLo_> >;
420
421 public:
422 typedef typename Base::Scalar Scalar;
423 typedef typename Base::RealScalar RealScalar;
424 typedef typename Base::StorageIndex StorageIndex;
425 enum { UpLo = UpLo_ };
426 using Base::compute;
427
428 PardisoLLT() : Base() { pardisoInit(Base::ScalarIsComplex ? 4 : 2); }
429
430 explicit PardisoLLT(const MatrixType& matrix) : Base() {
431 pardisoInit(Base::ScalarIsComplex ? 4 : 2);
432 compute(matrix);
433 }
434
435 protected:
436 void getMatrix(const MatrixType& matrix) {
437 // PARDISO supports only upper, row-major matrices
439 m_matrix.resize(matrix.rows(), matrix.cols());
440 m_matrix.template selfadjointView<Upper>() = matrix.template selfadjointView<UpLo>().twistedBy(p_null);
441 m_matrix.makeCompressed();
442 }
443};
444
467template <typename MatrixType, int Options>
468class PardisoLDLT : public PardisoImpl<PardisoLDLT<MatrixType, Options> > {
469 protected:
470 typedef PardisoImpl<PardisoLDLT<MatrixType, Options> > Base;
471 using Base::m_matrix;
472 using Base::pardisoInit;
473 friend class PardisoImpl<PardisoLDLT<MatrixType, Options> >;
474
475 public:
476 typedef typename Base::Scalar Scalar;
477 typedef typename Base::RealScalar RealScalar;
478 typedef typename Base::StorageIndex StorageIndex;
479 using Base::compute;
480 enum { UpLo = Options & (Upper | Lower) };
481
482 PardisoLDLT() : Base() { pardisoInit(Base::ScalarIsComplex ? (bool(Options & Symmetric) ? 6 : -4) : -2); }
483
484 explicit PardisoLDLT(const MatrixType& matrix) : Base() {
485 pardisoInit(Base::ScalarIsComplex ? (bool(Options & Symmetric) ? 6 : -4) : -2);
486 compute(matrix);
487 }
488
489 void getMatrix(const MatrixType& matrix) {
490 // PARDISO supports only upper, row-major matrices
492 m_matrix.resize(matrix.rows(), matrix.cols());
493 m_matrix.template selfadjointView<Upper>() = matrix.template selfadjointView<UpLo>().twistedBy(p_null);
494 m_matrix.makeCompressed();
495 }
496};
497
498} // end namespace Eigen
499
500#endif // EIGEN_PARDISOSUPPORT_H
@ Flags
Definition DenseBase.h:162
Base class for all dense matrices, vectors, and expressions.
Definition MatrixBase.h:53
The matrix class, also used for vectors and row-vectors.
Definition Matrix.h:188
A sparse direct Cholesky (LDLT) factorization and solver based on the PARDISO library.
Definition PardisoSupport.h:468
A sparse direct Cholesky (LLT) factorization and solver based on the PARDISO library.
Definition PardisoSupport.h:414
A sparse direct LU factorization and solver based on the PARDISO library.
Definition PardisoSupport.h:366
void resize(Index newSize)
Definition PermutationMatrix.h:165
Permutation matrix.
Definition PermutationMatrix.h:346
A base class for sparse solvers.
Definition SparseSolverBase.h:68
Solve< Derived, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition SparseSolverBase.h:88
ComputationInfo
Definition Constants.h:455
@ Symmetric
Definition Constants.h:230
@ Lower
Definition Constants.h:212
@ Upper
Definition Constants.h:214
@ NumericalIssue
Definition Constants.h:459
@ InvalidInput
Definition Constants.h:464
@ Success
Definition Constants.h:457
constexpr unsigned int RowMajorBit
Definition Constants.h:71