Warning: this documentation for the development version is under construction.
00001 // Copyright (C) 2010 Marc DuruflĂ© 00002 // 00003 // This file is part of the linear-algebra library Seldon, 00004 // http://seldon.sourceforge.net/. 00005 // 00006 // Seldon is free software; you can redistribute it and/or modify it under the 00007 // terms of the GNU Lesser General Public License as published by the Free 00008 // Software Foundation; either version 2.1 of the License, or (at your option) 00009 // any later version. 00010 // 00011 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY 00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00013 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00014 // more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public License 00017 // along with Seldon. If not, see http://www.gnu.org/licenses/. 00018 00019 00020 #ifndef SELDON_FILE_CHOLMOD_CXX 00021 00022 #include "Cholmod.hxx" 00023 00024 namespace Seldon 00025 { 00026 00027 MatrixCholmod::MatrixCholmod() 00028 { 00029 // Sets default parameters. 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 // Initialization of sparse matrix. 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 // Cholesky factorization. 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 // We convert the factorization to column sparse row format. 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 // Dense right hand side. 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 // Conversion from Lsparse to Seldon structure. 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 // Computing L^T P^T x. 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 // Computing P L x. 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