Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_paraklete_lsolve_node.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === paraklete_lsolve_node ================================================ */
3 /* ========================================================================== */
4 
6 
7 /* Solve Lx=b with node c of the separator tree.
8  *
9  * PARAKLETE version 0.3: parallel sparse LU factorization. Nov 13, 2007
10  * Copyright (C) 2007, Univ. of Florida. Author: Timothy A. Davis
11  * See License.txt for the Version 2.1 of the GNU Lesser General Public License
12  * http://www.cise.ufl.edu/research/sparse
13  */
14 
16 (
17  Int c,
19  paraklete_symbolic *LUsymbolic,
20  paraklete_common *Common
21 )
22 
23 {
24  double xj ;
25  paraklete_node *LUnode ;
26  cholmod_common *cm ;
27  double *X, *B, *LUix, *Xchild, *Lx ;
28  Int *Child, *Childp, *Lost, *Lostp, *Cstart, *Lip, *Llen,
29  *Cn, *Pinv, *Li, *Cparent, *Sched ;
30  Int cp, nchild, child, cn, k, j, p, i, nfound, k1, k2, llen,
31  ci, nlost_in, cn_child, cn_nfound, parent, myid, pass ;
32  MPI (MPI_Status ms) ;
33  MPI (MPI_Request req) ;
34 
35  /* ---------------------------------------------------------------------- */
36  /* get local workspace */
37  /* ---------------------------------------------------------------------- */
38 
39  cm = &(Common->cm) ;
40  PR0 ((Common->file, "\n\n########################## Lsolve NODE "ID"\n", c)) ;
41 
42  /* ---------------------------------------------------------------------- */
43  /* get the symbolic analysis of this node */
44  /* ---------------------------------------------------------------------- */
45 
46  myid = Common->myid ;
47  Childp = LUsymbolic->Childp ; /* Child [Childp [c]..Childp[c+1]-1] */
48  Child = LUsymbolic->Child ; /* is list of children of node c */
49  nchild = Childp [c+1] - Childp [c] ; /* # of children of node c */
50  Cn = LUsymbolic->Cn ; /* dimension of each node */
51  Cstart = LUsymbolic->Cstart ;
52  Sched = LUsymbolic->Sched ;
53  Cparent = LUsymbolic->Cparent ;
54 
55  /* ---------------------------------------------------------------------- */
56  /* get factors at this node */
57  /* ---------------------------------------------------------------------- */
58 
59  LUnode = LU->LUnode [c] ;
60 
61  Lip = LUnode->lp ;
62  Llen = LUnode->llen ;
63  LUix = LUnode->ix ;
64  nfound = LUnode->PK_NFOUND ;
65 
66  nlost_in = 0 ;
67  Lost = LUnode->Lost ;
68  Lostp = LUnode->Lostp ;
69  nlost_in = LUnode->nlost_in ;
70 
71  /* The matrix factorized at this node is cn-by-cn. */
72  cn = nlost_in + Cn [c] ;
73  k1 = Cstart [c] ;
74  k2 = Cstart [c+1] ;
75 
76  Pinv = LUnode->Pinv ;
77 
78 #ifndef NDEBUG
79  {
80  Int npiv = LUnode->PK_NPIV ;
81  Int *Plocal = LUnode->Plocal ;
82  ASSERT (cn == LUnode->PK_NN) ;
83  ASSERT (npiv == nlost_in + (k2 - k1)) ;
84  for (k = 0 ; k < npiv ; k++)
85  {
86  i = Plocal [k] ;
87  ASSERT (i >= 0 && i < npiv) ;
88  ASSERT (Pinv [i] == k) ;
89  }
90  DEBUG (CHOLMOD (print_perm) (Plocal, npiv, npiv, "Plocal at node c", cm));
91  DEBUG (CHOLMOD (print_perm) (Pinv, npiv, npiv, "Pinv at node c", cm)) ;
92  }
93 #endif
94 
95  /* ---------------------------------------------------------------------- */
96  /* add up all the contributions to the right-hand-side */
97  /* ---------------------------------------------------------------------- */
98 
99  X = LU->LUnode [c]->X ;
100  PR1 ((Common->file, "Lsolve at Node "ID", cn "ID"\n", c, cn)) ;
101  for (i = 0 ; i < cn ; i++)
102  {
103  X [i] = 0 ;
104  }
105 
106  /* B [0..(k2-k1)-1] contains the right-hand-side corresponding to rows
107  * Cstart [c] to Cstart [c+1]-1 of the global system (after permuted by
108  * Cperm).
109  */
110  B = LUnode->B ;
111 
112  /* wait for B to arrive at this node */
113  MPI (MPI_Wait (&(LU->LUnode [c]->req), &ms)) ;
114 
115  for (i = 0 ; i < k2-k1 ; i++)
116  {
117  ci = i + nlost_in ;
118  k = Pinv [ci] ;
119  PR2 ((Common->file, "orig B ["ID"] = %g goes to X ["ID"]\n", i, B [i], k)) ;
120  ASSERT (k >= 0 && k < cn) ;
121  X [k] = B [i] ;
122  }
123 
124  /* scatter and add the contributions from each child */
125  for (pass = 1 ; pass <= 2 ; pass++)
126  {
127  for (cp = 0 ; cp < nchild ; cp++)
128  {
129  child = Child [Childp [c] + cp] ;
130  if (pass == 1)
131  {
132  /* do local contributions on first pass */
133  if (Sched [child] != myid) continue ;
134  }
135  else
136  {
137  /* do non-local contributions on second pass */
138  if (Sched [child] == myid) continue ;
139  MPI (MPI_Wait (&(LUnode->Req [cp]), &ms)) ;
140  }
141 
142  cn_child = LU->LUnode [child]->PK_NN ;
143  cn_nfound = LU->LUnode [child]->PK_NFOUND ;
144  Xchild = LU->LUnode [child]->X + cn_nfound ;
145 
146  PR1 ((Common->file, "child "ID" cn "ID" nfound "ID"\n",
147  child, cn_child, cn_nfound)) ;
148 
149  /* get the contributions of child to its lost pivot rows */
150  for (i = 0 ; i < Lost [cp] ; i++)
151  {
152  ci = i + Lostp [cp] ; /* ci is now "original" local index */
153  k = Pinv [ci] ; /* kth local pivot row */
154  PR2 ((Common->file, "Xchild ["ID"] = %g goes to X ["ID"] (lost)\n",
155  i, Xchild [i], k)) ;
156  ASSERT (k >= 0 && k < cn) ;
157  X [k] += Xchild [i] ;
158  }
159 
160  /* get the contributions to candidate pivot rows of node c */
161  for ( ; i < Lost [cp] + (k2-k1) ; i++)
162  {
163  ci = i + (nlost_in - Lost [cp]) ;
164  k = Pinv [ci] ; /* kth local pivot row */
165  PR2 ((Common->file, "Xchild ["ID"] = %g goes to X ["ID"] (cand)\n",
166  i, Xchild [i], k)) ;
167  ASSERT (k >= 0 && k < cn) ;
168  X [k] += Xchild [i] ;
169  }
170 
171  /* get contributions to candidate pivot rows of ancestors of c */
172  for ( ; i < cn_child - cn_nfound ; i++)
173  {
174  k = i + (nlost_in - Lost [cp]) ;
175  PR2 ((Common->file, "Xchild ["ID"] = %g goes to X ["ID"] (anc)\n",
176  i, Xchild [i], k)) ;
177  ASSERT (k >= 0 && k < cn) ;
178  X [k] += Xchild [i] ;
179  }
180  }
181  }
182 
183  /* ---------------------------------------------------------------------- */
184  /* solve Lx=b */
185  /* ---------------------------------------------------------------------- */
186 
187  for (j = 0 ; j < nfound ; j++)
188  {
189  xj = X [j] ;
190  GET_COLUMN (Lip, Llen, LUix, j, Li, Lx, llen) ;
191  for (p = 1 ; p < llen ; p++)
192  {
193  X [Li [p]] -= Lx [p] * xj ;
194  }
195  }
196 
197  /* ---------------------------------------------------------------------- */
198  /* send results to parent */
199  /* ---------------------------------------------------------------------- */
200 
201  /* X [0..nfound-1] is part of the global solution, X [nfound..nn-1] is
202  * the contribution to the parent and ancestors */
203 
204  parent = Cparent [c] ;
205  if (parent != EMPTY && Sched [parent] != myid)
206  {
207  MPI (MPI_Isend (X, cn, MPI_DOUBLE, Sched [parent], TAG0, MPI_COMM_WORLD,
208  &req)) ;
209 
210  /* this request can be freed, because this process is now done, and
211  paraklete_lsolve_node is followed by a barrier */
212  MPI (MPI_Request_free (&req)) ;
213  }
214 
215  return (TRUE) ;
216 }
#define TAG0
#define EMPTY
#define Int
#define PR0(params)
Int amesos_paraklete_lsolve_node(Int c, paraklete_numeric *LU, paraklete_symbolic *LUsymbolic, paraklete_common *Common)
#define CHOLMOD(name)
#define PR2(params)
#define GET_COLUMN(Ap, Anz, Aix, j, Ai, Ax, len)
#define ASSERT(expression)
#define ID
#define PR1(params)
int CHOLMOD() print_perm(Int *Perm, size_t len, size_t n, char *name, cholmod_common *Common)
#define MPI(statement)
#define DEBUG(statement)
#define TRUE