Cholmod.cxx
1 // Copyright (C) 2010 Marc DuruflĂ©
2 //
3 // This file is part of the linear-algebra library Seldon,
4 // http://seldon.sourceforge.net/.
5 //
6 // Seldon is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your option)
9 // any later version.
10 //
11 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
14 // more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with Seldon. If not, see http://www.gnu.org/licenses/.
18 
19 
20 #ifndef SELDON_FILE_CHOLMOD_CXX
21 
22 #include "Cholmod.hxx"
23 
24 namespace Seldon
25 {
26 
27  MatrixCholmod::MatrixCholmod()
28  {
29  // Sets default parameters.
30  cholmod_start(&param_chol);
31  n = 0;
32  }
33 
34 
35 
36  MatrixCholmod::~MatrixCholmod()
37  {
38  if (n > 0)
39  Clear();
40 
41  cholmod_finish(&param_chol);
42  }
43 
44 
45  void MatrixCholmod::HideMessages()
46  {
47  }
48 
49 
50  void MatrixCholmod::ShowMessages()
51  {
52  }
53 
54 
55  void MatrixCholmod::ShowFullHistory()
56  {
57  }
58 
59 
60  size_t MatrixCholmod::GetMemorySize() const
61  {
62  size_t taille = sizeof(*this);
63  if (n > 0)
64  {
65  // assuming that L only contains simplicial structure (and not the supernodal one)
66  taille += size_t(L->nzmax)*(sizeof(double) + sizeof(int)) + (n+1)*sizeof(int);
67  }
68 
69  return taille;
70  }
71 
72 
73  int MatrixCholmod::GetInfoFactorization() const
74  {
75  return 0;
76  }
77 
78 
79  bool MatrixCholmod::UseInteger8() const
80  {
81  return false;
82  }
83 
84 
85  void MatrixCholmod::Clear()
86  {
87  if (n > 0)
88  {
89  n = 0;
90  cholmod_free_factor(&L, &param_chol);
91  }
92  }
93 
94 
95  template<class Prop, class Storage, class Allocator>
96  void MatrixCholmod::
97  FactorizeMatrix(Matrix<double, Prop, Storage, Allocator> & mat,
98  bool keep_matrix)
99  {
100  Clear();
101 
102  Matrix<double, Symmetric, RowSymSparse> Acsc;
103  Copy(mat, Acsc);
104  if (!keep_matrix)
105  mat.Clear();
106 
107  FactorizeCSR(Acsc);
108  }
109 
110 
111  void MatrixCholmod::
112  FactorizeCSR(Matrix<double, Symmetric, RowSymSparse> & Acsc)
113  {
114  n = Acsc.GetM();
115 
116  // Initialization of sparse matrix.
117  cholmod_sparse A;
118  Vector<int> ptrA; Acsc.FillPtrInt(ptrA);
119 
120  A.nrow = n;
121  A.ncol = n;
122  A.nzmax = Acsc.GetDataSize();
123  A.nz = NULL;
124  A.p = ptrA.GetData();
125  A.i = Acsc.GetInd();
126  A.x = Acsc.GetData();
127  A.z = NULL;
128  A.stype = -1;
129  A.xtype = CHOLMOD_REAL;
130  A.dtype = CHOLMOD_DOUBLE;
131  A.sorted = true;
132  A.packed = true;
133  L = cholmod_analyze(&A, &param_chol);
134 
135  // Cholesky factorization.
136  cholmod_factorize(&A, L, &param_chol);
137 
138  // L is converted as a simplicial factor (i.e. CSR format)
139  // in order to complete a matrix-vector product with L
140  cholmod_change_factor(CHOLMOD_REAL, true, false, true,
141  true, L, &param_chol);
142  }
143 
144 
146  template<class Allocator>
149  {
150  Solve(TransA, x.GetData(), 1);
151  }
152 
153 
154  void MatrixCholmod::Solve(const SeldonTranspose& TransA, double* x_ptr, int nrhs)
155  {
156  // Dense right hand side.
157  cholmod_dense b_rhs;
158  b_rhs.nrow = n;
159  b_rhs.ncol = nrhs;
160  b_rhs.nzmax = b_rhs.nrow;
161  b_rhs.d = b_rhs.nrow;
162  b_rhs.x = x_ptr;
163  b_rhs.z = NULL;
164  b_rhs.xtype = CHOLMOD_REAL;
165  b_rhs.dtype = CHOLMOD_DOUBLE;
166 
167  cholmod_dense* x_sol, *y;
168  if (TransA.Trans())
169  {
170  y = cholmod_solve(CHOLMOD_Lt, L, &b_rhs, &param_chol);
171  x_sol = cholmod_solve(CHOLMOD_Pt, L, y, &param_chol);
172  }
173  else
174  {
175  y = cholmod_solve(CHOLMOD_P, L, &b_rhs, &param_chol);
176  x_sol = cholmod_solve(CHOLMOD_L, L, y, &param_chol);
177  }
178 
179  double* data = reinterpret_cast<double*>(x_sol->x);
180  for (int i = 0; i < n*nrhs; i++)
181  x_ptr[i] = data[i];
182 
183  cholmod_free_dense(&x_sol, &param_chol);
184  cholmod_free_dense(&y, &param_chol);
185  }
186 
187 
189  template<class Allocator>
192  {
194 
195  cholmod_dense Xchol,Ychol;
196 
197  Xchol.nrow = X.GetM();
198  Xchol.ncol = 1;
199  Xchol.nzmax = Xchol.nrow;
200  Xchol.d = Xchol.nrow;
201  Xchol.x = X.GetData();
202  Xchol.z = NULL;
203  Xchol.xtype = CHOLMOD_REAL;
204  Xchol.dtype = CHOLMOD_DOUBLE;
205 
206  Ychol.nrow = X.GetM();
207  Ychol.ncol = 1;
208  Ychol.nzmax = Ychol.nrow;
209  Ychol.d = Ychol.nrow;
210  Ychol.x = Y.GetData();
211  Ychol.z = NULL;
212  Ychol.xtype = CHOLMOD_REAL;
213  Ychol.dtype = CHOLMOD_DOUBLE;
214 
215  Vector<long> ptrL(n+1);
216  int* pint = reinterpret_cast<int*>(L->p);
217  for (int i = 0; i <= n; i++)
218  ptrL(i) = pint[i];
219 
220  // filling Seldon structure Lcsr
222  Lcsr.SetData(n, n, L->nzmax, reinterpret_cast<double*>(L->x),
223  ptrL.GetData(),
224  reinterpret_cast<int*>(L->i));
225 
226  if (TransA.Trans())
227  {
228  // Computing L^T P^T x.
229  cholmod_dense* x_sol;
230  x_sol = cholmod_solve(CHOLMOD_P, L, &Xchol, &param_chol);
231 
232  double* data = reinterpret_cast<double*>(x_sol->x);
233  for (int i = 0; i < n; i++)
234  Y(i) = data[i];
235 
236  Seldon::Mlt(Lcsr, Y, X);
237 
238  cholmod_free_dense(&x_sol, &param_chol);
239  }
240  else
241  {
242  // Computing P L x.
243  Seldon::MltAdd(1.0, SeldonTrans, Lcsr, X, 0.0, Y);
244 
245  cholmod_dense* x_sol;
246  x_sol = cholmod_solve(CHOLMOD_Pt, L, &Ychol, &param_chol);
247 
248  double* data = reinterpret_cast<double*>(x_sol->x);
249  for (int i = 0; i < X.GetM(); i++)
250  X(i) = data[i];
251 
252  cholmod_free_dense(&x_sol, &param_chol);
253  }
254 
255  Lcsr.Nullify();
256  }
257 
258 
259  template<class T, class Prop, class Storage, class Allocator>
260  void GetCholesky(Matrix<T, Prop, Storage, Allocator>& A,
261  MatrixCholmod& mat_chol, bool keep_matrix)
262  {
263  mat_chol.FactorizeMatrix(A, keep_matrix);
264  }
265 
266 
267  template<class T, class Allocator>
268  void
269  SolveCholesky(const SeldonTranspose& TransA,
270  MatrixCholmod& mat_chol, Vector<T, VectFull, Allocator>& x)
271  {
272  mat_chol.Solve(TransA, x);
273  }
274 
275 
276  template<class T, class Allocator>
277  void
278  MltCholesky(const SeldonTranspose& TransA,
279  MatrixCholmod& mat_chol, Vector<T, VectFull, Allocator>& x)
280  {
281  mat_chol.Mlt(TransA, x);
282  }
283 
284 }
285 
286 #define SELDON_FILE_CHOLMOD_CXX
287 #endif
Seldon::SeldonTranspose
Definition: MatrixFlag.hxx:32
Seldon::MatrixCholmod::Solve
void Solve(const SeldonTranspose &TransA, Vector< double, VectFull, Allocator > &x)
Solves L x = b or L^T x = b.
Definition: Cholmod.cxx:147
Seldon::Vector
Definition: SeldonHeader.hxx:207
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::MatrixCholmod
Object containing Cholesky factorization.
Definition: Cholmod.hxx:32
Seldon::MatrixCholmod::Mlt
void Mlt(const SeldonTranspose &TransA, Vector< double, VectFull, Allocator > &x)
Performs the matrix vector product y = L X or y = L^T X.
Definition: Cholmod.cxx:190
Seldon
Seldon namespace.
Definition: Array.cxx:24