Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_spsolve.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Cholesky/cholmod_spsolve ============================================= */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Cholesky Module. Copyright (C) 2005-2006, Timothy A. Davis
7  * The CHOLMOD/Cholesky Module is licensed under Version 2.1 of the GNU
8  * Lesser General Public License. See lesser.txt for a text of the license.
9  * CHOLMOD is also available under other licenses; contact authors for details.
10  * http://www.cise.ufl.edu/research/sparse
11  * -------------------------------------------------------------------------- */
12 
13 /* Given an LL' or LDL' factorization of A, solve one of the following systems:
14  *
15  * Ax=b 0: CHOLMOD_A also applies the permutation L->Perm
16  * LDL'x=b 1: CHOLMOD_LDLt does not apply L->Perm
17  * LDx=b 2: CHOLMOD_LD
18  * DL'x=b 3: CHOLMOD_DLt
19  * Lx=b 4: CHOLMOD_L
20  * L'x=b 5: CHOLMOD_Lt
21  * Dx=b 6: CHOLMOD_D
22  * x=Pb 7: CHOLMOD_P apply a permutation (P is L->Perm)
23  * x=P'b 8: CHOLMOD_Pt apply an inverse permutation
24  *
25  * where b and x are sparse. If L and b are real, then x is real. Otherwise,
26  * x is complex or zomplex, depending on the Common->prefer_zomplex parameter.
27  * All xtypes of x and b are supported (real, complex, and zomplex).
28  */
29 
30 #ifndef NCHOLESKY
31 
34 
35 /* ========================================================================== */
36 /* === EXPAND_AS_NEEDED ===================================================== */
37 /* ========================================================================== */
38 
39 /* Double the size of the sparse matrix X, if we have run out of space. */
40 
41 #define EXPAND_AS_NEEDED \
42 if (xnz >= nzmax) \
43 { \
44  nzmax *= 2 ; \
45  CHOLMOD(reallocate_sparse) (nzmax, X, Common) ; \
46  if (Common->status < CHOLMOD_OK) \
47  { \
48  CHOLMOD(free_sparse) (&X, Common) ; \
49  CHOLMOD(free_dense) (&X4, Common) ; \
50  CHOLMOD(free_dense) (&B4, Common) ; \
51  return (NULL) ; \
52  } \
53  Xi = X->i ; \
54  Xx = X->x ; \
55  Xz = X->z ; \
56 }
57 
58 
59 /* ========================================================================== */
60 /* === cholmod_spolve ======================================================= */
61 /* ========================================================================== */
62 
63 cholmod_sparse *CHOLMOD(spsolve) /* returns the sparse solution X */
64 (
65  /* ---- input ---- */
66  int sys, /* system to solve */
67  cholmod_factor *L, /* factorization to use */
68  cholmod_sparse *B, /* right-hand-side */
69  /* --------------- */
70  cholmod_common *Common
71 )
72 {
73  double x, z ;
74  cholmod_dense *X4, *B4 ;
75  cholmod_sparse *X ;
76  double *Bx, *Bz, *Xx, *Xz, *B4x, *B4z, *X4x, *X4z ;
77  Int *Bi, *Bp, *Xp, *Xi, *Bnz ;
78  Int n, nrhs, q, p, i, j, j1, j2, packed, block, pend, jn, xtype ;
79  size_t xnz, nzmax ;
80 
81  /* ---------------------------------------------------------------------- */
82  /* check inputs */
83  /* ---------------------------------------------------------------------- */
84 
86  RETURN_IF_NULL (L, NULL) ;
87  RETURN_IF_NULL (B, NULL) ;
90  if (L->n != B->nrow)
91  {
92  ERROR (CHOLMOD_INVALID, "dimensions of L and B do not match") ;
93  return (NULL) ;
94  }
95  if (B->stype)
96  {
97  ERROR (CHOLMOD_INVALID, "B cannot be stored in symmetric mode") ;
98  return (NULL) ;
99  }
100  Common->status = CHOLMOD_OK ;
101 
102  /* ---------------------------------------------------------------------- */
103  /* allocate workspace B4 and initial result X */
104  /* ---------------------------------------------------------------------- */
105 
106  n = L->n ;
107  nrhs = B->ncol ;
108 
109  /* X is real if both L and B are real, complex/zomplex otherwise */
110  xtype = (L->xtype == CHOLMOD_REAL && B->xtype == CHOLMOD_REAL) ?
111  CHOLMOD_REAL :
112  (Common->prefer_zomplex ? CHOLMOD_ZOMPLEX : CHOLMOD_COMPLEX) ;
113 
114  /* solve up to 4 columns at a time */
115  block = MIN (nrhs, 4) ;
116 
117  /* initial size of X is at most 4*n */
118  nzmax = n*block ;
119 
120  X = CHOLMOD(spzeros) (n, nrhs, nzmax, xtype, Common) ;
121  B4 = CHOLMOD(zeros) (n, block, B->xtype, Common) ;
122  if (Common->status < CHOLMOD_OK)
123  {
124  CHOLMOD(free_sparse) (&X, Common) ;
125  CHOLMOD(free_dense) (&B4, Common) ;
126  return (NULL) ;
127  }
128 
129  Bp = B->p ;
130  Bi = B->i ;
131  Bx = B->x ;
132  Bz = B->z ;
133  Bnz = B->nz ;
134  packed = B->packed ;
135 
136  Xp = X->p ;
137  Xi = X->i ;
138  Xx = X->x ;
139  Xz = X->z ;
140 
141  xnz = 0 ;
142 
143  B4x = B4->x ;
144  B4z = B4->z ;
145 
146  /* ---------------------------------------------------------------------- */
147  /* solve in chunks of 4 columns at a time */
148  /* ---------------------------------------------------------------------- */
149 
150  for (j1 = 0 ; j1 < nrhs ; j1 += block)
151  {
152 
153  /* ------------------------------------------------------------------ */
154  /* adjust the number of columns of B4 */
155  /* ------------------------------------------------------------------ */
156 
157  j2 = MIN (nrhs, j1 + block) ;
158  B4->ncol = j2 - j1 ;
159 
160  /* ------------------------------------------------------------------ */
161  /* scatter B(j1:j2-1) into B4 */
162  /* ------------------------------------------------------------------ */
163 
164  for (j = j1 ; j < j2 ; j++)
165  {
166  p = Bp [j] ;
167  pend = (packed) ? (Bp [j+1]) : (p + Bnz [j]) ;
168  jn = (j-j1)*n ;
169 
170  switch (B->xtype)
171  {
172 
173  case CHOLMOD_REAL:
174  for ( ; p < pend ; p++)
175  {
176  B4x [Bi [p] + jn] = Bx [p] ;
177  }
178  break ;
179 
180  case CHOLMOD_COMPLEX:
181  for ( ; p < pend ; p++)
182  {
183  q = Bi [p] + jn ;
184  B4x [2*q ] = Bx [2*p ] ;
185  B4x [2*q+1] = Bx [2*p+1] ;
186  }
187  break ;
188 
189  case CHOLMOD_ZOMPLEX:
190  for ( ; p < pend ; p++)
191  {
192  q = Bi [p] + jn ;
193  B4x [q] = Bx [p] ;
194  B4z [q] = Bz [p] ;
195  }
196  break ;
197  }
198  }
199 
200  /* ------------------------------------------------------------------ */
201  /* solve the system (X4 = A\B4 or other system) */
202  /* ------------------------------------------------------------------ */
203 
204  X4 = CHOLMOD(solve) (sys, L, B4, Common) ;
205  if (Common->status < CHOLMOD_OK)
206  {
207  CHOLMOD(free_sparse) (&X, Common) ;
208  CHOLMOD(free_dense) (&B4, Common) ;
209  CHOLMOD(free_dense) (&X4, Common) ;
210  return (NULL) ;
211  }
212  ASSERT (X4->xtype == xtype) ;
213  X4x = X4->x ;
214  X4z = X4->z ;
215 
216  /* ------------------------------------------------------------------ */
217  /* append the solution onto X */
218  /* ------------------------------------------------------------------ */
219 
220  for (j = j1 ; j < j2 ; j++)
221  {
222  Xp [j] = xnz ;
223  jn = (j-j1)*n ;
224  if ( xnz + n <= nzmax)
225  {
226 
227  /* ---------------------------------------------------------- */
228  /* X is guaranteed to be large enough */
229  /* ---------------------------------------------------------- */
230 
231  switch (xtype)
232  {
233 
234  case CHOLMOD_REAL:
235  for (i = 0 ; i < n ; i++)
236  {
237  x = X4x [i + jn] ;
238  if (IS_NONZERO (x))
239  {
240  Xi [xnz] = i ;
241  Xx [xnz] = x ;
242  xnz++ ;
243  }
244  }
245  break ;
246 
247  case CHOLMOD_COMPLEX:
248  for (i = 0 ; i < n ; i++)
249  {
250  x = X4x [2*(i + jn) ] ;
251  z = X4x [2*(i + jn)+1] ;
252  if (IS_NONZERO (x) || IS_NONZERO (z))
253  {
254  Xi [xnz] = i ;
255  Xx [2*xnz ] = x ;
256  Xx [2*xnz+1] = z ;
257  xnz++ ;
258  }
259  }
260  break ;
261 
262  case CHOLMOD_ZOMPLEX:
263  for (i = 0 ; i < n ; i++)
264  {
265  x = X4x [i + jn] ;
266  z = X4z [i + jn] ;
267  if (IS_NONZERO (x) || IS_NONZERO (z))
268  {
269  Xi [xnz] = i ;
270  Xx [xnz] = x ;
271  Xz [xnz] = z ;
272  xnz++ ;
273  }
274  }
275  break ;
276  }
277 
278  }
279  else
280  {
281 
282  /* ---------------------------------------------------------- */
283  /* X may need to increase in size */
284  /* ---------------------------------------------------------- */
285 
286  switch (xtype)
287  {
288 
289  case CHOLMOD_REAL:
290  for (i = 0 ; i < n ; i++)
291  {
292  x = X4x [i + jn] ;
293  if (IS_NONZERO (x))
294  {
296  Xi [xnz] = i ;
297  Xx [xnz] = x ;
298  xnz++ ;
299  }
300  }
301  break ;
302 
303  case CHOLMOD_COMPLEX:
304  for (i = 0 ; i < n ; i++)
305  {
306  x = X4x [2*(i + jn) ] ;
307  z = X4x [2*(i + jn)+1] ;
308  if (IS_NONZERO (x) || IS_NONZERO (z))
309  {
311  Xi [xnz] = i ;
312  Xx [2*xnz ] = x ;
313  Xx [2*xnz+1] = z ;
314  xnz++ ;
315  }
316  }
317  break ;
318 
319  case CHOLMOD_ZOMPLEX:
320  for (i = 0 ; i < n ; i++)
321  {
322  x = X4x [i + jn] ;
323  z = X4z [i + jn] ;
324  if (IS_NONZERO (x) || IS_NONZERO (z))
325  {
327  Xi [xnz] = i ;
328  Xx [xnz] = x ;
329  Xz [xnz] = z ;
330  xnz++ ;
331  }
332  }
333  break ;
334  }
335 
336  }
337  }
338  CHOLMOD(free_dense) (&X4, Common) ;
339 
340  /* ------------------------------------------------------------------ */
341  /* clear B4 for next iteration */
342  /* ------------------------------------------------------------------ */
343 
344  if (j2 < nrhs)
345  {
346 
347  for (j = j1 ; j < j2 ; j++)
348  {
349  p = Bp [j] ;
350  pend = (packed) ? (Bp [j+1]) : (p + Bnz [j]) ;
351  jn = (j-j1)*n ;
352 
353  switch (B->xtype)
354  {
355 
356  case CHOLMOD_REAL:
357  for ( ; p < pend ; p++)
358  {
359  B4x [Bi [p] + jn] = 0 ;
360  }
361  break ;
362 
363  case CHOLMOD_COMPLEX:
364  for ( ; p < pend ; p++)
365  {
366  q = Bi [p] + jn ;
367  B4x [2*q ] = 0 ;
368  B4x [2*q+1] = 0 ;
369  }
370  break ;
371 
372  case CHOLMOD_ZOMPLEX:
373  for ( ; p < pend ; p++)
374  {
375  q = Bi [p] + jn ;
376  B4x [q] = 0 ;
377  B4z [q] = 0 ;
378  }
379  break ;
380  }
381  }
382  }
383  }
384 
385  Xp [nrhs] = xnz ;
386 
387  /* ---------------------------------------------------------------------- */
388  /* reduce X in size, free workspace, and return result */
389  /* ---------------------------------------------------------------------- */
390 
391  ASSERT (xnz <= X->nzmax) ;
392  CHOLMOD(reallocate_sparse) (xnz, X, Common) ;
393  ASSERT (Common->status == CHOLMOD_OK) ;
394  CHOLMOD(free_dense) (&B4, Common) ;
395  return (X) ;
396 }
397 #endif
#define Int
#define CHOLMOD_COMPLEX
cholmod_sparse * CHOLMOD(spsolve)
int CHOLMOD() reallocate_sparse(size_t nznew, cholmod_sparse *A, cholmod_common *Common)
#define RETURN_IF_NULL_COMMON(result)
#define IS_NONZERO(x)
int CHOLMOD() free_sparse(cholmod_sparse **AHandle, cholmod_common *Common)
#define EXPAND_AS_NEEDED
#define CHOLMOD_REAL
#define NULL
cholmod_dense *CHOLMOD() zeros(size_t nrow, size_t ncol, int xtype, cholmod_common *Common)
#define ASSERT(expression)
cholmod_sparse *CHOLMOD() spzeros(size_t nrow, size_t ncol, size_t nzmax, int xtype, cholmod_common *Common)
int CHOLMOD() free_dense(cholmod_dense **XHandle, cholmod_common *Common)
#define CHOLMOD_INVALID
#define CHOLMOD_OK
cholmod_dense *CHOLMOD() solve(int sys, cholmod_factor *L, cholmod_dense *B, cholmod_common *Common)
#define RETURN_IF_NULL(A, result)
#define MIN(a, b)
int n
#define ERROR(status, msg)
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX