Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_paraklete_kernel.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === paraklete_kernel ===================================================== */
3 /* ========================================================================== */
4 
6 
7 /* Sparse left-looking LU factorization, with partial pivoting. Based on
8  * Gilbert & Peierl's method, with a non-recursive DFS and with Eisenstat &
9  * Liu's symmetric pruning. No user-callable routines are in this file.
10  *
11  * PARAKLETE version 0.3: parallel sparse LU factorization. Nov 13, 2007
12  * Copyright (C) 2007, Univ. of Florida. Author: Timothy A. Davis
13  * See License.txt for the Version 2.1 of the GNU Lesser General Public License
14  * http://www.cise.ufl.edu/research/sparse
15  */
16 
17 #ifndef NDEBUG
18 /* global variables for debugging only */
20 #endif
21 
22 /* ========================================================================== */
23 /* === dfs ================================================================== */
24 /* ========================================================================== */
25 
26 /* Does a depth-first-search, starting at node j. */
27 
28 static Int dfs /* returns new top of output stack */
29 (
30  /* input, not modified on output: */
31  Int npiv,
32  Int j, /* node at which to start the DFS */
33  Int mark, /* mark value for Flag */
34  Int Pinv [ ], /* Pinv [i] = k if row i is kth pivot row, or EMPTY if
35  * row i is not yet pivotal. Only used in phase 1. */
36  Int Llen [ ],
37  Int Lip [ ],
38 
39  Int phase1, /* TRUE if in phase 1, FALSE if in phase 2 */
40 
41  /* workspace, not defined on input or output */
42  Int Stack [ ], /* size n */
43 
44  /* input/output: */
45  Int Flag [ ], /* Flag [i] >= mark means i is marked */
46  Int Lprune [ ], /* for symmetric pruning */
47  Int top, /* top of stack on input */
48  double LU [ ],
49  Int Li [ ], /* resulting column of L */
50  Int *plength,
51 
52  /* other, not defined on input or output */
53  Int Pstack [ ] /* keeps track of position in adj list during DFS */
54 )
55 {
56  Int i, pos, jnew, head, llen ;
57  Int *Lj ;
58 
59  llen = *plength ;
60  head = 0 ;
61  Stack [0] = j ;
62  ASSERT (Flag [j] < mark) ;
63 
64  while (head >= 0)
65  {
66  /* In phase 1, j is in the original row index space of A. In
67  * phase 2, j is in the final pivotal order. In both phases, jnew is
68  * in the pivotal row order. */
69  j = Stack [head] ;
70  jnew = (phase1 && j < npiv) ? (Pinv [j]) : (j) ;
71 
72  ASSERT (IMPLIES ( phase1, jnew >= 0 && jnew < debug_k)) ;
73  ASSERT (IMPLIES (!phase1, jnew >= 0 && jnew < debug_nfound)) ;
74 
75  if (Flag [j] < mark) /* a node is not yet visited */
76  {
77  /* first time that j has been visited */
78  Flag [j] = mark ;
79  /* set Pstack [head] to one past the last entry in col j to scan */
80  Pstack [head] = (Lprune [jnew] == EMPTY) ?
81  (Llen [jnew]) : (Lprune [jnew]) ;
82  }
83 
84  /* add the adjacent nodes to the recursive stack by iterating through
85  * until finding another non-visited pivotal node */
86  Lj = (Int *) (LU + Lip [jnew]) ;
87  for (pos = --Pstack [head] ; pos > 0 ; --pos)
88  {
89  /* In phase 1, i is in the original row index space of A. In
90  * phase 2, i is in the final pivotal order. */
91  i = Lj [pos] ;
92 
93  ASSERT (IMPLIES ( phase1, i >= 0 && i < debug_n)) ;
94  ASSERT (IMPLIES (!phase1, i >= 0 && i < debug_nfound)) ;
95 
96  if (Flag [i] < mark)
97  {
98  /* node i is not yet visited */
99  if (i < npiv && (!phase1 || Pinv [i] >= 0))
100  {
101  ASSERT (i < npiv) ;
102  /* keep track of where we left off in the scan of the
103  * adjacency list of node j so we can restart j where we
104  * left off. */
105  Pstack [head] = pos ;
106 
107  /* node i is pivotal; push it onto the recursive stack
108  * and immediately break so we can recurse on node i. */
109  Stack [++head] = i ;
110  break ;
111  }
112  else
113  {
114  /* node i is not pivotal (no outgoing edges).
115  * Flag as visited and store directly into L,
116  * and continue with current node j.
117  * This cannot occur during phase 2. */
118  Flag [i] = mark ;
119  Li [llen++] = i ;
120  }
121  }
122  }
123 
124  if (pos == 0)
125  {
126  /* if all adjacent nodes of j are already visited, pop j from
127  * recursive stack and push j onto output stack */
128  head-- ;
129  Stack [--top] = j ;
130  }
131  }
132 
133  *plength = llen ;
134  return (top) ; /* return top of output stack */
135 }
136 
137 
138 /* ========================================================================== */
139 /* === lsolve_symbolic ====================================================== */
140 /* ========================================================================== */
141 
142 /* Finds the pattern of x, for the solution of Lx=b */
143 
144 static void lsolve_symbolic
145 (
146  /* input, not modified on output: */
147  Int n, /* L is n-by-n, where n >= 0 */
148  Int k, /* kth step of factorization */
149  Int mark, /* mark for Flag */
150  Int kcol, /* b = A (:,kcol) */
151  Int Ap [ ],
152  Int Ai [ ],
153  Int Pinv [ ], /* Pinv [i] = k if i is kth pivot row, or EMPTY if row i
154  * is not yet pivotal. In phase 2, all rows are in
155  * their final order, and Pinv is a complete inverse
156  * permutation. */
157 
158  Int phase1, /* TRUE if in phase 1, FALSE if in phase 2 */
159  Int nfound, /* used in phase 2 only */
160  Int npiv,
161 
162  /* workspace, not defined on input or output */
163  Int Stack [ ], /* size n */
164 
165  /* workspace, defined on input and output */
166  Int Flag [ ], /* size n. Initially, all of Flag [0..n-1] < mark.
167  * After lsolve_symbolic is done, Flag [i] == mark if i
168  * is in the pattern of the output, and
169  * Flag [0..n-1] <= mark. */
170 
171  /* other */
172  Int Lprune [ ], /* for symmetric pruning */
173  Int Pstack [ ], /* workspace used in dfs */
174 
175  /* TODO: comment this */
176  double LU [ ],
177  Int *plu,
178  Int Llen [ ],
179  Int Ulen [ ],
180  Int Lip [ ],
181  Int Uip [ ]
182 )
183 {
184  Int i, p, p2, pend, top, llen, ulen, lup ;
185  Int *Li, *Ui ;
186 
187  top = n ;
188  llen = 0 ;
189  lup = *plu ;
190 
191  if (phase1)
192  {
193  Lip [k] = lup ;
194  }
195  Li = (Int *) (LU + lup) ;
196  pend = Ap [kcol+1] ;
197 
198  for (p = Ap [kcol] ; p < pend ; p++)
199  {
200  /* Ai is always in original row order, since it is never modified.
201  * In phase 1, we need to leave i in its original row index space.
202  * In phase 2, i needs to refer to the ith pivot row instead. */
203  if (phase1)
204  {
205  i = Ai [p] ;
206  }
207  else
208  {
209  i = Ai [p] ;
210  i = (i < npiv) ? Pinv [i] : i ;
211  if (i >= nfound) continue ;
212  }
213 
214  /* (i,k) is an entry in the block. start a DFS at node i */
215  if (Flag [i] < mark)
216  {
217  if (i < npiv && (!phase1 || Pinv [i] >= 0))
218  {
219  top = dfs (npiv, i, mark, Pinv, Llen, Lip, phase1, Stack, Flag,
220  Lprune, top, LU, Li, &llen, Pstack) ;
221  }
222  else
223  {
224  /* i is not pivotal, and not flagged. Flag and put in L.
225  * This cannot occur during phase 2. */
226  Flag [i] = mark ;
227  Li [llen++] = i ;
228  }
229  }
230  }
231 
232  /* for phase 2, llen will be zero */
233  if (phase1)
234  {
235  Llen [k] = llen ;
236  }
237  ASSERT (IMPLIES (!phase1, llen == 0)) ;
238 
239  /* advance LU pointer past the pattern and values of the new column of L */
240  lup += ((llen + 1) / 2) + llen ;
241 
242  /* find the length of the column of U */
243  ulen = n - top ;
244  if (phase1)
245  {
246  /* add one for the pivot itself */
247  ulen++ ;
248  }
249  Ulen [k] = ulen ;
250  Ui = (Int *) (LU + lup) ;
251  Uip [k] = lup ;
252 
253  /* advance LU pointer past the pattern and values of the new column of U */
254  lup += ((ulen + 1) / 2) + ulen ;
255 
256  /* extract Stack [top..n-1] to Ui */
257  for (p = top, p2 = 0 ; p < n ; p++, p2++)
258  {
259  Ui [p2] = Stack [p] ;
260  ASSERT (IMPLIES (!phase1, Ui [p2] < debug_nfound)) ;
261  }
262 
263  /* position the lu index at the starting point for next column */
264  *plu = lup ;
265 }
266 
267 
268 /* ========================================================================== */
269 /* === construct_column ===================================================== */
270 /* ========================================================================== */
271 
272 /* Scatter the column of A into the workspace X */
273 
274 static void construct_column
275 (
276  /* inputs, not modified on output */
277  Int kcol, /* the column of A to construct */
278  Int Ap [ ],
279  Int Ai [ ],
280  double Ax [ ],
281  Int phase1, /* phase 1: computing L1, L2 and U1. phase 2: just U2 */
282  Int nfound, /* only used in phase 2 */
283  Int npiv,
284  Int Pinv [ ], /* only used in phase 2 */
285 
286  /* zero on input, modified on output */
287  double X [ ]
288 )
289 {
290  Int p, pend, i ;
291 
292  pend = Ap [kcol+1] ;
293  if (phase1)
294  {
295  /* scatter the entire column of A */
296  for (p = Ap [kcol] ; p < pend ; p++)
297  {
298  X [Ai [p]] = Ax [p] ;
299  }
300  }
301  else
302  {
303  /* scatter only the pivotal rows of A (for the U2 part only),
304  * and permute to their final pivot order as well. */
305  for (p = Ap [kcol] ; p < pend ; p++)
306  {
307  i = Ai [p] ;
308  i = (i < npiv) ? Pinv [i] : i ;
309  if (i < nfound)
310  {
311  X [i] = Ax [p] ;
312  }
313  }
314  }
315 }
316 
317 
318 /* ========================================================================== */
319 /* === lsolve_numeric ======================================================= */
320 /* ========================================================================== */
321 
322 /* Computes the numerical values of x, for the solution of Lx=b. Note that x
323  * may include explicit zeros if numerical cancelation occurs. L is assumed
324  * to be unit-diagonal, with possibly unsorted columns (but the first entry in
325  * the column must always be the diagonal entry). */
326 
327 static void lsolve_numeric
328 (
329  /* input, not modified on output: */
330  Int npiv,
331  Int Pinv [ ], /* Pinv [i] = k if i is kth pivot row, or EMPTY if row i
332  * is not yet pivotal. */
333 
334  /* TODO comment this */
335  double *LU,
336  Int Uip [ ],
337  Int Lip [ ],
338  Int Ulen [ ],
339  Int Llen [ ],
340  Int k,
341 
342  Int phase1,
343  Int Lphase_len [ ], /* phase 1: Llen, phase 2: L1_len */
344 
345  /* output, must be zero on input: */
346  double X [ ] /* size n, initially zero. On output,
347  * X [Ui [up1..up-1]] and X [Li [lp1..lp-1]]
348  * contains the solution. */
349 )
350 {
351  double xj ;
352  double *Lx ;
353  Int p, s, j, jnew, llen, ulen ;
354  Int *Ui, *Li ;
355 
356  Ui = (Int *) (LU + Uip [k]) ;
357  ulen = Ulen [k] ;
358 
359  if (phase1) ulen-- ; /* skip the diagonal */
360 
361  /* solve Lx=b */
362  for (s = 0 ; s < ulen ; s++)
363  {
364  /* forward solve with column j of L (skip the unit diagonal of L).
365  * In phase 1, all of L1 and L2 is used. Ui not yet in pivotal order.
366  * In phase 2, only L1 is used. Ui already in pivotal order. */
367  j = Ui [s] ;
368  jnew = (phase1 && j < npiv) ? (Pinv [j]) : j ;
369 
370  ASSERT (IMPLIES ( phase1, jnew >= 0 && jnew < debug_n)) ;
371  ASSERT (IMPLIES (!phase1, jnew >= 0 && jnew < debug_nfound)) ;
372 
373  xj = X [j] ;
374  GET_COLUMN (Lip, Llen, LU, jnew, Li, Lx, llen) ;
375 
376  /* phase 1: solve with entire column of L (L1 and L2).
377  * phase 2: solve with L1 only */
378  llen = Lphase_len [jnew] ;
379 
380  for (p = 1 ; p < llen ; p++)
381  {
382  ASSERT (IMPLIES (!phase1, Li [p] > j && Li [p] < debug_nfound)) ;
383  X [Li [p]] -= Lx [p] * xj ;
384  }
385  }
386 }
387 
388 
389 /* ========================================================================== */
390 /* === lsolve =============================================================== */
391 /* ========================================================================== */
392 
393 /* Sparse symbolic and numeric solve of Lx=b to compute the kth column of L and
394  * U. In phase 1: L1, L2, and U1 are computed. In phase 2: only U2 is
395  * computed. */
396 
397 static void lsolve
398 (
399  Int phase1,
400  Int nfound,
401  Int npiv,
402  Int n,
403  Int k,
404  Int kcol,
405  Int Ap [ ],
406  Int Ai [ ],
407  double Ax [ ],
408 
409  double *LU,
410  Int *lup,
411  Int Lip [ ],
412  Int Uip [ ],
413  Int Llen [ ],
414  Int Ulen [ ],
415 
416  Int Lphase_len [ ],
417 
418  Int Pinv [ ],
419  Int Stack [ ],
420  Int Lprune [ ],
421  Int Pstack [ ],
422  Int Flag [ ],
423  Int mark,
424  double X [ ]
425 )
426 {
427  double *Ux ;
428  Int i, p, ulen ;
429  Int *Ui ;
430 
431  /* ---------------------------------------------------------------------- */
432  /* compute the nonzero pattern of the kth column of L and U */
433  /* ---------------------------------------------------------------------- */
434 
435  lsolve_symbolic (n, k, mark, kcol, Ap, Ai, Pinv, phase1, nfound, npiv,
436  Stack, Flag, Lprune, Pstack, LU, lup, Llen, Ulen, Lip, Uip) ;
437 
438  /* ---------------------------------------------------------------------- */
439  /* get the column of the matrix to factorize and scatter into X */
440  /* ---------------------------------------------------------------------- */
441 
442  construct_column (kcol, Ap, Ai, Ax, phase1, nfound, npiv, Pinv, X) ;
443 
444  /* ---------------------------------------------------------------------- */
445  /* compute the numerical values of the kth column (s = L \ A(:,kcol)) */
446  /* ---------------------------------------------------------------------- */
447 
448  lsolve_numeric (npiv,
449  Pinv, LU, Uip, Lip, Ulen, Llen, k, phase1, Lphase_len, X) ;
450 
451  /* --------------------------------------------------------------------- */
452  /* finalize the kth column of U (pivot excluded) and clear X */
453  /* --------------------------------------------------------------------- */
454 
455  GET_COLUMN (Uip, Ulen, LU, k, Ui, Ux, ulen) ;
456 
457  if (phase1)
458  {
459  /* phase 1: modify row indices in Ui to be in their final pivot order */
460  ulen-- ; /* skip the diagonal */
461  for (p = 0 ; p < ulen ; p++)
462  {
463  i = Ui [p] ;
464  ASSERT (i >= 0 && i < npiv) ;
465  ASSERT (Pinv [i] >= 0 && Pinv [i] < npiv) ;
466  Ui [p] = Pinv [i] ;
467  Ux [p] = X [i] ;
468  X [i] = 0 ;
469  }
470  }
471  else
472  {
473  /* phase 2: Ui is already in pivotal order */
474  for (p = 0 ; p < ulen ; p++)
475  {
476  i = Ui [p] ;
477  ASSERT (i >= 0 && i < nfound) ;
478  Ux [p] = X [i] ;
479  X [i] = 0 ;
480  }
481  }
482 }
483 
484 
485 /* ========================================================================== */
486 /* === lpivot =============================================================== */
487 /* ========================================================================== */
488 
489 /* Find a pivot via threshold partial pivoting, and scale the column of L.
490  * This routine is active during phase 1 only. Returns TRUE if pivot found,
491  * FALSE otherwise. */
492 
493 static Int lpivot
494 (
495  Int diagrow,
496  Int *p_pivrow,
497  double *p_pivot,
498  double *p_abs_pivot,
499  double tol_diag,
500  double tol_offdiag,
501  double X [ ],
502  double *LU,
503  Int Lip [ ],
504  Int Llen [ ],
505  Int k,
506  Int npiv
507 )
508 {
509  double x, pivot, abs_pivot, max_entry ;
510  double *Lx ;
511  Int p, i, ppivrow, pdiag, pivrow, pivot_found, llen ;
512  Int *Li ;
513 
514  /* ---------------------------------------------------------------------- */
515  /* look in Li [0 ... Llen [k] - 1 ] for a pivot row */
516  /* ---------------------------------------------------------------------- */
517 
518  GET_COLUMN (Lip, Llen, LU, k, Li, Lx, llen) ;
519 
520  pdiag = EMPTY ;
521  abs_pivot = -1 ;
522  max_entry = -1 ;
523  ppivrow = EMPTY ;
524 
525  for (p = 0 ; p < llen ; p++)
526  {
527  /* gather the entry from X and store in L */
528  i = Li [p] ;
529  x = X [i] ;
530  X [i] = 0 ;
531 
532  Lx [p] = x ;
533  x = fabs (x) ;
534 
535  /* find the diagonal */
536  if (i == diagrow)
537  {
538  pdiag = p ;
539  }
540 
541  /* find the partial-pivoting choice (constrained to rows 0..npiv-1) */
542  if (x > abs_pivot && i < npiv)
543  {
544  abs_pivot = x ;
545  ppivrow = p ;
546  }
547 
548  /* find the max entry in this column (any row) */
549  max_entry = MAX (max_entry, x) ;
550  }
551 
552  /* compare the diagonal with the largest entry */
553  if (pdiag != EMPTY)
554  {
555  x = fabs (Lx [pdiag]) ;
556  if (x >= tol_diag * max_entry)
557  {
558  /* the diagonal is large enough */
559  abs_pivot = x ;
560  ppivrow = pdiag ;
561  }
562  else
563  {
564  /* diagonal entry is too small, discard it */
565  pdiag = EMPTY ;
566  }
567  }
568 
569  /* if diagonal not found or not chosen, try for an off-diagonal pivot */
570  if (pdiag == EMPTY && ppivrow != EMPTY)
571  {
572  /* no diagonal pivot. Try to pick the off-diagonal pivot */
573  if (abs_pivot < tol_offdiag * max_entry)
574  {
575  /* off-diagonal pivot is too small, discard it */
576  ppivrow = EMPTY ;
577  }
578  }
579 
580  pivot_found = (ppivrow != EMPTY && abs_pivot > 0) ;
581 
582  if (pivot_found)
583  {
584  /* swap pivot row to first entry in column k of L */
585  pivrow = Li [ppivrow] ;
586  pivot = Lx [ppivrow] ;
587  Li [ppivrow] = Li [0] ;
588  Lx [ppivrow] = Lx [0] ;
589  Li [0] = pivrow ;
590  Lx [0] = 1.0 ;
591 
592  ASSERT (pivrow >= 0 && pivrow < npiv) ;
593  ASSERT (pivot != 0) ;
594 
595  /* divide L by the pivot value */
596  for (p = 1 ; p < Llen [k] ; p++)
597  {
598  Lx [p] /= pivot ;
599  }
600 
601  *p_pivrow = pivrow ;
602  *p_pivot = pivot ;
603  *p_abs_pivot = abs_pivot ;
604  }
605 
606  return (pivot_found) ;
607 }
608 
609 
610 /* ========================================================================== */
611 /* === prune ================================================================ */
612 /* ========================================================================== */
613 
614 /* Prune the columns of L to reduce work in subsequent depth-first searches.
615  * This routine is not active during phase 2. */
616 
617 static void prune
618 (
619  /* TODO comment this */
620  Int npiv,
621  Int Lprune [ ],
622  Int Pinv [ ],
623  Int k,
624  Int pivrow,
625  double *LU,
626  Int Uip [ ],
627  Int Lip [ ],
628  Int Ulen [ ],
629  Int Llen [ ]
630 )
631 {
632  double x ;
633  double *Lx, *Ux ;
634  Int p, i, j, p2, phead, ptail, ulen, llen ;
635  Int *Li, *Ui ;
636 
637  /* ---------------------------------------------------------------------- */
638  /* check to see if any column of L can be pruned */
639  /* ---------------------------------------------------------------------- */
640 
641  GET_COLUMN (Uip, Ulen, LU, k, Ui, Ux, ulen) ;
642  ulen-- ; /* skip the diagonal entry */
643 
644  for (p = 0 ; p < ulen ; p++)
645  {
646  j = Ui [p] ;
647  ASSERT (j >= 0 && j < k) ;
648  if (Lprune [j] == EMPTY)
649  {
650  /* scan column j of L for the pivot row */
651  GET_COLUMN (Lip, Llen, LU, j, Li, Lx, llen) ;
652 
653  for (p2 = 0 ; p2 < Llen [j] ; p2++)
654  {
655  if (pivrow == Li [p2])
656  {
657  /* found it! This column can be pruned.
658  * partition column j of L. The unit diagonal of L
659  * remains as the first entry in the column of L. */
660  phead = 0 ;
661  ptail = Llen [j] ;
662  while (phead < ptail)
663  {
664  i = Li [phead] ;
665  if (i < npiv && Pinv [i] >= 0)
666  {
667  /* leave at the head */
668  phead++ ;
669  }
670  else
671  {
672  /* swap with the tail */
673  ptail-- ;
674  Li [phead] = Li [ptail] ;
675  Li [ptail] = i ;
676  x = Lx [phead] ;
677  Lx [phead] = Lx [ptail] ;
678  Lx [ptail] = x ;
679  }
680  }
681 
682  /* set Lprune to one past the last entry in the
683  * first part of the column of L. Entries in
684  * Li [0 ... Lprune [j]-1] are the only part of
685  * column j of L that needs to be scanned in the DFS.
686  * Lprune [j] was EMPTY; setting it >= 0 also flags
687  * column j as pruned. */
688  Lprune [j] = ptail ;
689  break ;
690  }
691  }
692  }
693  }
694 }
695 
696 
697 /* ========================================================================== */
698 /* === paraklete_kernel ===================================================== */
699 /* ========================================================================== */
700 
701 /* Factorize P*A*Q into L*U+S. Returns TRUE if successful, FALSE if out of
702  * memory. If memory runs out, the factors of this node (LUnode) are not
703  * freed; that is done by the caller. If the matrix is singular, the
704  * Schur complement (S) has a larger dimension than expected. */
705 
707 (
708  cholmod_sparse *A,
709  paraklete_node *LUnode,
710  paraklete_common *Common
711 )
712 {
713  cholmod_common *cm ;
714  double pivot, abs_pivot, umin, umax, ujk, x, tol_diag, tol_offdiag, growth ;
715  double *Lx, *Ux, *LU, *S, *Sx, *Ax, *X ;
716  Int *Li, *Ui, *Si, *Qinv, *L1_len, *Ap, *Ai, *Llen, *Ulen, *Lip, *Uip, *P,
717  *Q, *Pinv, *Sip, *Slen, *Flag, *Queue, *Iwork, *Stack, *Pstack,
718  *Lprune ;
719  Int k, p, i, j, pivrow, kbar, diagrow, noffdiag, lup, mark, unpruned,
720  phead, ptail, sp, slen, llen, ulen, p2, pend, ngrow, qhead, qtail, sn,
721  found, kcol, second_try, nfound, n, npiv, lnz, unz, snz, lup_orig ;
722  size_t lusize, ssize ;
723 
724  /* ---------------------------------------------------------------------- */
725  /* get inputs */
726  /* ---------------------------------------------------------------------- */
727 
728  cm = &(Common->cm) ; /* CHOLMOD Common */
729 
730  /* Matrix to factorize */
731  n = A->nrow ; /* A is n-by-n */
732  Ap = A->p ; /* size n+1, column pointers for A */
733  Ai = A->i ; /* size nz = Ap [n], row indices for A */
734  Ax = A->x ; /* size nz, values of A */
735 
736  /* LU factors of this node */
737  Llen = LUnode->llen ; /* size n, column length of L */
738  Ulen = LUnode->ulen ; /* size n, column length of U */
739  Lip = LUnode->lp ; /* size n, column pointers for L */
740  Uip = LUnode->up ; /* size n, column pointers for U */
741  LU = LUnode->ix ; /* size LU->size on input and output */
742  lusize = LUnode->lusize ; /* initial and final size of LU */
743  npiv = LUnode->PK_NPIV ; /* number of pivots to find */
744 
745  P = LUnode->Plocal ; /* size npiv, row permutation, where P [k] = i
746  * if row i is the kth pivot row. */
747  Q = LUnode->Qlocal ; /* size npiv, column permutation */
748  Pinv = LUnode->Pinv ; /* size npiv, inverse row permutation, where
749  * Pinv [i] = k if row i is the kth pivot row */
750  Qinv = LUnode->Qinv ; /* size npiv, inverse of Q */
751 
752  tol_diag = Common->tol_diag ; /* partial pivoting tolerance */
753  tol_offdiag = Common->tol_offdiag ; /* partial pivoting tolerance */
754  growth = Common->growth ; /* memory growth factor */
755 
756  /* ---------------------------------------------------------------------- */
757  /* get workspace */
758  /* ---------------------------------------------------------------------- */
759 
760  CHOLMOD (allocate_work) (n, 3*n, n, cm) ;
761  if (cm->status != CHOLMOD_OK)
762  {
763  /* out of memory */
764  return (FALSE) ;
765  }
766 
767  /* workspace, not defined on input or output: */
768  Flag = cm->Flag ; /* size n */
769  Queue = cm->Head ; /* size n+1 */
770  Iwork = cm->Iwork ;
771  Stack = Iwork ; /* size n */
772  Pstack = Iwork + n ; /* size n */
773  Lprune = Iwork + 2*n ; /* size n */
774 
775  /* workspace, not defined on input */
776  X = cm->Xwork ; /* size n, undefined on input, zero on output */
777 
778  /* ====================================================================== */
779  /* PHASE 1: compute L1, L2, and U1 ====================================== */
780  /* ====================================================================== */
781 
782  /* ---------------------------------------------------------------------- */
783  /* initializations */
784  /* ---------------------------------------------------------------------- */
785 
786  npiv = MAX (0, MIN (npiv, n)) ;
787  nfound = 0 ;
788 
789  DEBUG (debug_n = n) ;
790  DEBUG (debug_npiv = npiv) ;
791 
792  lnz = 0 ;
793  unz = 0 ;
794  snz = 0 ;
795 
796  umin = 0 ;
797  umax = 0 ;
798  noffdiag = 0 ;
799  lup = 0 ;
800  LUnode->nrealloc = 0 ;
801  for (k = 0 ; k < n ; k++)
802  {
803  X [k] = 0 ;
804  Flag [k] = EMPTY ; /* flag k as unmarked */
805  Lprune [k] = EMPTY ; /* flag k as not pruned */
806  }
807  mark = 0 ;
808 
809  ngrow =
810  (n+1) /* reals, in L and U (both diag L and U are stored) */
811  + (n+1)/2 /* ints */
812  + 2 ; /* Int to real may be rounded up */
813 
814  /*
815  (3*n/2) + 2 ;
816  */
817 
818  /* ---------------------------------------------------------------------- */
819  /* mark all rows as non-pivotal and determine initial diagonal mapping */
820  /* ---------------------------------------------------------------------- */
821 
822  /* initial Q is identity, so the diagonal entries are the natural ones */
823  for (k = 0 ; k < npiv ; k++)
824  {
825  P [k] = k ;
826  Pinv [k] = FLIP (k) ; /* mark all candidiate rows as non-pivotal */
827  }
828 
829  /* (P [k] = row) means that (UNFLIP (Pinv [row]) = k), and visa versa.
830  * If row is pivotal, then Pinv [row] >= 0. A row is initially "flipped"
831  * (Pinv [k] < EMPTY), and then marked "unflipped" when it becomes
832  * pivotal. */
833 
834  /* ---------------------------------------------------------------------- */
835  /* place all potential pivot columns in the candidate column queue */
836  /* ---------------------------------------------------------------------- */
837 
838  for (k = 0 ; k < npiv ; k++)
839  {
840  Queue [k] = k ;
841  }
842  qhead = 0 ;
843  qtail = npiv ;
844 
845  /* ---------------------------------------------------------------------- */
846  /* factorize up to npiv columns */
847  /* ---------------------------------------------------------------------- */
848 
849  for (k = 0 ; k < npiv ; k++)
850  {
851 
852  PR1 ((Common->file, "\n\n==========================L,U1: k: "ID"\n", k));
853  DEBUG (debug_k = k) ;
854 
855  /* ------------------------------------------------------------------ */
856  /* determine if LU factors have grown too big */
857  /* ------------------------------------------------------------------ */
858 
859  /* LU can grow by at most 3n/2 + 2 entries if the column is dense */
860  if (lup + ngrow > (Int) lusize)
861  {
862  size_t new = (growth * lusize + ngrow + 2) ;
863  PR1 ((Common->file, "growing LU from "ID" to "ID"\n", lusize, new)) ;
864  LU = CHOLMOD (realloc) (new, sizeof (double), LU, &lusize, cm) ;
865  LUnode->ix = LU ;
866  LUnode->lusize = lusize ;
867  if (cm->status != CHOLMOD_OK)
868  {
869  /* TODO return FALSE, and broadcast error to all processes */
870  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
871  return (FALSE) ;
872  }
873  }
874 
875  /* ------------------------------------------------------------------ */
876  /* find a good pivot column, if possible */
877  /* ------------------------------------------------------------------ */
878 
879  found = FALSE ;
880  diagrow = EMPTY ;
881  kcol = EMPTY ;
882  while (!found && qhead != qtail)
883  {
884 
885  /* -------------------------------------------------------------- */
886  /* grab a pivot column candidate from the head of the queue */
887  /* -------------------------------------------------------------- */
888 
889  kcol = Queue [qhead] ;
890  qhead = (qhead + 1) % (npiv + 1) ;
891  second_try = (kcol < 0) ;
892  kcol = UNFLIP (kcol) ;
893 
894  /* -------------------------------------------------------------- */
895  /* s = L \ A (:, kcol) ; store result in L(:,k) and U(:,k) */
896  /* -------------------------------------------------------------- */
897 
898  lup_orig = lup ;
899  lsolve (TRUE, nfound, npiv,
900  n, k, kcol, Ap, Ai, Ax, LU, &lup, Lip, Uip,
901  Llen, Ulen, Llen, Pinv, Stack, Lprune, Pstack, Flag, mark, X) ;
902 
903  /* -------------------------------------------------------------- */
904  /* partial pivoting with diagonal preference */
905  /* -------------------------------------------------------------- */
906 
907  /* determine what the "diagonal" is */
908  diagrow = P [k] ; /* might already be pivotal */
909  PR1 ((Common->file, "k "ID", diagrow = "ID", UNFLIP(diagrow) = "ID"\n",
910  k, diagrow, UNFLIP (diagrow))) ;
911 
912  /* find a pivot and scale the pivot column */
913  found = lpivot (diagrow, &pivrow, &pivot, &abs_pivot, tol_diag,
914  tol_offdiag, X, LU, Lip, Llen, k, npiv) ;
915 
916  if (!found)
917  {
918  /* pivot column candidate failed. If this was already its
919  * second chance, discard it. Otherwise, flag it and put it
920  * at the end of the queue. The kth column of L and U
921  * computed by lsolve, above, is discarded. */
922  if (!second_try)
923  {
924  PR1 ((Common->file, "requeue kcol "ID" for 2nd try\n", kcol));
925  Queue [qtail] = FLIP (kcol) ;
926  qtail = (qtail + 1) % (npiv + 1) ;
927  }
928  else
929  {
930  PR1 ((Common->file, "discarding kcol "ID"\n", kcol)) ;
931  }
932  PR1 ((Common->file, "restore lup, "ID" to "ID"\n", lup_orig, lup)) ;
933  lup = lup_orig ;
934  }
935  else
936  {
937  /* we found a pivot column */
938  Q [nfound++] = kcol ;
939  PR1 ((Common->file,"found kcol: "ID" nfound "ID"\n", kcol, nfound));
940  }
941 
942  /* clear the flag array */
943  mark++ ;
944  }
945 
946  DEBUG (debug_nfound = nfound) ;
947 
948  if (!found)
949  {
950  /* No more pivots to be found. Go to phase 2 to compute U2 */
951  break ;
952  }
953 
954  /* ------------------------------------------------------------------ */
955  /* we now have a valid pivot row and column */
956  /* ------------------------------------------------------------------ */
957 
958  PR1 ((Common->file, "\nk "ID": pivcol "ID" pivrow "ID": %g\n",
959  k, kcol, pivrow, pivot)) ;
960  ASSERT (pivrow >= 0 && pivrow < npiv) ;
961  ASSERT (Pinv [pivrow] < 0) ;
962 
963  /* ------------------------------------------------------------------ */
964  /* keep track of the smallest and largest entry on the diagonal of U */
965  /* ------------------------------------------------------------------ */
966 
967  if (k == 0)
968  {
969  umin = abs_pivot ;
970  umax = abs_pivot ;
971  }
972  else if (abs_pivot < umin)
973  {
974  umin = abs_pivot ;
975  }
976  else if (abs_pivot > umax)
977  {
978  umax = abs_pivot ;
979  }
980 
981  /* ------------------------------------------------------------------ */
982  /* copy the pivot value as the last entry in the column of U */
983  /* ------------------------------------------------------------------ */
984 
985  GET_COLUMN (Uip, Ulen, LU, k, Ui, Ux, ulen) ;
986  PR1 ((Common->file, "k "ID" Ulen[k] "ID"\n", k, Ulen [k])) ;
987  ASSERT (ulen > 0) ;
988  Ui [ulen-1] = k ;
989  Ux [ulen-1] = pivot ;
990  PR1 ((Common->file, "pivot: Ui "ID" Ux %g\n", Ui [ulen-1], Ux [ulen-1])) ;
991 
992  /* ------------------------------------------------------------------ */
993  /* log the pivot permutation */
994  /* ------------------------------------------------------------------ */
995 
996  DEBUG (kbar = UNFLIP (Pinv [diagrow])) ;
997  ASSERT (kbar < n) ;
998  ASSERT (P [kbar] == diagrow) ;
999 
1000  if (pivrow != diagrow)
1001  {
1002  /* an off-diagonal pivot has been chosen */
1003  noffdiag++ ;
1004  /*
1005  printf ("pivrow "ID" k "ID" noffdiagn "ID"\n", pivrow, k, noffdiag) ;
1006  */
1007  PR1 ((Common->file,">>>>>>>>>>>>>>>> pivrow "ID" k "ID" off-diagonal\n",
1008  pivrow, k)) ;
1009  if (Pinv [diagrow] < 0)
1010  {
1011  /* the former diagonal row index, diagrow, has not yet been
1012  * chosen as a pivot row. Log this diagrow as the "diagonal"
1013  * entry in the column kbar for which the chosen pivot row,
1014  * pivrow, was originally logged as the "diagonal" */
1015  kbar = FLIP (Pinv [pivrow]) ;
1016  P [kbar] = diagrow ;
1017  Pinv [diagrow] = FLIP (kbar) ;
1018  }
1019  }
1020  P [k] = pivrow ;
1021  Pinv [pivrow] = k ;
1022 
1023 #ifndef NDEBUG
1024  for (p = 0 ; p < ulen ; p++)
1025  {
1026  PR2 ((Common->file,"Column "ID" of U: "ID": %g\n", k, Ui [p], Ux [p])) ;
1027  }
1028  GET_COLUMN (Lip, Llen, LU, k, Li, Lx, llen) ;
1029  for (p = 0 ; p < llen ; p++)
1030  {
1031  PR2 ((Common->file,"Column "ID" of L: "ID": %g\n", k, Li [p], Lx [p])) ;
1032  }
1033 #endif
1034 
1035  /* ------------------------------------------------------------------ */
1036  /* symmetric pruning */
1037  /* ------------------------------------------------------------------ */
1038 
1039  prune (npiv, Lprune, Pinv, k, pivrow, LU, Uip, Lip, Ulen, Llen) ;
1040 
1041  lnz += Llen [k] ;
1042  unz += Ulen [k] ;
1043  }
1044 
1045  LUnode->noffdiag = noffdiag ; /* # of off-diagonal pivots chosen */
1046  LUnode->umin = umin ; /* smallest entry on diagonal of U */
1047  LUnode->umax = umax ; /* largest entry on the diagonal of U */
1048  LUnode->PK_NFOUND = nfound ; /* number of pivots found */
1049  LUnode->lnz = lnz ; /* nnz in L */
1050 
1051  PR1 ((Common->file, "noffdiag "ID"\n", noffdiag)) ;
1052  PR1 ((Common->file, "umin %g umax %g condest %g\n", umin, umax, umax/umin));
1053 
1054  /* ====================================================================== */
1055  /* PHASE 2: compute U2 and S ============================================ */
1056  /* ====================================================================== */
1057 
1058  /* ---------------------------------------------------------------------- */
1059  /* finalize the row and column permutations */
1060  /* ---------------------------------------------------------------------- */
1061 
1062  DEBUG (for (i = 0 ; i < n ; i++) ASSERT (Flag [i] < mark)) ;
1063 
1064  k = nfound ;
1065  for (i = 0 ; i < npiv ; i++)
1066  {
1067  if (Pinv [i] < 0)
1068  {
1069  /* a non-pivotal row */
1070  P [k] = i ;
1071  Pinv [i] = k++ ;
1072  }
1073  }
1074 
1075  for (j = 0 ; j < npiv ; j++)
1076  {
1077  Qinv [j] = EMPTY ;
1078  }
1079  for (k = 0 ; k < nfound ; k++)
1080  {
1081  PR2 ((Common->file, "k "ID" Q [k] "ID" npiv "ID"\n", k, Q [k], npiv)) ;
1082  ASSERT (Q [k] >= 0 && Q [k] < npiv) ;
1083  Qinv [Q [k]] = k ;
1084  }
1085 
1086  k = nfound ;
1087  for (j = 0 ; j < npiv ; j++)
1088  {
1089  if (Qinv [j] == EMPTY)
1090  {
1091  /* a non-pivotal column */
1092  Q [k] = j ;
1093  Qinv [j] = k++ ;
1094  }
1095  }
1096  ASSERT (k == npiv) ;
1097 
1098 #ifndef NDEBUG
1099  for (i = 0 ; i < npiv ; i++)
1100  {
1101  if (i == nfound) PR1 ((Common->file,"-------- nfound = "ID"\n", nfound)) ;
1102  if (i == npiv ) PR1 ((Common->file,"-------- npiv = "ID"\n", npiv )) ;
1103  PR2 ((Common->file,"P["ID"] = "ID" Pinv["ID"] = "ID"\n", i, P[i], i, Pinv[i])) ;
1104  PR2 ((Common->file,"Q["ID"] = "ID" Qinv["ID"] = "ID"\n", i, Q[i], i, Qinv[i])) ;
1105  }
1106 #endif
1107 
1108  /* ---------------------------------------------------------------------- */
1109  /* partition the columns of L into L1 (pivotal) and L2 (non-pivotal) */
1110  /* ---------------------------------------------------------------------- */
1111 
1112  /* use Queue as workspace for L1_len */
1113  L1_len = Queue ;
1114 
1115  for (j = 0 ; j < nfound ; j++)
1116  {
1117  GET_COLUMN (Lip, Llen, LU, j, Li, Lx, llen) ;
1118 
1119  /* change all row indices in L1 and L2 to final row indices */
1120  for (p = 0 ; p < llen ; p++)
1121  {
1122  i = Li [p] ;
1123  if (i < npiv)
1124  {
1125  Li [p] = Pinv [i] ;
1126  }
1127  }
1128 
1129  unpruned = (Lprune [j] == EMPTY) ;
1130 
1131  phead = (unpruned) ? 1 : (Lprune [j]) ;
1132  ptail = llen ;
1133 
1134 #ifndef NDEBUG
1135  /* any pruned part of the column is already pivotal */
1136  for (p = 0 ; p < phead ; p++)
1137  {
1138  ASSERT (Li [p] < nfound) ;
1139  }
1140 #endif
1141 
1142  /* partition row indices in L1 (< nfound) and L2 (>= nfound) */
1143  while (phead < ptail)
1144  {
1145  i = Li [phead] ;
1146  if (i < nfound)
1147  {
1148  /* leave at the head */
1149  phead++ ;
1150  }
1151  else
1152  {
1153  /* swap with the tail */
1154  ptail-- ;
1155  Li [phead] = Li [ptail] ;
1156  Li [ptail] = i ;
1157  x = Lx [phead] ;
1158  Lx [phead] = Lx [ptail] ;
1159  Lx [ptail] = x ;
1160  }
1161  }
1162 
1163  L1_len [j] = ptail ;
1164 
1165  /* prune the column for the next lsolve */
1166  if (unpruned)
1167  {
1168  Lprune [j] = L1_len [j] ;
1169  }
1170 
1171 #ifndef NDEBUG
1172  /* the column is now partitioned */
1173  for (p = 0 ; p < Lprune [j] ; p++)
1174  {
1175  ASSERT (Li [p] < nfound) ;
1176  }
1177  ASSERT (Lprune [j] <= L1_len [j]) ;
1178  for ( ; p < L1_len [j] ; p++)
1179  {
1180  ASSERT (Li [p] < nfound) ;
1181  }
1182  for ( ; p < Llen [j] ; p++)
1183  {
1184  ASSERT (Li [p] >= nfound) ;
1185  }
1186 #endif
1187 
1188  }
1189 
1190  /* ---------------------------------------------------------------------- */
1191  /* compute the U2 block, U2 = L1 \ A12 */
1192  /* ---------------------------------------------------------------------- */
1193 
1194  ngrow =
1195  (nfound+1) /* reals, in L and U (both diag L and U are stored) */
1196  + (nfound+1)/2 /* ints */
1197  + 2 ; /* Int to real may be rounded up */
1198 
1199  for (k = nfound ; k < n ; k++)
1200  {
1201  PR1 ((Common->file, "\n\n=============================U2: k: "ID"\n", k));
1202  DEBUG (debug_k = k) ;
1203 
1204  /* ------------------------------------------------------------------ */
1205  /* determine if LU factors have grown too big */
1206  /* ------------------------------------------------------------------ */
1207 
1208  /* LU can grow by at most 3*nfound/2+2 entries if the column is dense */
1209  if (lup + ngrow > (Int) lusize)
1210  {
1211  size_t new = (growth * lusize + ngrow + 2) ;
1212  LU = CHOLMOD (realloc) (new, sizeof (double), LU, &lusize, cm) ;
1213  LUnode->ix = LU ;
1214  LUnode->lusize = lusize ;
1215  if (cm->status != CHOLMOD_OK)
1216  {
1217  /* TODO return FALSE, and broadcast error to all processes */
1218  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
1219  return (FALSE) ;
1220  }
1221  }
1222 
1223  /* ------------------------------------------------------------------ */
1224  /* determine which column of A this is */
1225  /* ------------------------------------------------------------------ */
1226 
1227  kcol = (k < npiv) ? Q [k] : k ;
1228 
1229  /* ------------------------------------------------------------------ */
1230  /* s = L \ A (:, kcol) and store result in U(:,k) */
1231  /* ------------------------------------------------------------------ */
1232 
1233  lsolve (FALSE, nfound, npiv,
1234  n, k, kcol, Ap, Ai, Ax, LU, &lup, Lip, Uip,
1235  Llen, Ulen, L1_len, Pinv, Stack, Lprune, Pstack, Flag, mark, X) ;
1236 
1237  PR2 ((Common->file, "lup is now "ID"\n", lup)) ;
1238 
1239 #ifndef NDEBUG
1240  GET_COLUMN (Uip, Ulen, LU, k, Ui, Ux, ulen) ;
1241  for (p = 0 ; p < ulen ; p++)
1242  {
1243  PR2 ((Common->file, "Column "ID" of U2: "ID": %g\n", k, Ui[p], Ux[p])) ;
1244  }
1245 #endif
1246 
1247  unz += Ulen [k] ;
1248 
1249  /* clear the flag array */
1250  mark++ ;
1251  }
1252 
1253  LUnode->unz = unz ; /* nnz in U */
1254 
1255  /* ---------------------------------------------------------------------- */
1256  /* shrink the LU factors to just the required size */
1257  /* ---------------------------------------------------------------------- */
1258 
1259  LU = CHOLMOD (realloc) (lup, sizeof (double), LU, &lusize, cm) ;
1260  LUnode->ix = LU ;
1261  LUnode->lusize = lusize ;
1262  ASSERT (cm->status == CHOLMOD_OK) ;
1263 
1264  /* ---------------------------------------------------------------------- */
1265  /* compute the Schur complement, S = A22 - L2*U2 */
1266  /* ---------------------------------------------------------------------- */
1267 
1268  sn = n - nfound ;
1269  ssize = lusize ;
1270  LUnode->PK_SSIZE = ssize ;
1271  PR1 ((Common->file, "allocate S, : ssize "ID" sn "ID" \n", ssize, sn)) ;
1272 
1273  S = CHOLMOD (malloc) (ssize, sizeof (double), cm) ;
1274  Sip = CHOLMOD (malloc) (sn, sizeof (Int), cm) ;
1275  Slen = CHOLMOD (malloc) (sn, sizeof (Int), cm) ;
1276  LUnode->sx = S ;
1277  LUnode->sp = Sip ;
1278  LUnode->slen = Slen ;
1279  LUnode->PK_SSIZE = ssize ;
1280  LUnode->PK_SN = sn ;
1281  if (cm->status != CHOLMOD_OK)
1282  {
1283  /* TODO return FALSE, and broadcast error to all processes */
1284  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
1285  return (FALSE) ;
1286  }
1287 
1288  sp = 0 ;
1289  ngrow = (3 * (n - nfound) / 2) + 2 ;
1290 
1291  /* S is square, of order n-nfound, with rows/cols in range 0 : n-nfound-1 */
1292 
1293  for (k = nfound ; k < n ; k++)
1294  {
1295  PR2 ((Common->file, "\n\n========================== S: k: "ID" sk: "ID"\n",
1296  k, k-nfound)) ;
1297  DEBUG (for (i = 0 ; i < n ; i++) ASSERT (Flag [i] < mark)) ;
1298 
1299  /* ------------------------------------------------------------------ */
1300  /* determine if the Schur complement needs to grow */
1301  /* ------------------------------------------------------------------ */
1302 
1303  if (sp + ngrow > (Int) ssize)
1304  {
1305  size_t new = (growth * ssize + ngrow + 2) ;
1306  PR1 ((Common->file, "proc "ID" growing S from "ID" to "ID"\n",
1307  Common->myid, ssize, new)) ;
1308  S = CHOLMOD (realloc) (new, sizeof (double), S, &ssize, cm) ;
1309  LUnode->sx = S ;
1310  LUnode->PK_SSIZE = ssize ;
1311  if (cm->status != CHOLMOD_OK)
1312  {
1313  /* TODO return FALSE, and broadcast error to all processes */
1314  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
1315  return (FALSE) ;
1316  }
1317  }
1318 
1319  /* ------------------------------------------------------------------ */
1320  /* compute the kth column of S */
1321  /* ------------------------------------------------------------------ */
1322 
1323  Sip [k - nfound] = sp ;
1324  Si = (Int *) (S + sp) ;
1325 
1326  /* ------------------------------------------------------------------ */
1327  /* scatter the kth column of A*Q (namely, A(:,kcol)) into X */
1328  /* ------------------------------------------------------------------ */
1329 
1330  kcol = (k < npiv) ? Q [k] : k ;
1331  slen = 0 ;
1332  DEBUG (for (i = 0 ; i < n ; i++) ASSERT (X [i] == 0)) ;
1333 
1334  /* scatter only the non-pivotal rows of A (for the S part only) */
1335  pend = Ap [kcol+1] ;
1336  for (p = Ap [kcol] ; p < pend ; p++)
1337  {
1338  i = Ai [p] ;
1339  i = (i < npiv) ? Pinv [i] : i ;
1340  if (i >= nfound)
1341  {
1342  PR3 ((Common->file, "S: Entry in A: "ID" %g\n", i, Ax [p])) ;
1343  X [i] = Ax [p] ;
1344  Flag [i] = mark ;
1345  Si [slen++] = i - nfound ;
1346  }
1347  }
1348 
1349  /* ------------------------------------------------------------------ */
1350  /* X = X - L2 * U2 (:,k) */
1351  /* ------------------------------------------------------------------ */
1352 
1353  /* get the pointers for the kth column of U */
1354  GET_COLUMN (Uip, Ulen, LU, k, Ui, Ux, ulen) ;
1355  PR2 ((Common->file, "Multiply L2 by U2(:,"ID") :\n", k)) ;
1356 
1357  /* for each j for which U (j,k) is nonzero, do: */
1358  for (p = 0 ; p < ulen ; p++)
1359  {
1360  /* X = X - L (nfound:n, j) * U (j,k) */
1361  j = Ui [p] ;
1362  ASSERT (j >= 0 && j < nfound) ;
1363  ujk = Ux [p] ;
1364  PR2 ((Common->file, "U("ID","ID") = %g\n", j, k, ujk)) ;
1365  GET_COLUMN (Lip, Llen, LU, j, Li, Lx, llen) ;
1366  for (p2 = L1_len [j] ; p2 < llen ; p2++)
1367  {
1368  i = Li [p2] ;
1369  ASSERT (i >= nfound && i < n) ;
1370  PR3 ((Common->file, " L("ID","ID") = %g\n", i, j, Lx [p2])) ;
1371  if (Flag [i] < mark)
1372  {
1373  PR3 ((Common->file, " new entry in Si, slen "ID"\n",slen));
1374  Si [slen++] = i - nfound ;
1375  Flag [i] = mark ;
1376  }
1377  X [i] -= Lx [p2] * ujk ;
1378  }
1379  }
1380 
1381  /* ------------------------------------------------------------------ */
1382  /* allocate space for S(:,k) */
1383  /* ------------------------------------------------------------------ */
1384 
1385  /* if slen is odd, this entry is allocated but not accessed */
1386  if (slen % 2 == 1)
1387  {
1388  Si [slen] = EMPTY ;
1389  }
1390 
1391  Slen [k - nfound] = slen ;
1392  PR2 ((Common->file, "Slen ["ID"] = "ID"\n", k - nfound, Slen [k - nfound]));
1393  snz += slen ;
1394  sp += ((slen + 1) / 2) ;
1395  Sx = (double *) (S + sp) ;
1396  sp += slen ;
1397 
1398  /* ------------------------------------------------------------------ */
1399  /* gather X into S and clear X */
1400  /* ------------------------------------------------------------------ */
1401 
1402  PR2 ((Common->file, "snz so far: "ID". Final col of S(:,"ID")=\n", snz, k));
1403  for (p = 0 ; p < slen ; p++)
1404  {
1405  i = Si [p] + nfound ;
1406  Sx [p] = X [i] ;
1407  X [i] = 0 ;
1408  PR3 ((Common->file, " S("ID","ID") = %g\n", i-nfound, k-nfound, Sx[p]));
1409  }
1410  DEBUG (for (i = 0 ; i < n ; i++) ASSERT (X [i] == 0)) ;
1411 
1412  /* clear the flag array */
1413  mark++ ;
1414  }
1415 
1416  /* ---------------------------------------------------------------------- */
1417  /* shrink the Schur complement to just the required size */
1418  /* ---------------------------------------------------------------------- */
1419 
1420  PR0 ((Common->file, "Final ssize = "ID" sn = "ID" snz: "ID"\n", sp, sn, snz)) ;
1421  S = CHOLMOD (realloc) (sp, sizeof (double), S, &ssize, cm) ;
1422  LUnode->sx = S ;
1423  LUnode->PK_SNZ = snz ;
1424  LUnode->PK_SSIZE = ssize ;
1425 
1426  return (TRUE) ;
1427 }
static void prune(Int npiv, Int Lprune[], Int Pinv[], Int k, Int pivrow, double *LU, Int Uip[], Int Lip[], Int Ulen[], Int Llen[])
static void construct_column(Int kcol, Int Ap[], Int Ai[], double Ax[], Int phase1, Int nfound, Int npiv, Int Pinv[], double X[])
#define EMPTY
#define Int
#define FALSE
#define PR0(params)
#define P(k)
#define PARAKLETE_ERROR(status, message)
#define CHOLMOD(name)
static Int debug_k
#define MAX(a, b)
#define PR2(params)
#define GET_COLUMN(Ap, Anz, Aix, j, Ai, Ax, len)
#define ASSERT(expression)
#define FLIP(i)
static Int debug_npiv
#define ID
#define UNFLIP(i)
static Int debug_n
static void lsolve(Int phase1, Int nfound, Int npiv, Int n, Int k, Int kcol, Int Ap[], Int Ai[], double Ax[], double *LU, Int *lup, Int Lip[], Int Uip[], Int Llen[], Int Ulen[], Int Lphase_len[], Int Pinv[], Int Stack[], Int Lprune[], Int Pstack[], Int Flag[], Int mark, double X[])
#define PR1(params)
#define PR3(params)
#define CHOLMOD_OK
#define PK_OUT_OF_MEMORY
static Int dfs(Int npiv, Int j, Int mark, Int Pinv[], Int Llen[], Int Lip[], Int phase1, Int Stack[], Int Flag[], Int Lprune[], Int top, double LU[], Int Li[], Int *plength, Int Pstack[])
Int amesos_paraklete_kernel(cholmod_sparse *A, paraklete_node *LUnode, paraklete_common *Common)
int CHOLMOD() allocate_work(size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common)
#define DEBUG(statement)
#define MIN(a, b)
static Int debug_nfound
static void lsolve_symbolic(Int n, Int k, Int mark, Int kcol, Int Ap[], Int Ai[], Int Pinv[], Int phase1, Int nfound, Int npiv, Int Stack[], Int Flag[], Int Lprune[], Int Pstack[], double LU[], Int *plu, Int Llen[], Int Ulen[], Int Lip[], Int Uip[])
static Int lpivot(Int diagrow, Int *p_pivrow, double *p_pivot, double *p_abs_pivot, double tol_diag, double tol_offdiag, double X[], double *LU, Int Lip[], Int Llen[], Int k, Int npiv)
#define IMPLIES(p, q)
#define TRUE
static void lsolve_numeric(Int npiv, Int Pinv[], double *LU, Int Uip[], Int Lip[], Int Ulen[], Int Llen[], Int k, Int phase1, Int Lphase_len[], double X[])