Warning, file /include/eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_PASTIXSUPPORT_H
0011 #define EIGEN_PASTIXSUPPORT_H
0012
0013 namespace Eigen {
0014
0015 #if defined(DCOMPLEX)
0016 #define PASTIX_COMPLEX COMPLEX
0017 #define PASTIX_DCOMPLEX DCOMPLEX
0018 #else
0019 #define PASTIX_COMPLEX std::complex<float>
0020 #define PASTIX_DCOMPLEX std::complex<double>
0021 #endif
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 template<typename _MatrixType, bool IsStrSym = false> class PastixLU;
0032 template<typename _MatrixType, int Options> class PastixLLT;
0033 template<typename _MatrixType, int Options> class PastixLDLT;
0034
0035 namespace internal
0036 {
0037
0038 template<class Pastix> struct pastix_traits;
0039
0040 template<typename _MatrixType>
0041 struct pastix_traits< PastixLU<_MatrixType> >
0042 {
0043 typedef _MatrixType MatrixType;
0044 typedef typename _MatrixType::Scalar Scalar;
0045 typedef typename _MatrixType::RealScalar RealScalar;
0046 typedef typename _MatrixType::StorageIndex StorageIndex;
0047 };
0048
0049 template<typename _MatrixType, int Options>
0050 struct pastix_traits< PastixLLT<_MatrixType,Options> >
0051 {
0052 typedef _MatrixType MatrixType;
0053 typedef typename _MatrixType::Scalar Scalar;
0054 typedef typename _MatrixType::RealScalar RealScalar;
0055 typedef typename _MatrixType::StorageIndex StorageIndex;
0056 };
0057
0058 template<typename _MatrixType, int Options>
0059 struct pastix_traits< PastixLDLT<_MatrixType,Options> >
0060 {
0061 typedef _MatrixType MatrixType;
0062 typedef typename _MatrixType::Scalar Scalar;
0063 typedef typename _MatrixType::RealScalar RealScalar;
0064 typedef typename _MatrixType::StorageIndex StorageIndex;
0065 };
0066
0067 inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, float *vals, int *perm, int * invp, float *x, int nbrhs, int *iparm, double *dparm)
0068 {
0069 if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
0070 if (nbrhs == 0) {x = NULL; nbrhs=1;}
0071 s_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm);
0072 }
0073
0074 inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, double *vals, int *perm, int * invp, double *x, int nbrhs, int *iparm, double *dparm)
0075 {
0076 if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
0077 if (nbrhs == 0) {x = NULL; nbrhs=1;}
0078 d_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm);
0079 }
0080
0081 inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex<float> *vals, int *perm, int * invp, std::complex<float> *x, int nbrhs, int *iparm, double *dparm)
0082 {
0083 if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
0084 if (nbrhs == 0) {x = NULL; nbrhs=1;}
0085 c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<PASTIX_COMPLEX*>(vals), perm, invp, reinterpret_cast<PASTIX_COMPLEX*>(x), nbrhs, iparm, dparm);
0086 }
0087
0088 inline void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex<double> *vals, int *perm, int * invp, std::complex<double> *x, int nbrhs, int *iparm, double *dparm)
0089 {
0090 if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; }
0091 if (nbrhs == 0) {x = NULL; nbrhs=1;}
0092 z_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast<PASTIX_DCOMPLEX*>(vals), perm, invp, reinterpret_cast<PASTIX_DCOMPLEX*>(x), nbrhs, iparm, dparm);
0093 }
0094
0095
0096 template <typename MatrixType>
0097 void c_to_fortran_numbering (MatrixType& mat)
0098 {
0099 if ( !(mat.outerIndexPtr()[0]) )
0100 {
0101 int i;
0102 for(i = 0; i <= mat.rows(); ++i)
0103 ++mat.outerIndexPtr()[i];
0104 for(i = 0; i < mat.nonZeros(); ++i)
0105 ++mat.innerIndexPtr()[i];
0106 }
0107 }
0108
0109
0110 template <typename MatrixType>
0111 void fortran_to_c_numbering (MatrixType& mat)
0112 {
0113
0114 if ( mat.outerIndexPtr()[0] == 1 )
0115 {
0116 int i;
0117 for(i = 0; i <= mat.rows(); ++i)
0118 --mat.outerIndexPtr()[i];
0119 for(i = 0; i < mat.nonZeros(); ++i)
0120 --mat.innerIndexPtr()[i];
0121 }
0122 }
0123 }
0124
0125
0126
0127 template <class Derived>
0128 class PastixBase : public SparseSolverBase<Derived>
0129 {
0130 protected:
0131 typedef SparseSolverBase<Derived> Base;
0132 using Base::derived;
0133 using Base::m_isInitialized;
0134 public:
0135 using Base::_solve_impl;
0136
0137 typedef typename internal::pastix_traits<Derived>::MatrixType _MatrixType;
0138 typedef _MatrixType MatrixType;
0139 typedef typename MatrixType::Scalar Scalar;
0140 typedef typename MatrixType::RealScalar RealScalar;
0141 typedef typename MatrixType::StorageIndex StorageIndex;
0142 typedef Matrix<Scalar,Dynamic,1> Vector;
0143 typedef SparseMatrix<Scalar, ColMajor> ColSpMatrix;
0144 enum {
0145 ColsAtCompileTime = MatrixType::ColsAtCompileTime,
0146 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime
0147 };
0148
0149 public:
0150
0151 PastixBase() : m_initisOk(false), m_analysisIsOk(false), m_factorizationIsOk(false), m_pastixdata(0), m_size(0)
0152 {
0153 init();
0154 }
0155
0156 ~PastixBase()
0157 {
0158 clean();
0159 }
0160
0161 template<typename Rhs,typename Dest>
0162 bool _solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &x) const;
0163
0164
0165
0166
0167
0168
0169 Array<StorageIndex,IPARM_SIZE,1>& iparm()
0170 {
0171 return m_iparm;
0172 }
0173
0174
0175
0176
0177
0178 int& iparm(int idxparam)
0179 {
0180 return m_iparm(idxparam);
0181 }
0182
0183
0184
0185
0186
0187 Array<double,DPARM_SIZE,1>& dparm()
0188 {
0189 return m_dparm;
0190 }
0191
0192
0193
0194
0195
0196 double& dparm(int idxparam)
0197 {
0198 return m_dparm(idxparam);
0199 }
0200
0201 inline Index cols() const { return m_size; }
0202 inline Index rows() const { return m_size; }
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212 ComputationInfo info() const
0213 {
0214 eigen_assert(m_isInitialized && "Decomposition is not initialized.");
0215 return m_info;
0216 }
0217
0218 protected:
0219
0220
0221 void init();
0222
0223
0224 void analyzePattern(ColSpMatrix& mat);
0225
0226
0227 void factorize(ColSpMatrix& mat);
0228
0229
0230 void clean()
0231 {
0232 eigen_assert(m_initisOk && "The Pastix structure should be allocated first");
0233 m_iparm(IPARM_START_TASK) = API_TASK_CLEAN;
0234 m_iparm(IPARM_END_TASK) = API_TASK_CLEAN;
0235 internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, 0, 0, 0, (Scalar*)0,
0236 m_perm.data(), m_invp.data(), 0, 0, m_iparm.data(), m_dparm.data());
0237 }
0238
0239 void compute(ColSpMatrix& mat);
0240
0241 int m_initisOk;
0242 int m_analysisIsOk;
0243 int m_factorizationIsOk;
0244 mutable ComputationInfo m_info;
0245 mutable pastix_data_t *m_pastixdata;
0246 mutable int m_comm;
0247 mutable Array<int,IPARM_SIZE,1> m_iparm;
0248 mutable Array<double,DPARM_SIZE,1> m_dparm;
0249 mutable Matrix<StorageIndex,Dynamic,1> m_perm;
0250 mutable Matrix<StorageIndex,Dynamic,1> m_invp;
0251 mutable int m_size;
0252 };
0253
0254
0255
0256
0257
0258 template <class Derived>
0259 void PastixBase<Derived>::init()
0260 {
0261 m_size = 0;
0262 m_iparm.setZero(IPARM_SIZE);
0263 m_dparm.setZero(DPARM_SIZE);
0264
0265 m_iparm(IPARM_MODIFY_PARAMETER) = API_NO;
0266 pastix(&m_pastixdata, MPI_COMM_WORLD,
0267 0, 0, 0, 0,
0268 0, 0, 0, 1, m_iparm.data(), m_dparm.data());
0269
0270 m_iparm[IPARM_MATRIX_VERIFICATION] = API_NO;
0271 m_iparm[IPARM_VERBOSE] = API_VERBOSE_NOT;
0272 m_iparm[IPARM_ORDERING] = API_ORDER_SCOTCH;
0273 m_iparm[IPARM_INCOMPLETE] = API_NO;
0274 m_iparm[IPARM_OOC_LIMIT] = 2000;
0275 m_iparm[IPARM_RHS_MAKING] = API_RHS_B;
0276 m_iparm(IPARM_MATRIX_VERIFICATION) = API_NO;
0277
0278 m_iparm(IPARM_START_TASK) = API_TASK_INIT;
0279 m_iparm(IPARM_END_TASK) = API_TASK_INIT;
0280 internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, 0, 0, 0, (Scalar*)0,
0281 0, 0, 0, 0, m_iparm.data(), m_dparm.data());
0282
0283
0284 if(m_iparm(IPARM_ERROR_NUMBER)) {
0285 m_info = InvalidInput;
0286 m_initisOk = false;
0287 }
0288 else {
0289 m_info = Success;
0290 m_initisOk = true;
0291 }
0292 }
0293
0294 template <class Derived>
0295 void PastixBase<Derived>::compute(ColSpMatrix& mat)
0296 {
0297 eigen_assert(mat.rows() == mat.cols() && "The input matrix should be squared");
0298
0299 analyzePattern(mat);
0300 factorize(mat);
0301
0302 m_iparm(IPARM_MATRIX_VERIFICATION) = API_NO;
0303 }
0304
0305
0306 template <class Derived>
0307 void PastixBase<Derived>::analyzePattern(ColSpMatrix& mat)
0308 {
0309 eigen_assert(m_initisOk && "The initialization of PaSTiX failed");
0310
0311
0312 if(m_size>0)
0313 clean();
0314
0315 m_size = internal::convert_index<int>(mat.rows());
0316 m_perm.resize(m_size);
0317 m_invp.resize(m_size);
0318
0319 m_iparm(IPARM_START_TASK) = API_TASK_ORDERING;
0320 m_iparm(IPARM_END_TASK) = API_TASK_ANALYSE;
0321 internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, m_size, mat.outerIndexPtr(), mat.innerIndexPtr(),
0322 mat.valuePtr(), m_perm.data(), m_invp.data(), 0, 0, m_iparm.data(), m_dparm.data());
0323
0324
0325 if(m_iparm(IPARM_ERROR_NUMBER))
0326 {
0327 m_info = NumericalIssue;
0328 m_analysisIsOk = false;
0329 }
0330 else
0331 {
0332 m_info = Success;
0333 m_analysisIsOk = true;
0334 }
0335 }
0336
0337 template <class Derived>
0338 void PastixBase<Derived>::factorize(ColSpMatrix& mat)
0339 {
0340
0341 eigen_assert(m_analysisIsOk && "The analysis phase should be called before the factorization phase");
0342 m_iparm(IPARM_START_TASK) = API_TASK_NUMFACT;
0343 m_iparm(IPARM_END_TASK) = API_TASK_NUMFACT;
0344 m_size = internal::convert_index<int>(mat.rows());
0345
0346 internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, m_size, mat.outerIndexPtr(), mat.innerIndexPtr(),
0347 mat.valuePtr(), m_perm.data(), m_invp.data(), 0, 0, m_iparm.data(), m_dparm.data());
0348
0349
0350 if(m_iparm(IPARM_ERROR_NUMBER))
0351 {
0352 m_info = NumericalIssue;
0353 m_factorizationIsOk = false;
0354 m_isInitialized = false;
0355 }
0356 else
0357 {
0358 m_info = Success;
0359 m_factorizationIsOk = true;
0360 m_isInitialized = true;
0361 }
0362 }
0363
0364
0365 template<typename Base>
0366 template<typename Rhs,typename Dest>
0367 bool PastixBase<Base>::_solve_impl(const MatrixBase<Rhs> &b, MatrixBase<Dest> &x) const
0368 {
0369 eigen_assert(m_isInitialized && "The matrix should be factorized first");
0370 EIGEN_STATIC_ASSERT((Dest::Flags&RowMajorBit)==0,
0371 THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES);
0372 int rhs = 1;
0373
0374 x = b;
0375
0376 for (int i = 0; i < b.cols(); i++){
0377 m_iparm[IPARM_START_TASK] = API_TASK_SOLVE;
0378 m_iparm[IPARM_END_TASK] = API_TASK_REFINE;
0379
0380 internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, internal::convert_index<int>(x.rows()), 0, 0, 0,
0381 m_perm.data(), m_invp.data(), &x(0, i), rhs, m_iparm.data(), m_dparm.data());
0382 }
0383
0384
0385 m_info = m_iparm(IPARM_ERROR_NUMBER)==0 ? Success : NumericalIssue;
0386
0387 return m_iparm(IPARM_ERROR_NUMBER)==0;
0388 }
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411 template<typename _MatrixType, bool IsStrSym>
0412 class PastixLU : public PastixBase< PastixLU<_MatrixType> >
0413 {
0414 public:
0415 typedef _MatrixType MatrixType;
0416 typedef PastixBase<PastixLU<MatrixType> > Base;
0417 typedef typename Base::ColSpMatrix ColSpMatrix;
0418 typedef typename MatrixType::StorageIndex StorageIndex;
0419
0420 public:
0421 PastixLU() : Base()
0422 {
0423 init();
0424 }
0425
0426 explicit PastixLU(const MatrixType& matrix):Base()
0427 {
0428 init();
0429 compute(matrix);
0430 }
0431
0432
0433
0434
0435
0436 void compute (const MatrixType& matrix)
0437 {
0438 m_structureIsUptodate = false;
0439 ColSpMatrix temp;
0440 grabMatrix(matrix, temp);
0441 Base::compute(temp);
0442 }
0443
0444
0445
0446
0447
0448 void analyzePattern(const MatrixType& matrix)
0449 {
0450 m_structureIsUptodate = false;
0451 ColSpMatrix temp;
0452 grabMatrix(matrix, temp);
0453 Base::analyzePattern(temp);
0454 }
0455
0456
0457
0458
0459
0460
0461 void factorize(const MatrixType& matrix)
0462 {
0463 ColSpMatrix temp;
0464 grabMatrix(matrix, temp);
0465 Base::factorize(temp);
0466 }
0467 protected:
0468
0469 void init()
0470 {
0471 m_structureIsUptodate = false;
0472 m_iparm(IPARM_SYM) = API_SYM_NO;
0473 m_iparm(IPARM_FACTORIZATION) = API_FACT_LU;
0474 }
0475
0476 void grabMatrix(const MatrixType& matrix, ColSpMatrix& out)
0477 {
0478 if(IsStrSym)
0479 out = matrix;
0480 else
0481 {
0482 if(!m_structureIsUptodate)
0483 {
0484
0485 m_transposedStructure = matrix.transpose();
0486
0487
0488 for (Index j=0; j<m_transposedStructure.outerSize(); ++j)
0489 for(typename ColSpMatrix::InnerIterator it(m_transposedStructure, j); it; ++it)
0490 it.valueRef() = 0.0;
0491
0492 m_structureIsUptodate = true;
0493 }
0494
0495 out = m_transposedStructure + matrix;
0496 }
0497 internal::c_to_fortran_numbering(out);
0498 }
0499
0500 using Base::m_iparm;
0501 using Base::m_dparm;
0502
0503 ColSpMatrix m_transposedStructure;
0504 bool m_structureIsUptodate;
0505 };
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523 template<typename _MatrixType, int _UpLo>
0524 class PastixLLT : public PastixBase< PastixLLT<_MatrixType, _UpLo> >
0525 {
0526 public:
0527 typedef _MatrixType MatrixType;
0528 typedef PastixBase<PastixLLT<MatrixType, _UpLo> > Base;
0529 typedef typename Base::ColSpMatrix ColSpMatrix;
0530
0531 public:
0532 enum { UpLo = _UpLo };
0533 PastixLLT() : Base()
0534 {
0535 init();
0536 }
0537
0538 explicit PastixLLT(const MatrixType& matrix):Base()
0539 {
0540 init();
0541 compute(matrix);
0542 }
0543
0544
0545
0546
0547 void compute (const MatrixType& matrix)
0548 {
0549 ColSpMatrix temp;
0550 grabMatrix(matrix, temp);
0551 Base::compute(temp);
0552 }
0553
0554
0555
0556
0557
0558 void analyzePattern(const MatrixType& matrix)
0559 {
0560 ColSpMatrix temp;
0561 grabMatrix(matrix, temp);
0562 Base::analyzePattern(temp);
0563 }
0564
0565
0566
0567 void factorize(const MatrixType& matrix)
0568 {
0569 ColSpMatrix temp;
0570 grabMatrix(matrix, temp);
0571 Base::factorize(temp);
0572 }
0573 protected:
0574 using Base::m_iparm;
0575
0576 void init()
0577 {
0578 m_iparm(IPARM_SYM) = API_SYM_YES;
0579 m_iparm(IPARM_FACTORIZATION) = API_FACT_LLT;
0580 }
0581
0582 void grabMatrix(const MatrixType& matrix, ColSpMatrix& out)
0583 {
0584 out.resize(matrix.rows(), matrix.cols());
0585
0586 out.template selfadjointView<Lower>() = matrix.template selfadjointView<UpLo>();
0587 internal::c_to_fortran_numbering(out);
0588 }
0589 };
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607 template<typename _MatrixType, int _UpLo>
0608 class PastixLDLT : public PastixBase< PastixLDLT<_MatrixType, _UpLo> >
0609 {
0610 public:
0611 typedef _MatrixType MatrixType;
0612 typedef PastixBase<PastixLDLT<MatrixType, _UpLo> > Base;
0613 typedef typename Base::ColSpMatrix ColSpMatrix;
0614
0615 public:
0616 enum { UpLo = _UpLo };
0617 PastixLDLT():Base()
0618 {
0619 init();
0620 }
0621
0622 explicit PastixLDLT(const MatrixType& matrix):Base()
0623 {
0624 init();
0625 compute(matrix);
0626 }
0627
0628
0629
0630
0631 void compute (const MatrixType& matrix)
0632 {
0633 ColSpMatrix temp;
0634 grabMatrix(matrix, temp);
0635 Base::compute(temp);
0636 }
0637
0638
0639
0640
0641
0642 void analyzePattern(const MatrixType& matrix)
0643 {
0644 ColSpMatrix temp;
0645 grabMatrix(matrix, temp);
0646 Base::analyzePattern(temp);
0647 }
0648
0649
0650
0651 void factorize(const MatrixType& matrix)
0652 {
0653 ColSpMatrix temp;
0654 grabMatrix(matrix, temp);
0655 Base::factorize(temp);
0656 }
0657
0658 protected:
0659 using Base::m_iparm;
0660
0661 void init()
0662 {
0663 m_iparm(IPARM_SYM) = API_SYM_YES;
0664 m_iparm(IPARM_FACTORIZATION) = API_FACT_LDLT;
0665 }
0666
0667 void grabMatrix(const MatrixType& matrix, ColSpMatrix& out)
0668 {
0669
0670 out.resize(matrix.rows(), matrix.cols());
0671 out.template selfadjointView<Lower>() = matrix.template selfadjointView<UpLo>();
0672 internal::c_to_fortran_numbering(out);
0673 }
0674 };
0675
0676 }
0677
0678 #endif