Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_paraklete_btf.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Paraklete/paraklete_btf.c ============================================ */
3 /* ========================================================================== */
4 
5 /* User-callable functions that combine the functions of Paraklete,
6  * KLU, and BTF. See pb.c for examples on how to use these functions.
7  *
8  * PARAKLETE version 0.3: parallel sparse LU factorization. Nov 13, 2007
9  * Copyright (C) 2007, Univ. of Florida. Author: Timothy A. Davis
10  */
11 
12 #include "amesos_paraklete_decl.h"
13 
14 /* ========================================================================== */
15 /* === paraklete_btf_bcast_symbolic ========================================= */
16 /* ========================================================================== */
17 
18 #ifndef NMPI
20 (
21  paraklete_btf_symbolic **LU_btf_symbolic_handle,
22  paraklete_common *Common
23 )
24 {
25  paraklete_btf_symbolic *LU_btf_symbolic = NULL ;
26  Int n, nblocks, header [4] ;
27  int ok, all_ok ;
28  cholmod_common *cm ;
29  KLU_common *km ;
30 
31  cm = &(Common->cm) ;
32  km = &(Common->km) ;
33 
34  n = EMPTY ;
35  nblocks = EMPTY ;
36 
37  /* broadcast number of diagonal blocks in the BTF form, or -1 if failure */
38  if (Common->myid == 0)
39  {
40  LU_btf_symbolic = *LU_btf_symbolic_handle ;
41  if (LU_btf_symbolic != NULL)
42  {
43  n = LU_btf_symbolic->n ;
44  nblocks = LU_btf_symbolic->nblocks ;
45  }
46  }
47  else
48  {
49  /* other processes do not yet have the BTF symbolic object */
50  *LU_btf_symbolic_handle = NULL ;
51  }
52 
53  /* broadcast the size of the object, or -1 if a failure occurred */
54  header [0] = n ;
55  header [1] = nblocks ;
56  MPI (MPI_Bcast (&header, 2, MPI_Int, TAG0, MPI_COMM_WORLD)) ;
57  n = header [0] ;
58  nblocks = header [1] ;
59  if (n == EMPTY)
60  {
61  return (FALSE) ;
62  }
63 
64  if (Common->myid != 0)
65  {
66  /* allocate the copy of this analysis on the slave */
67  LU_btf_symbolic = amesos_paraklete_btf_alloc_symbolic (n, nblocks, Common) ;
68  *LU_btf_symbolic_handle = LU_btf_symbolic ;
69  /* TODO return if failed, and broadcast error to all processes */
70  /* PARAKLETE_ERROR already called */
71  }
72 
73  /* all processes find out if any one process fails to allocate memory */
74  ok = (cm->status == CHOLMOD_OK) && (LU_btf_symbolic != NULL) ;
75  all_ok = ok ;
76  MPI (MPI_Allreduce (&ok, &all_ok, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD)) ;
77  if (!all_ok)
78  {
79  /* out of memory; inform all processes */
80  PR0 ((Common->file, "proc "ID" all fail in analyze\n", Common->myid)) ;
81  amesos_paraklete_btf_free_symbolic (&LU_btf_symbolic, Common) ;
82  *LU_btf_symbolic_handle = NULL ;
83  return (FALSE) ;
84  }
85 
86  /* broadcast the contents of the LU_btf_symbolic object (excluding
87  * the LUsymbolic analysis of each diagonal block) */
88  MPI (MPI_Bcast (LU_btf_symbolic->Mem_n, 3*n+1, MPI_Int, TAG0,
89  MPI_COMM_WORLD)) ;
90  return (TRUE) ;
91 }
92 #endif
93 
94 
95 /* ========================================================================== */
96 /* === paraklete_btf_alloc_symbolic ========================================= */
97 /* ========================================================================== */
98 
100 (
101  Int n,
102  Int nblocks,
103  paraklete_common *Common
104 )
105 {
106  cholmod_common *cm ;
107  KLU_common *km ;
108  paraklete_btf_symbolic *LU_btf_symbolic ;
109  Int *p ;
110  int ok = TRUE ;
111  size_t n3 ;
112 
113  cm = &(Common->cm) ;
114  km = &(Common->km) ;
115 
116  /* n3 = 3*n+1 */
117  n3 = CHOLMOD (mult_size_t) (n, 3, &ok) ;
118  n3 = CHOLMOD (add_size_t) (n3, 1, &ok) ;
119  if (!ok) PARAKLETE_ERROR (PK_TOO_LARGE, "problem too large") ;
120 
121  LU_btf_symbolic = CHOLMOD (malloc) (1, sizeof (paraklete_btf_symbolic), cm) ;
122  if (cm->status != CHOLMOD_OK)
123  {
124  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
125  return (NULL) ;
126  }
127 
128  LU_btf_symbolic->n = n ;
129  LU_btf_symbolic->nblocks = nblocks ;
130  LU_btf_symbolic->cnz = 0 ;
131  LU_btf_symbolic->fnz = 0 ;
132  p = LU_btf_symbolic->Mem_n = CHOLMOD (calloc) (n3, sizeof (Int), cm) ;
133  LU_btf_symbolic->Qbtf = p ; /* size n */
134  LU_btf_symbolic->Pbinv = p + n ; /* size n */
135  LU_btf_symbolic->Rbtf = p + 2*n ; /* size n+1 */
136  /* only nblocks of the LUsymbolic array is used: */
137  LU_btf_symbolic->LUsymbolic = CHOLMOD (calloc) (n, sizeof (void *), cm) ;
138 
139  if (cm->status != CHOLMOD_OK)
140  {
141  /* TODO free object and return NULL if malloc fails */
142  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
143  }
144  return (LU_btf_symbolic) ;
145 }
146 
147 
148 /* ========================================================================== */
149 /* === paraklete_btf_analyze ================================================ */
150 /* ========================================================================== */
151 
153 (
154  cholmod_sparse *A, /* matrix to analyze */
155  paraklete_common *Common
156 )
157 {
158  double work = 0 ;
159  Int *Pbtf = NULL, *Qbtf = NULL, *Rbtf = NULL, *Work = NULL, *Ap = NULL,
160  *Ai = NULL, *Cp = NULL, *Ci = NULL, *Pbinv = NULL ;
161  cholmod_sparse *C = NULL ;
162  cholmod_common *cm ;
163  KLU_common *km ;
164  paraklete_btf_symbolic *LU_btf_symbolic = NULL ;
165  void **LUsymbolic ;
166  Int nblocks, n = 0, nmatch, block, k, k1, k2, inew, jold, anz = 0, fnz,
167  cnz, p, nk ;
168 
169  /* ---------------------------------------------------------------------- */
170  /* root processor finds the BTF ordering */
171  /* ---------------------------------------------------------------------- */
172 
173  cm = &(Common->cm) ;
174  km = &(Common->km) ;
175 
176  if (Common->myid == 0)
177  {
178  Ap = A->p ;
179  Ai = A->i ;
180  n = A->nrow ;
181  anz = Ap [n] ;
182 
183  LU_btf_symbolic = amesos_paraklete_btf_alloc_symbolic (n, n, Common) ;
184  if (LU_btf_symbolic == NULL)
185  {
186  /* TODO return NULL if malloc fails */
187  /* PARAKLETE_ERROR already called */ ;
188  }
189 
190  Qbtf = LU_btf_symbolic->Qbtf ; /* size n */
191  Rbtf = LU_btf_symbolic->Rbtf ; /* size n+1 */
192  Pbinv = LU_btf_symbolic->Pbinv ; /* size n */
193  LUsymbolic = LU_btf_symbolic->LUsymbolic ; /* size n */
194 
195  /* ------------------------------------------------------------------ */
196  /* find the BTF ordering */
197  /* ------------------------------------------------------------------ */
198 
199  Work = CHOLMOD (malloc) (n, 6*sizeof (Int), cm) ;
200  Pbtf = Work + 5*n ;
201  if (cm->status != CHOLMOD_OK)
202  {
203  /* TODO return if malloc fails */
204  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
205  }
206 
207  nblocks = BTF_order (n, Ap, Ai, 0, &work, Pbtf, Qbtf, Rbtf, &nmatch,
208  Work) ;
209 
210  /* Pbinv = inverse of Pbtf */
211  for (k = 0 ; k < n ; k++)
212  {
213  Pbinv [Pbtf [k]] = k ;
214  }
215 
216  CHOLMOD (free) (n, 6*sizeof (Int), Work, cm) ;
217  LU_btf_symbolic->nblocks = nblocks ;
218  }
219 
220  /* ---------------------------------------------------------------------- */
221  /* broadcast the BTF information */
222  /* ---------------------------------------------------------------------- */
223 
224  MPI (paraklete_btf_bcast_symbolic (&LU_btf_symbolic, Common)) ;
225  /* TODO return if broadcast fails */
226  Rbtf = LU_btf_symbolic->Rbtf ;
227  LUsymbolic = LU_btf_symbolic->LUsymbolic ;
228  nblocks = LU_btf_symbolic->nblocks ;
229 
230  /* ---------------------------------------------------------------------- */
231  /* symbolic analysis of diagonal blocks of A(p,q) */
232  /* ---------------------------------------------------------------------- */
233 
234  if (Common->myid == 0)
235  {
236  /* C = empty n-by-n sparse matrix */
237  fnz = 0 ;
238  C = CHOLMOD (allocate_sparse) (n, n, anz, FALSE, TRUE, 0, CHOLMOD_PATTERN,
239  cm) ;
240  if (cm->status != CHOLMOD_OK)
241  {
242  /* TODO return if malloc fails */
243  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
244  }
245  Cp = C->p ;
246  Ci = C->i ;
247  LU_btf_symbolic->cnz = 0 ;
248  }
249 
250  for (block = 0 ; block < nblocks ; block++)
251  {
252  k1 = Rbtf [block] ;
253  k2 = Rbtf [block+1] ;
254  nk = k2 - k1 ;
255 
256  if (Common->myid == 0)
257  {
258  cnz = 0 ;
259  for (k = k1 ; k < k2 ; k++)
260  {
261  Cp [k - k1] = cnz ; /* note change of index */
262  jold = Qbtf [k] ;
263  for (p = Ap [jold] ; p < Ap [jold+1] ; p++)
264  {
265  inew = Pbinv [Ai [p]] ;
266  if (inew < k1)
267  {
268  /* this entry goes in the off-diagonal part */
269  fnz++ ;
270  }
271  else
272  {
273  /* this entry goes in the diagonal block */
274  Ci [cnz++] = inew - k1 ; /* note the change of index */
275  }
276  }
277  }
278  LU_btf_symbolic->cnz = MAX (LU_btf_symbolic->cnz, cnz) ;
279  Cp [nk] = cnz ;
280  C->nrow = nk ;
281  C->ncol = nk ;
282  }
283 
284  if (nk == 1)
285  {
286  /* singleton; nothing to do */
287  LUsymbolic [block] = NULL ;
288  }
289  else if (nk < 1000)
290  {
291  if (Common->myid == 0)
292  {
293  /* use KLU on process 0 */
294  LUsymbolic [block] = (void *) KLU_analyze (nk, Cp, Ci, km) ;
295  if (km->status != KLU_OK)
296  {
297  /* TODO return if KLU_analyze failed; broadcast the error */
298  PARAKLETE_ERROR (PK_UNKNOWN, "KLU analyze failed") ;
299  }
300  }
301  else
302  {
303  /* small block; nothing to do for other processors*/
304  LUsymbolic [block] = NULL ;
305  }
306  }
307  else
308  {
309  /* parallel factorization of a large block */
310  /* process 0 does the work and broadcasts it to all the others */
311  LUsymbolic [block] = (void *) amesos_paraklete_analyze (C, Common) ;
312  if (LUsymbolic [block] == NULL)
313  {
314  /* TODO return if analyze fails and broadcast the error */
315  /* note that PARAKLETE_ERROR has already been called */
316  }
317  }
318  }
319 
320  /* ---------------------------------------------------------------------- */
321  /* free workspace sparse matrix C */
322  /* ---------------------------------------------------------------------- */
323 
324  if (Common->myid == 0)
325  {
326  /* process 0 finalizes the object and frees its workspace */
327  LU_btf_symbolic->fnz = fnz ;
328  C->nrow = n ;
329  C->ncol = n ;
330  CHOLMOD (free_sparse) (&C, cm) ;
331  }
332 
333  /* ---------------------------------------------------------------------- */
334  /* return the result */
335  /* ---------------------------------------------------------------------- */
336 
337  return (LU_btf_symbolic) ;
338 }
339 
340 
341 /* ========================================================================== */
342 /* === paraklete_btf_factorize ============================================== */
343 /* ========================================================================== */
344 
346 (
347  cholmod_sparse *A, /* matrix to analyze */
348  paraklete_btf_symbolic *LU_btf_symbolic, /* symbolic analysis */
349  paraklete_common *Common
350 )
351 {
352  cholmod_sparse *F = NULL, *C = NULL ;
353  cholmod_common *cm ;
354  KLU_common *km ;
355  double *Ax = NULL, *Cx = NULL, *Fx = NULL, *Singleton = NULL ;
356  Int *Qbtf = NULL, *Rbtf = NULL, *Ap = NULL, *Ai = NULL, *Cp = NULL,
357  *Ci = NULL, *Pbinv = NULL, *Fp = NULL, *Fi = NULL ;
358  Int fnz = 0, cnz = 0, nblocks, n, k, k1, k2, block, jold, inew, p, nk ;
359  int ok = TRUE, all_ok ;
360  void **LUsymbolic = NULL;
361  paraklete_btf_numeric *LU_btf_numeric = NULL ;
362  void **LUnumeric = NULL ;
363 
364  /* ---------------------------------------------------------------------- */
365  /* get inputs and allocate result */
366  /* ---------------------------------------------------------------------- */
367 
368  cm = &(Common->cm) ;
369  km = &(Common->km) ;
370 
371  LU_btf_numeric = CHOLMOD (malloc) (1, sizeof (paraklete_btf_numeric), cm) ;
372  if (cm->status != CHOLMOD_OK)
373  {
374  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
375  return (NULL) ;
376  }
377 
378  if (Common->myid == 0)
379  {
380  fnz = LU_btf_symbolic->fnz ;
381  cnz = LU_btf_symbolic->cnz ;
382  n = A->nrow ;
383  F = CHOLMOD (allocate_sparse) (n, n, fnz, FALSE, TRUE, 0,
384  CHOLMOD_REAL, cm) ;
385  C = CHOLMOD (allocate_sparse) (n, n, cnz, FALSE, TRUE, 0,
386  CHOLMOD_REAL, cm) ;
387  if (cm->status != CHOLMOD_OK)
388  {
389  /* TODO free LU_btf_numeric and return NULL;
390  * broadcast error to all processes */
391  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
392  }
393  }
394 
395  n = LU_btf_symbolic->n ;
396  nblocks = LU_btf_symbolic->nblocks ;
397  Rbtf = LU_btf_symbolic->Rbtf ;
398  Qbtf = LU_btf_symbolic->Qbtf ;
399  Pbinv = LU_btf_symbolic->Pbinv ;
400  LUsymbolic = LU_btf_symbolic->LUsymbolic ;
401 
402  if (Common->myid == 0)
403  {
404  fnz = 0 ;
405  Fp = F->p ;
406  Fi = F->i ;
407  Fx = F->x ;
408  Ap = A->p ;
409  Ai = A->i ;
410  Ax = A->x ;
411  Cp = C->p ;
412  Ci = C->i ;
413  Cx = C->x ;
414  Singleton = CHOLMOD (calloc) (nblocks, sizeof (double), cm) ;
415  if (cm->status != CHOLMOD_OK)
416  {
417  /* TODO free LU_btf_numeric and return NULL;
418  * broadcast error to all processes */
419  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
420  }
421  }
422 
423  /* all processes do this */
424  LU_btf_numeric->Singleton = Singleton ;
425  LU_btf_numeric->LUnumeric = LUnumeric =
426  CHOLMOD (calloc) (nblocks, sizeof (void *), cm) ;
427  LU_btf_numeric->F = F ;
428  LU_btf_numeric->nblocks = nblocks ;
429 
430  if (cm->status != CHOLMOD_OK)
431  {
432  /* TODO free LU_btf_numeric and return NULL;
433  * broadcast error to all processes */
434  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
435  }
436 
437  /* ---------------------------------------------------------------------- */
438  /* factorize each diagonal block, and construct F */
439  /* ---------------------------------------------------------------------- */
440 
441  for (block = 0 ; block < nblocks ; block++)
442  {
443  k1 = Rbtf [block] ;
444  k2 = Rbtf [block+1] ;
445  nk = k2 - k1 ;
446 
447  if (Common->myid == 0)
448  {
449  cnz = 0 ;
450  for (k = k1 ; k < k2 ; k++)
451  {
452  Fp [k] = fnz ;
453  Cp [k - k1] = cnz ; /* note change of index */
454  jold = Qbtf [k] ;
455  for (p = Ap [jold] ; p < Ap [jold+1] ; p++)
456  {
457  inew = Pbinv [Ai [p]] ;
458  if (inew < k1)
459  {
460  /* this entry goes in the off-diagonal part */
461  Fi [fnz] = inew ;
462  Fx [fnz] = Ax [p] ;
463  fnz++ ;
464  }
465  else
466  {
467  /* this entry goes in the diagonal block */
468  Ci [cnz] = inew - k1 ; /* note the change of index */
469  Cx [cnz] = Ax [p] ;
470  cnz++ ;
471  }
472  }
473  }
474  Cp [nk] = cnz ;
475  C->nrow = nk ;
476  C->ncol = nk ;
477  }
478 
479  if (nk == 1)
480  {
481  /* singleton */
482  if (Common->myid == 0)
483  {
484  Singleton [block] = Cx [0] ;
485  }
486  LUnumeric [block] = NULL ;
487  }
488  else if (nk < 1000)
489  {
490  if (Common->myid == 0)
491  {
492  /* use KLU on process 0 */
493  LUnumeric [block] = (void *) KLU_factor (Cp, Ci, Cx,
494  (KLU_symbolic *) LUsymbolic [block], km) ;
495  if (km->status != KLU_OK)
496  {
497  /* TODO return if KLU failed; broadcast the error */
498  PARAKLETE_ERROR (PK_UNKNOWN, "KLU factorize failed") ;
499  ok = FALSE ;
500  }
501  }
502  else
503  {
504  /* small block; nothing to do for other processors */
505  LUnumeric [block] = NULL ;
506  }
507  }
508  else
509  {
510  /* parallel factorization of a large block */
511  LUnumeric [block] = (void *) amesos_paraklete_factorize (C,
512  (paraklete_symbolic *) LUsymbolic [block], Common) ;
513  if (LUnumeric [block] == NULL)
514  {
515  /* PARAKLETE failed */
516  ok = FALSE ;
517  }
518  }
519  }
520 
521  if (Common->myid == 0)
522  {
523  /* process 0 frees its workspace */
524  Fp [n] = fnz ;
525  C->nrow = n ;
526  C->ncol = n ;
527  CHOLMOD (free_sparse) (&C, cm) ;
528  }
529 
530  /* all processes find out if any one process fails */
531  all_ok = ok ;
532  MPI (MPI_Allreduce (&ok, &all_ok, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD)) ;
533  if (!all_ok)
534  {
535  /* one of the blocks failed; all processes free result */
536  amesos_paraklete_btf_free_numeric (&LU_btf_numeric, Common) ;
537  }
538  return (LU_btf_numeric) ;
539 }
540 
541 
542 /* ========================================================================== */
543 /* === paraklete_btf_solve ================================================== */
544 /* ========================================================================== */
545 
546 Int amesos_paraklete_btf_solve /* TRUE if OK, FALSE otherwise */
547 (
548  paraklete_btf_numeric *LU_btf_numeric, /* numeric factorization */
549  paraklete_btf_symbolic *LU_btf_symbolic, /* symbolic analysis */
550  double *B, /* right-hand-side; soln on output */
551  paraklete_common *Common
552 )
553 {
554  double wk ;
555  cholmod_common *cm ;
556  KLU_common *km ;
557  cholmod_sparse *F ;
558  void **LUsymbolic ;
559  void **LUnumeric ;
560  double *Fx = NULL, *W = NULL, *Singleton ;
561  Int *Qbtf, *Pbinv, *Rbtf, *Fp = NULL, *Fi = NULL ;
562  Int iold, n, jnew, k, k1, k2, nk, p, nblocks, block ;
563 
564  /* ---------------------------------------------------------------------- */
565  /* get inputs and allocate workspace */
566  /* ---------------------------------------------------------------------- */
567 
568  cm = &(Common->cm) ;
569  km = &(Common->km) ;
570 
571  nblocks = LU_btf_symbolic->nblocks ;
572  n = LU_btf_symbolic->n ;
573  Rbtf = LU_btf_symbolic->Rbtf ;
574  Qbtf = LU_btf_symbolic->Qbtf ;
575  Pbinv = LU_btf_symbolic->Pbinv ;
576  LUsymbolic = LU_btf_symbolic->LUsymbolic ;
577  LUnumeric = LU_btf_numeric->LUnumeric ;
578  Singleton = LU_btf_numeric->Singleton ;
579  F = LU_btf_numeric->F ;
580  if (Common->myid == 0)
581  {
582  /* only the master process has the off-diagonal blocks F */
583  Fp = F->p ;
584  Fi = F->i ;
585  Fx = F->x ;
586  }
587 
588  /* ---------------------------------------------------------------------- */
589  /* permute right-hand side; W = Pbtf*B */
590  /* ---------------------------------------------------------------------- */
591 
592  if (Common->myid == 0)
593  {
594  /* only the master process does this */
595  W = CHOLMOD (malloc) (n, sizeof (double), cm) ;
596  if (cm->status != CHOLMOD_OK)
597  {
598  /* TODO return NULL, and broadcast error to all processes */
599  PARAKLETE_ERROR (PK_OUT_OF_MEMORY, "out of memory") ;
600  }
601  for (iold = 0 ; iold < n ; iold++)
602  {
603  W [Pbinv [iold]] = B [iold] ;
604  }
605  }
606 
607  /* ---------------------------------------------------------------------- */
608  /* block backsolve */
609  /* ---------------------------------------------------------------------- */
610 
611  for (block = nblocks-1 ; block >= 0 ; block--)
612  {
613  k1 = Rbtf [block] ;
614  k2 = Rbtf [block+1] ;
615  nk = k2 - k1 ;
616  if (nk == 1)
617  {
618  /* singleton */
619  if (Common->myid == 0)
620  {
621  W [k1] /= Singleton [block] ;
622  }
623  }
624  else if (nk < 1000)
625  {
626  if (Common->myid == 0)
627  {
628  /* use KLU on process 0 */
629  KLU_solve (
630  (KLU_symbolic *) LUsymbolic [block],
631  (KLU_numeric *) LUnumeric [block], nk, 1, W+k1, km) ;
632 
633  if (km->status != KLU_OK)
634  {
635  /* TODO return NULL, and broadcast error to all processes */
636  PARAKLETE_ERROR (PK_UNKNOWN, "KLU solve failed") ;
637  }
638 
639  }
640  else
641  {
642  /* small block; nothing to do for other processors*/
643  LUnumeric [block] = NULL ;
644  }
645  }
646  else
647  {
648  /* solve the diagonal block */
650  (paraklete_numeric *) LUnumeric [block],
651  (paraklete_symbolic *) LUsymbolic [block], W+k1, Common) ;
652  /* TODO check for error here */
653  }
654  /* backsolve for off-diagonal entries */
655  if (Common->myid == 0)
656  {
657  for (k = k1 ; k < k2 ; k++)
658  {
659  wk = W [k] ;
660  for (p = Fp [k] ; p < Fp [k+1] ; p++)
661  {
662  W [Fi [p]] -= Fx [p] * wk ;
663  }
664  }
665  }
666  }
667 
668  /* ---------------------------------------------------------------------- */
669  /* permute solution; B = Qbtf'*W */
670  /* ---------------------------------------------------------------------- */
671 
672  if (Common->myid == 0)
673  {
674  for (jnew = 0 ; jnew < n ; jnew++)
675  {
676  B [Qbtf [jnew]] = W [jnew] ;
677  }
678  CHOLMOD (free) (n, sizeof (double), W, cm) ;
679  }
680 
681  return (TRUE) ;
682 }
683 
684 
685 /* ========================================================================== */
686 /* === paraklete_btf_free_symbolic ========================================== */
687 /* ========================================================================== */
688 
690 (
691  paraklete_btf_symbolic **LU_btf_symbolic_handle,
692  paraklete_common *Common
693 )
694 {
695  paraklete_btf_symbolic *LU_btf_symbolic ;
696  void **LUsymbolic ;
697  Int n, block, nblocks, k1, k2, nk, *Rbtf ;
698  cholmod_common *cm ;
699  KLU_common *km ;
700 
701  if (LU_btf_symbolic_handle == NULL)
702  {
703  return ;
704  }
705  LU_btf_symbolic = *LU_btf_symbolic_handle ;
706  if (LU_btf_symbolic == NULL)
707  {
708  *LU_btf_symbolic_handle = NULL ;
709  return ;
710  }
711  cm = &(Common->cm) ;
712  km = &(Common->km) ;
713 
714  LUsymbolic = LU_btf_symbolic->LUsymbolic ;
715  Rbtf = LU_btf_symbolic->Rbtf ;
716  n = LU_btf_symbolic->n ;
717  nblocks = LU_btf_symbolic->nblocks ;
718  for (block = 0 ; block < nblocks ; block++)
719  {
720  k2 = Rbtf [block+1] ;
721  k1 = Rbtf [block] ;
722  nk = k2 - k1 ;
723  if (nk < 1000)
724  {
725  KLU_symbolic *S ;
726  S = (KLU_symbolic *) LUsymbolic [block] ;
727  KLU_free_symbolic (&S, &(Common->km)) ;
728  }
729  else
730  {
731  paraklete_symbolic *S ;
732  S = (paraklete_symbolic *) LUsymbolic [block] ;
733  amesos_paraklete_free_symbolic (&S, Common) ;
734  }
735  LUsymbolic [block] = NULL ;
736  }
737  CHOLMOD (free) (n, sizeof (void *), LU_btf_symbolic->LUsymbolic, cm) ;
738  CHOLMOD (free) (3*n+1, sizeof (Int), LU_btf_symbolic->Mem_n, cm) ;
739  *LU_btf_symbolic_handle = CHOLMOD (free) (1, sizeof (paraklete_btf_symbolic),
740  LU_btf_symbolic, cm) ;
741 }
742 
743 
744 /* ========================================================================== */
745 /* === paraklete_btf_free_numeric =========================================== */
746 /* ========================================================================== */
747 
749 (
750  paraklete_btf_numeric **LU_btf_numeric_handle,
751  paraklete_common *Common
752 )
753 {
754  paraklete_btf_numeric *LU_btf_numeric ;
755  void **LUnumeric ;
756  Int block, nblocks ;
757  cholmod_common *cm ;
758 
759  if (LU_btf_numeric_handle == NULL)
760  {
761  return ;
762  }
763  LU_btf_numeric = *LU_btf_numeric_handle ;
764  if (LU_btf_numeric == NULL)
765  {
766  *LU_btf_numeric_handle = NULL ;
767  return ;
768  }
769  cm = &(Common->cm) ;
770 
771  LUnumeric = LU_btf_numeric->LUnumeric ;
772  nblocks = LU_btf_numeric->nblocks ;
773 
774  for (block = 0 ; block < nblocks ; block++)
775  {
777  N = (paraklete_numeric *) LUnumeric [block] ;
778  if (N != NULL)
779  {
780  if (N->magic == PARAKLETE_MAGIC)
781  {
782  /* this block was factorized with Paraklete */
783  amesos_paraklete_free_numeric (&N, Common) ;
784  }
785  else
786  {
787  /* this block was factorized with KLU */
788  KLU_numeric *K ;
789  K = (KLU_numeric *) LUnumeric [block] ;
790  KLU_free_numeric (&K, &(Common->km)) ;
791  }
792  }
793  LUnumeric [block] = NULL ;
794  }
795 
796  CHOLMOD (free) (nblocks, sizeof (double), LU_btf_numeric->Singleton, cm) ;
797  CHOLMOD (free) (nblocks, sizeof (void *), LUnumeric, cm) ;
798  CHOLMOD (free_sparse) (&(LU_btf_numeric->F), cm) ;
799 
800  *LU_btf_numeric_handle = CHOLMOD (free) (1, sizeof (paraklete_btf_numeric),
801  LU_btf_numeric, cm) ;
802 }
#define TAG0
struct paraklete_btf_numeric_struct paraklete_btf_numeric
#define MPI_Int
paraklete_btf_symbolic * amesos_paraklete_btf_analyze(cholmod_sparse *A, paraklete_common *Common)
#define EMPTY
#define KLU_symbolic
#define Int
size_t CHOLMOD() add_size_t(size_t a, size_t b, int *ok)
#define FALSE
#define KLU_analyze
#define PR0(params)
size_t CHOLMOD() mult_size_t(size_t a, size_t k, int *ok)
#define KLU_factor
#define PARAKLETE_ERROR(status, message)
paraklete_btf_numeric * amesos_paraklete_btf_factorize(cholmod_sparse *A, paraklete_btf_symbolic *LU_btf_symbolic, paraklete_common *Common)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
void amesos_paraklete_free_numeric(paraklete_numeric **LUHandle, paraklete_common *Common)
#define MAX(a, b)
#define PK_TOO_LARGE
paraklete_btf_symbolic * amesos_paraklete_btf_alloc_symbolic(Int n, Int nblocks, paraklete_common *Common)
int CHOLMOD() free_sparse(cholmod_sparse **AHandle, cholmod_common *Common)
#define CHOLMOD_REAL
#define NULL
const int N
#define KLU_free_numeric
struct paraklete_btf_symbolic_struct paraklete_btf_symbolic
#define ID
#define KLU_numeric
Int amesos_paraklete_solve(paraklete_numeric *LU, paraklete_symbolic *LUsymbolic, double *B, paraklete_common *Common)
Int amesos_paraklete_btf_solve(paraklete_btf_numeric *LU_btf_numeric, paraklete_btf_symbolic *LU_btf_symbolic, double *B, paraklete_common *Common)
#define KLU_free_symbolic
#define CHOLMOD_OK
#define KLU_solve
void amesos_paraklete_free_symbolic(paraklete_symbolic **LUsymbolicHandle, paraklete_common *Common)
#define PK_OUT_OF_MEMORY
#define MPI(statement)
void amesos_paraklete_btf_free_symbolic(paraklete_btf_symbolic **LU_btf_symbolic_handle, paraklete_common *Common)
cholmod_sparse *CHOLMOD() allocate_sparse(size_t nrow, size_t ncol, size_t nzmax, int sorted, int packed, int stype, int xtype, cholmod_common *Common)
void amesos_paraklete_btf_free_numeric(paraklete_btf_numeric **LU_btf_numeric_handle, paraklete_common *Common)
#define KLU_common
#define PARAKLETE_MAGIC
paraklete_symbolic * amesos_paraklete_analyze(cholmod_sparse *A, paraklete_common *Common)
static Int paraklete_btf_bcast_symbolic(paraklete_btf_symbolic **LU_btf_symbolic_handle, paraklete_common *Common)
#define BTF_order
int n
#define TRUE
#define KLU_OK
paraklete_numeric * amesos_paraklete_factorize(cholmod_sparse *A, paraklete_symbolic *LUsymbolic, paraklete_common *Common)
#define PK_UNKNOWN