00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef SELDON_FILE_CHOLMOD_CXX
00021
00022 #include "Cholmod.hxx"
00023
00024 namespace Seldon
00025 {
00026
00027 MatrixCholmod::MatrixCholmod()
00028 {
00029
00030 cholmod_start(¶m_chol);
00031 Lsparse = NULL;
00032 n = 0;
00033 }
00034
00035
00036
00037 MatrixCholmod::~MatrixCholmod()
00038 {
00039 if (n > 0)
00040 {
00041 Clear();
00042 cholmod_finish(¶m_chol);
00043 }
00044 }
00045
00046
00047 void MatrixCholmod::HideMessages()
00048 {
00049 }
00050
00051
00052 void MatrixCholmod::ShowMessages()
00053 {
00054 }
00055
00056
00057 void MatrixCholmod::ShowFullHistory()
00058 {
00059 }
00060
00061
00062 void MatrixCholmod::Clear()
00063 {
00064 if (n > 0)
00065 {
00066 n = 0;
00067 cholmod_free_factor(&L, ¶m_chol);
00068 if (Lsparse != NULL)
00069 cholmod_free_sparse(&Lsparse, ¶m_chol);
00070
00071 Lsparse = NULL;
00072 }
00073 }
00074
00075
00076 template<class Prop, class Storage, class Allocator>
00077 void MatrixCholmod::
00078 FactorizeMatrix(Matrix<double, Prop, Storage, Allocator> & mat,
00079 bool keep_matrix)
00080 {
00081 Clear();
00082
00083 n = mat.GetM();
00084 Matrix<double, Symmetric, RowSymSparse, MallocAlloc<double> > Acsc;
00085 Copy(mat, Acsc);
00086 if (!keep_matrix)
00087 mat.Clear();
00088
00089
00090 cholmod_sparse A;
00091
00092 A.nrow = n;
00093 A.ncol = n;
00094 A.nzmax = Acsc.GetDataSize();
00095 A.nz = NULL;
00096 A.p = Acsc.GetPtr();
00097 A.i = Acsc.GetInd();
00098 A.x = Acsc.GetData();
00099 A.z = NULL;
00100 A.stype = -1;
00101 A.xtype = CHOLMOD_REAL;
00102 A.dtype = CHOLMOD_DOUBLE;
00103 A.sorted = true;
00104 A.packed = true;
00105 L = cholmod_analyze(&A, ¶m_chol);
00106
00107
00108 cholmod_factorize(&A, L, ¶m_chol);
00109
00110 cholmod_change_factor(CHOLMOD_REAL, true, L->is_super,
00111 true, L->is_monotonic, L, ¶m_chol);
00112
00113
00114 cholmod_factor* B = cholmod_copy_factor(L, ¶m_chol);
00115 Lsparse = cholmod_factor_to_sparse(B, ¶m_chol);
00116
00117 cholmod_free_factor(&B, ¶m_chol);
00118 }
00119
00120
00122 template<class Transpose_status, class Allocator>
00123 void MatrixCholmod::Solve(const Transpose_status& TransA,
00124 Vector<double, VectFull, Allocator>& x)
00125 {
00126
00127 cholmod_dense b_rhs;
00128 b_rhs.nrow = x.GetM();
00129 b_rhs.ncol = 1;
00130 b_rhs.nzmax = b_rhs.nrow;
00131 b_rhs.d = b_rhs.nrow;
00132 b_rhs.x = x.GetData();
00133 b_rhs.z = NULL;
00134 b_rhs.xtype = CHOLMOD_REAL;
00135 b_rhs.dtype = CHOLMOD_DOUBLE;
00136
00137 cholmod_dense* x_sol, *y;
00138 if (TransA.Trans())
00139 {
00140 y = cholmod_solve(CHOLMOD_Lt, L, &b_rhs, ¶m_chol);
00141 x_sol = cholmod_solve(CHOLMOD_Pt, L, y, ¶m_chol);
00142 }
00143 else
00144 {
00145 y = cholmod_solve(CHOLMOD_P, L, &b_rhs, ¶m_chol);
00146 x_sol = cholmod_solve(CHOLMOD_L, L, y, ¶m_chol);
00147 }
00148
00149 double* data = reinterpret_cast<double*>(x_sol->x);
00150 for (int i = 0; i < x.GetM(); i++)
00151 x(i) = data[i];
00152
00153 cholmod_free_dense(&x_sol, ¶m_chol);
00154 cholmod_free_dense(&y, ¶m_chol);
00155 }
00156
00157
00159 template<class Transpose_status, class Allocator>
00160 void MatrixCholmod::Mlt(const Transpose_status& TransA,
00161 Vector<double, VectFull, Allocator>& X)
00162 {
00163 int trans = 1;
00164 if(TransA.Trans())
00165 trans = 0;
00166
00167 Vector<double, VectFull, Allocator> Y = X;
00168
00169 cholmod_dense Xchol,Ychol;
00170
00171 Xchol.nrow = X.GetM();
00172 Xchol.ncol = 1;
00173 Xchol.nzmax = Xchol.nrow;
00174 Xchol.d = Xchol.nrow;
00175 Xchol.x = X.GetData();
00176 Xchol.z = NULL;
00177 Xchol.xtype = CHOLMOD_REAL;
00178 Xchol.dtype = CHOLMOD_DOUBLE;
00179
00180 Ychol.nrow = X.GetM();
00181 Ychol.ncol = 1;
00182 Ychol.nzmax = Ychol.nrow;
00183 Ychol.d = Ychol.nrow;
00184 Ychol.x = Y.GetData();
00185 Ychol.z = NULL;
00186 Ychol.xtype = CHOLMOD_REAL;
00187 Ychol.dtype = CHOLMOD_DOUBLE;
00188
00189
00190 Matrix<double, General, RowSparse, MallocAlloc<double> > Lcsr;
00191 Lcsr.SetData(n, n, Lsparse->nzmax, reinterpret_cast<double*>(Lsparse->x),
00192 reinterpret_cast<int*>(Lsparse->p),
00193 reinterpret_cast<int*>(Lsparse->i));
00194
00195 if (TransA.Trans())
00196 {
00197
00198 cholmod_dense* x_sol;
00199 x_sol = cholmod_solve(CHOLMOD_P, L, &Xchol, ¶m_chol);
00200
00201 double* data = reinterpret_cast<double*>(x_sol->x);
00202 for (int i = 0; i < n; i++)
00203 Y(i) = data[i];
00204
00205 Seldon::Mlt(Lcsr, Y, X);
00206
00207 cholmod_free_dense(&x_sol, ¶m_chol);
00208 }
00209 else
00210 {
00211
00212 Seldon::MltAdd(1.0, SeldonTrans, Lcsr, X, 0.0, Y);
00213
00214 cholmod_dense* x_sol;
00215 x_sol = cholmod_solve(CHOLMOD_Pt, L, &Ychol, ¶m_chol);
00216
00217 double* data = reinterpret_cast<double*>(x_sol->x);
00218 for (int i = 0; i < X.GetM(); i++)
00219 X(i) = data[i];
00220
00221 cholmod_free_dense(&x_sol, ¶m_chol);
00222 }
00223
00224 Lcsr.Nullify();
00225 }
00226
00227
00228 template<class T, class Prop, class Storage, class Allocator>
00229 void GetCholesky(Matrix<T, Prop, Storage, Allocator>& A,
00230 MatrixCholmod& mat_chol, bool keep_matrix = false)
00231 {
00232 mat_chol.FactorizeMatrix(A, keep_matrix);
00233 }
00234
00235
00236 template<class T, class Allocator, class Transpose_status>
00237 void
00238 SolveCholesky(const Transpose_status& TransA,
00239 MatrixCholmod& mat_chol, Vector<T, VectFull, Allocator>& x)
00240 {
00241 mat_chol.Solve(TransA, x);
00242 }
00243
00244
00245 template<class T, class Allocator, class Transpose_status>
00246 void
00247 MltCholesky(const Transpose_status& TransA,
00248 MatrixCholmod& mat_chol, Vector<T, VectFull, Allocator>& x)
00249 {
00250 mat_chol.Mlt(TransA, x);
00251 }
00252
00253 }
00254
00255 #define SELDON_FILE_CHOLMOD_CXX
00256 #endif