Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_paraklete_reanalyze.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === paraklete_reanalyze ================================================== */
3 /* ========================================================================== */
4 
5 /* paraklete_analyze and paraklete_factorize have already been called.
6  * This function constructs a new symbolic object that includes the original
7  * fill-reducing nested dissection ordering (Cperm) and separator tree
8  * from paraklete_analyze, combined with the partial-pivoting permutation
9  * and lost-pivots from paraklete_factorize.
10  *
11  * All processes should do this, independently, since all processes have their
12  * own complete copy of the LUsymbolic object. Each process also has its own
13  * copy of LU->P and LU->Q, the final row and column permutations from
14  * paraklete_factorize.
15  *
16  * Everyone has the global P, Q, and LU->LUnode [*]->header. The assignment
17  * of rows/columns to the nodes can be finalized, to reflect the final
18  * permutation. All processes compute the new schedule.
19  *
20  * PARAKLETE version 0.3: parallel sparse LU factorization. Nov 13, 2007
21  * Copyright (C) 2007, Univ. of Florida. Author: Timothy A. Davis
22  * See License.txt for the Version 2.1 of the GNU Lesser General Public License
23  * http://www.cise.ufl.edu/research/sparse
24  */
25 
26 #include "amesos_paraklete_decl.h"
27 
29 (
30  cholmod_sparse *A, /* only root processor owns this */
32  paraklete_symbolic *LUsymbolic,
33  paraklete_common *Common
34 )
35 {
36  paraklete_symbolic *LUsymbolic_new ;
37  Int *Cparent, *Cstart, *Cn, *Cmember, *Pmember, *P, *Q, *Cnz, *Ap, *Ai ;
38  Int i, j, k, c, n, ncomponents, jold, iold, parent, nparent, ci, cj, p ;
39 
40  /* TODO check inputs to make sure they are not NULL */
41 
42  /* ---------------------------------------------------------------------- */
43  /* allocate the new symbolic object */
44  /* ---------------------------------------------------------------------- */
45 
46  n = LUsymbolic->n ;
47  ncomponents = LUsymbolic->ncomponents ;
48  LUsymbolic_new = amesos_paraklete_alloc_symbolic (n, ncomponents, TRUE, Common) ;
49 
50  /* TODO check for out-of-memory here */
51 
52  /* ---------------------------------------------------------------------- */
53  /* copy the parts of the separator tree that do not change with pivoting */
54  /* ---------------------------------------------------------------------- */
55 
56  for (c = 0 ; c < ncomponents ; c++)
57  {
58  LUsymbolic_new->Child [c] = LUsymbolic->Child [c] ;
59  }
60 
61  for (c = 0 ; c <= ncomponents ; c++)
62  {
63  LUsymbolic_new->Childp [c] = LUsymbolic->Childp [c] ;
64  }
65 
66  for (c = 0 ; c < ncomponents ; c++)
67  {
68  LUsymbolic_new->Sched [c] = LUsymbolic->Sched [c] ;
69  }
70 
71  Cparent = LUsymbolic_new->Cparent ;
72  for (c = 0 ; c < ncomponents ; c++)
73  {
74  Cparent [c] = LUsymbolic->Cparent [c] ;
75  }
76 
77  /* ---------------------------------------------------------------------- */
78  /* determine actual number of entries in LU factors at each node */
79  /* ---------------------------------------------------------------------- */
80 
81  for (c = 0 ; c < ncomponents ; c++)
82  {
83  LUsymbolic_new->Clnz [c] = LU->LUnode [c]->lnz + LU->LUnode [c]->unz ;
84  }
85 
86  /* ---------------------------------------------------------------------- */
87  /* find the range of nodes in P*A*Q assigned to each node */
88  /* ---------------------------------------------------------------------- */
89 
90  Cstart = LUsymbolic_new->Cstart ;
91  Cstart [0] = 0 ;
92  for (c = 0 ; c < ncomponents ; c++)
93  {
94  Cstart [c+1] = Cstart [c] + LU->LUnode [c]-> PK_NFOUND ;
95  }
96 
97  /*
98  if (Common->myid == 0)
99  for (c = 0 ; c <= ncomponents ; c++)
100  printf ("new Cstart "ID"\n", Cstart [c]) ;
101  */
102 
103  /* ---------------------------------------------------------------------- */
104  /* find size of C matrix at each node (all pivoting accounted for) */
105  /* ---------------------------------------------------------------------- */
106 
107  Cn = LUsymbolic_new->Cn ;
108  for (c = ncomponents - 1 ; c >= 0 ; c--)
109  {
110  parent = Cparent [c] ;
111  nparent = (parent == EMPTY) ? 0 : Cn [parent] ;
112  Cn [c] = (Cstart [c+1] - Cstart [c]) + nparent ;
113  PR1 ((Common->file, "node "ID" new Cn: "ID"\n", c, Cn [c])) ;
114  }
115 
116  /* ---------------------------------------------------------------------- */
117  /* determine Cnz for each node */
118  /* ---------------------------------------------------------------------- */
119 
120  Cmember = LUsymbolic_new->Cperm ; /* use Cperm as workspace */
121  Pmember = LUsymbolic_new->Rperm ; /* use Rperm as workspace */
122 
123  Cnz = LUsymbolic_new->Cnz ; /* new nonzero count for each node */
124  Q = LU->Q ; /* final column ordering, P*A*Q=L*U */
125  P = LU->P ; /* final row ordering */
126 
127  if (Common->myid == 0)
128  {
129  for (c = 0 ; c < ncomponents ; c++)
130  {
131  Cnz [c] = 0 ;
132  }
133 
134  /* Cmember [k] = c if the kth diagonal entry of P*A*Q is in node c */
135  for (c = 0 ; c < ncomponents ; c++)
136  {
137  for (k = Cstart [c] ; k < Cstart [c+1] ; k++)
138  {
139  Cmember [k] = c ;
140  }
141  }
142 
143  /*
144  for (k = 0 ; k < n ; k++)
145  {
146  printf ("Cmember ["ID"] = "ID"\n", k, Cmember [k]) ;
147  }
148  for (k = 0 ; k < n ; k++)
149  {
150  printf ("P ["ID"] = "ID"\n", k, P [k]) ;
151  }
152  */
153 
154  /* Pmember [i] = c if A(i,i) becomes a pivot in node c */
155  for (k = 0 ; k < n ; k++)
156  {
157  i = P [k] ; /* kth row of P*A*Q is ith row of A */
158  c = Cmember [k] ; /* kth row of P*A*Q is in node c */
159  Pmember [i] = c ; /* A(i,i) becomes (P*A*Q)_kk, in node c */
160  }
161 
162  /*
163  for (i = 0 ; i < n ; i++)
164  {
165  printf ("Pmember ["ID"] = "ID"\n", i, Pmember [i]) ;
166  }
167  */
168 
169  /* count the entries in each node */
170  Ap = A->p ;
171  Ai = A->i ;
172  for (j = 0 ; j < n ; j++)
173  {
174  jold = Q [j] ; /* jth column of P*A*Q is column jold of A */
175  cj = Cmember [j] ; /* jth diagonal entry of P*A*Q in node cj */
176  for (p = Ap [jold] ; p < Ap [jold+1] ; p++)
177  {
178  iold = Ai [p] ; /* A(iold,jold) in original matrix */
179  ci = Pmember [iold] ; /* A(iold,iold) in node ci */
180  c = MIN (ci, cj) ; /* determine node of (P*A*Q)_ij */
181 
182  /*
183  printf ("A("ID","ID") PAQ("ID","ID") ci "ID" cj "ID" c "ID"\n",
184  iold, jold, Ai [p], j, ci, cj, c) ;
185  */
186  Cnz [c]++ ;
187  }
188  }
189 
190  /*
191  for (c = 0 ; c < ncomponents ; c++)
192  {
193  printf ("component "ID"\n", c) ;
194  printf (" new Cn "ID" Cnz "ID" Cstart "ID"\n",
195  Cn [c], Cnz [c], Cstart [c]) ;
196  }
197  */
198 
199  }
200 
201  /* Cmember and Pmember workspace no longer needed */
202 
203  /* broadcast results to all processors */
204  MPI (MPI_Bcast (Cnz, ncomponents, MPI_Int, TAG0, MPI_COMM_WORLD)) ;
205 
206  /* ---------------------------------------------------------------------- */
207  /* copy the final P and Q */
208  /* ---------------------------------------------------------------------- */
209 
210  /* column permutation Q */
211  for (k = 0 ; k < n ; k++)
212  {
213  LUsymbolic_new->Cperm [k] = Q [k] ;
214  }
215 
216  /* row permutation P and its inverse */
217  for (k = 0 ; k < n ; k++)
218  {
219  i = P [k] ;
220  LUsymbolic_new->RpermInv [i] = k ;
221  LUsymbolic_new->Rperm [k] = i ;
222  }
223 
224  return (LUsymbolic_new) ;
225 }
#define TAG0
#define MPI_Int
paraklete_symbolic * amesos_paraklete_reanalyze(cholmod_sparse *A, paraklete_numeric *LU, paraklete_symbolic *LUsymbolic, paraklete_common *Common)
#define EMPTY
#define Int
#define P(k)
#define PK_NFOUND
#define ID
paraklete_symbolic * amesos_paraklete_alloc_symbolic(Int n, Int ncomponents, Int do_Rperm, paraklete_common *Common)
#define PR1(params)
#define MPI(statement)
#define MIN(a, b)
int n
#define TRUE