00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef EIGEN_UMFPACKSUPPORT_H
00026 #define EIGEN_UMFPACKSUPPORT_H
00027
00028
00029
00030
00031
00032 inline void umfpack_free_numeric(void **Numeric, double)
00033 { umfpack_di_free_numeric(Numeric); }
00034
00035 inline void umfpack_free_numeric(void **Numeric, std::complex<double>)
00036 { umfpack_zi_free_numeric(Numeric); }
00037
00038 inline void umfpack_free_symbolic(void **Symbolic, double)
00039 { umfpack_di_free_symbolic(Symbolic); }
00040
00041 inline void umfpack_free_symbolic(void **Symbolic, std::complex<double>)
00042 { umfpack_zi_free_symbolic(Symbolic); }
00043
00044 inline int umfpack_symbolic(int n_row,int n_col,
00045 const int Ap[], const int Ai[], const double Ax[], void **Symbolic,
00046 const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
00047 {
00048 return umfpack_di_symbolic(n_row,n_col,Ap,Ai,Ax,Symbolic,Control,Info);
00049 }
00050
00051 inline int umfpack_symbolic(int n_row,int n_col,
00052 const int Ap[], const int Ai[], const std::complex<double> Ax[], void **Symbolic,
00053 const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO])
00054 {
00055 return umfpack_zi_symbolic(n_row,n_col,Ap,Ai,&Ax[0].real(),0,Symbolic,Control,Info);
00056 }
00057
00058 inline int umfpack_numeric( const int Ap[], const int Ai[], const double Ax[],
00059 void *Symbolic, void **Numeric,
00060 const double Control[UMFPACK_CONTROL],double Info [UMFPACK_INFO])
00061 {
00062 return umfpack_di_numeric(Ap,Ai,Ax,Symbolic,Numeric,Control,Info);
00063 }
00064
00065 inline int umfpack_numeric( const int Ap[], const int Ai[], const std::complex<double> Ax[],
00066 void *Symbolic, void **Numeric,
00067 const double Control[UMFPACK_CONTROL],double Info [UMFPACK_INFO])
00068 {
00069 return umfpack_zi_numeric(Ap,Ai,&Ax[0].real(),0,Symbolic,Numeric,Control,Info);
00070 }
00071
00072 inline int umfpack_solve( int sys, const int Ap[], const int Ai[], const double Ax[],
00073 double X[], const double B[], void *Numeric,
00074 const double Control[UMFPACK_CONTROL], double Info[UMFPACK_INFO])
00075 {
00076 return umfpack_di_solve(sys,Ap,Ai,Ax,X,B,Numeric,Control,Info);
00077 }
00078
00079 inline int umfpack_solve( int sys, const int Ap[], const int Ai[], const std::complex<double> Ax[],
00080 std::complex<double> X[], const std::complex<double> B[], void *Numeric,
00081 const double Control[UMFPACK_CONTROL], double Info[UMFPACK_INFO])
00082 {
00083 return umfpack_zi_solve(sys,Ap,Ai,&Ax[0].real(),0,&X[0].real(),0,&B[0].real(),0,Numeric,Control,Info);
00084 }
00085
00086 inline int umfpack_get_lunz(int *lnz, int *unz, int *n_row, int *n_col, int *nz_udiag, void *Numeric, double)
00087 {
00088 return umfpack_di_get_lunz(lnz,unz,n_row,n_col,nz_udiag,Numeric);
00089 }
00090
00091 inline int umfpack_get_lunz(int *lnz, int *unz, int *n_row, int *n_col, int *nz_udiag, void *Numeric, std::complex<double>)
00092 {
00093 return umfpack_zi_get_lunz(lnz,unz,n_row,n_col,nz_udiag,Numeric);
00094 }
00095
00096 inline int umfpack_get_numeric(int Lp[], int Lj[], double Lx[], int Up[], int Ui[], double Ux[],
00097 int P[], int Q[], double Dx[], int *do_recip, double Rs[], void *Numeric)
00098 {
00099 return umfpack_di_get_numeric(Lp,Lj,Lx,Up,Ui,Ux,P,Q,Dx,do_recip,Rs,Numeric);
00100 }
00101
00102 inline int umfpack_get_numeric(int Lp[], int Lj[], std::complex<double> Lx[], int Up[], int Ui[], std::complex<double> Ux[],
00103 int P[], int Q[], std::complex<double> Dx[], int *do_recip, double Rs[], void *Numeric)
00104 {
00105 return umfpack_zi_get_numeric(Lp,Lj,Lx?&Lx[0].real():0,0,Up,Ui,Ux?&Ux[0].real():0,0,P,Q,
00106 Dx?&Dx[0].real():0,0,do_recip,Rs,Numeric);
00107 }
00108
00109 inline int umfpack_get_determinant(double *Mx, double *Ex, void *NumericHandle, double User_Info [UMFPACK_INFO])
00110 {
00111 return umfpack_di_get_determinant(Mx,Ex,NumericHandle,User_Info);
00112 }
00113
00114 inline int umfpack_get_determinant(std::complex<double> *Mx, double *Ex, void *NumericHandle, double User_Info [UMFPACK_INFO])
00115 {
00116 return umfpack_zi_get_determinant(&Mx->real(),0,Ex,NumericHandle,User_Info);
00117 }
00118
00119
00120 template<typename MatrixType>
00121 class SparseLU<MatrixType,UmfPack> : public SparseLU<MatrixType>
00122 {
00123 protected:
00124 typedef SparseLU<MatrixType> Base;
00125 typedef typename Base::Scalar Scalar;
00126 typedef typename Base::RealScalar RealScalar;
00127 typedef Matrix<Scalar,Dynamic,1> Vector;
00128 typedef Matrix<int, 1, MatrixType::ColsAtCompileTime> IntRowVectorType;
00129 typedef Matrix<int, MatrixType::RowsAtCompileTime, 1> IntColVectorType;
00130 typedef SparseMatrix<Scalar,LowerTriangular|UnitDiagBit> LMatrixType;
00131 typedef SparseMatrix<Scalar,UpperTriangular> UMatrixType;
00132 using Base::m_flags;
00133 using Base::m_status;
00134
00135 public:
00136
00137 SparseLU(int flags = NaturalOrdering)
00138 : Base(flags), m_numeric(0)
00139 {
00140 }
00141
00142 SparseLU(const MatrixType& matrix, int flags = NaturalOrdering)
00143 : Base(flags), m_numeric(0)
00144 {
00145 compute(matrix);
00146 }
00147
00148 ~SparseLU()
00149 {
00150 if (m_numeric)
00151 umfpack_free_numeric(&m_numeric,Scalar());
00152 }
00153
00154 inline const LMatrixType& matrixL() const
00155 {
00156 if (m_extractedDataAreDirty) extractData();
00157 return m_l;
00158 }
00159
00160 inline const UMatrixType& matrixU() const
00161 {
00162 if (m_extractedDataAreDirty) extractData();
00163 return m_u;
00164 }
00165
00166 inline const IntColVectorType& permutationP() const
00167 {
00168 if (m_extractedDataAreDirty) extractData();
00169 return m_p;
00170 }
00171
00172 inline const IntRowVectorType& permutationQ() const
00173 {
00174 if (m_extractedDataAreDirty) extractData();
00175 return m_q;
00176 }
00177
00178 Scalar determinant() const;
00179
00180 template<typename BDerived, typename XDerived>
00181 bool solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived>* x) const;
00182
00183 void compute(const MatrixType& matrix);
00184
00185 protected:
00186
00187 void extractData() const;
00188
00189 protected:
00190
00191 void* m_numeric;
00192 const MatrixType* m_matrixRef;
00193 mutable LMatrixType m_l;
00194 mutable UMatrixType m_u;
00195 mutable IntColVectorType m_p;
00196 mutable IntRowVectorType m_q;
00197 mutable bool m_extractedDataAreDirty;
00198 };
00199
00200 template<typename MatrixType>
00201 void SparseLU<MatrixType,UmfPack>::compute(const MatrixType& a)
00202 {
00203 const int rows = a.rows();
00204 const int cols = a.cols();
00205 ei_assert((MatrixType::Flags&RowMajorBit)==0 && "Row major matrices are not supported yet");
00206
00207 m_matrixRef = &a;
00208
00209 if (m_numeric)
00210 umfpack_free_numeric(&m_numeric,Scalar());
00211
00212 void* symbolic;
00213 int errorCode = 0;
00214 errorCode = umfpack_symbolic(rows, cols, a._outerIndexPtr(), a._innerIndexPtr(), a._valuePtr(),
00215 &symbolic, 0, 0);
00216 if (errorCode==0)
00217 errorCode = umfpack_numeric(a._outerIndexPtr(), a._innerIndexPtr(), a._valuePtr(),
00218 symbolic, &m_numeric, 0, 0);
00219
00220 umfpack_free_symbolic(&symbolic,Scalar());
00221
00222 m_extractedDataAreDirty = true;
00223
00224 Base::m_succeeded = (errorCode==0);
00225 }
00226
00227 template<typename MatrixType>
00228 void SparseLU<MatrixType,UmfPack>::extractData() const
00229 {
00230 if (m_extractedDataAreDirty)
00231 {
00232
00233 int lnz, unz, rows, cols, nz_udiag;
00234 umfpack_get_lunz(&lnz, &unz, &rows, &cols, &nz_udiag, m_numeric, Scalar());
00235
00236
00237 m_l.resize(rows,std::min(rows,cols));
00238 m_l.resizeNonZeros(lnz);
00239
00240 m_u.resize(std::min(rows,cols),cols);
00241 m_u.resizeNonZeros(unz);
00242
00243 m_p.resize(rows);
00244 m_q.resize(cols);
00245
00246
00247 umfpack_get_numeric(m_l._outerIndexPtr(), m_l._innerIndexPtr(), m_l._valuePtr(),
00248 m_u._outerIndexPtr(), m_u._innerIndexPtr(), m_u._valuePtr(),
00249 m_p.data(), m_q.data(), 0, 0, 0, m_numeric);
00250
00251 m_extractedDataAreDirty = false;
00252 }
00253 }
00254
00255 template<typename MatrixType>
00256 typename SparseLU<MatrixType,UmfPack>::Scalar SparseLU<MatrixType,UmfPack>::determinant() const
00257 {
00258 Scalar det;
00259 umfpack_get_determinant(&det, 0, m_numeric, 0);
00260 return det;
00261 }
00262
00263 template<typename MatrixType>
00264 template<typename BDerived,typename XDerived>
00265 bool SparseLU<MatrixType,UmfPack>::solve(const MatrixBase<BDerived> &b, MatrixBase<XDerived> *x) const
00266 {
00267
00268 const int rhsCols = b.cols();
00269
00270 ei_assert((BDerived::Flags&RowMajorBit)==0 && "UmfPack backend does not support non col-major rhs yet");
00271 ei_assert((XDerived::Flags&RowMajorBit)==0 && "UmfPack backend does not support non col-major result yet");
00272
00273 int errorCode;
00274 for (int j=0; j<rhsCols; ++j)
00275 {
00276 errorCode = umfpack_solve(UMFPACK_A,
00277 m_matrixRef->_outerIndexPtr(), m_matrixRef->_innerIndexPtr(), m_matrixRef->_valuePtr(),
00278 &x->col(j).coeffRef(0), &b.const_cast_derived().col(j).coeffRef(0), m_numeric, 0, 0);
00279 if (errorCode!=0)
00280 return false;
00281 }
00282
00283
00284
00285
00286 return true;
00287 }
00288
00289 #endif // EIGEN_UMFPACKSUPPORT_H