xref: /petsc/src/mat/impls/aij/seq/aijfact.c (revision 4c04a9de2e624de0fa2e8b46feb619f94d1e86ab)
1 #ifndef lint
2 static char vcid[] = "$Id: aijfact.c,v 1.26 1995/07/10 05:02:25 bsmith Exp bsmith $";
3 #endif
4 
5 
6 #include "aij.h"
7 #include "inline/spops.h"
8 /*
9     Factorization code for AIJ format.
10 */
11 
12 int MatLUFactorSymbolic_AIJ(Mat mat,IS isrow,IS iscol,double f,Mat *fact)
13 {
14   Mat_AIJ *aij = (Mat_AIJ *) mat->data, *aijnew;
15   IS      isicol;
16   int     *r,*ic, ierr, i, n = aij->m, *ai = aij->i, *aj = aij->j;
17   int     *ainew,*ajnew, jmax,*fill, *ajtmp, nz;
18   int     *idnew, idx, row,m,fm, nnz, nzi,len, realloc = 0,nzbd,*im;
19 
20   if (n != aij->n)
21     SETERRQ(1,"MatLUFactorSymbolic_AIJ:Matrix must be square");
22   if (!isrow)
23     SETERRQ(1,"MatLUFactorSymbolic_AIJ:Matrix must have row permutation");
24   if (!iscol)
25     SETERRQ(1,"MatLUFactorSymbolic_AIJ:Matrix must have column permutation");
26 
27   ierr = ISInvertPermutation(iscol,&isicol); CHKERRQ(ierr);
28   ISGetIndices(isrow,&r); ISGetIndices(isicol,&ic);
29 
30   /* get new row pointers */
31   ainew = (int *) PETSCMALLOC( (n+1)*sizeof(int) ); CHKPTRQ(ainew);
32   ainew[0] = 1;
33   /* don't know how many column pointers are needed so estimate */
34   jmax = (int) (f*ai[n]);
35   ajnew = (int *) PETSCMALLOC( (jmax)*sizeof(int) ); CHKPTRQ(ajnew);
36   /* fill is a linked list of nonzeros in active row */
37   fill = (int *) PETSCMALLOC( (2*n+1)*sizeof(int)); CHKPTRQ(fill);
38   im = fill + n + 1;
39   /* idnew is location of diagonal in factor */
40   idnew = (int *) PETSCMALLOC( (n+1)*sizeof(int)); CHKPTRQ(idnew);
41   idnew[0] = 1;
42 
43   for ( i=0; i<n; i++ ) {
44     /* first copy previous fill into linked list */
45     nnz = nz    = ai[r[i]+1] - ai[r[i]];
46     ajtmp = aj + ai[r[i]] - 1;
47     fill[n] = n;
48     while (nz--) {
49       fm = n;
50       idx = ic[*ajtmp++ - 1];
51       do {
52         m = fm;
53         fm = fill[m];
54       } while (fm < idx);
55       fill[m] = idx;
56       fill[idx] = fm;
57     }
58     row = fill[n];
59     while ( row < i ) {
60       ajtmp = ajnew + idnew[row];
61       nzbd = 1 + idnew[row] - ainew[row];
62       nz = im[row] - nzbd;
63       fm = row;
64       while (nz-- > 0) {
65         /* fm = n;  */
66         idx = *ajtmp++ - 1;
67         nzbd++;
68         if (idx == i) im[row] = nzbd;
69         do {
70           m = fm;
71           fm = fill[m];
72         } while (fm < idx);
73         if (fm != idx) {
74           fill[m] = idx;
75           fill[idx] = fm;
76           fm = idx;
77           nnz++;
78         }
79 /*  printf("i %d row %d nz %d idx %d fm %d\n",i,row,nz,idx,fm);  */
80       }
81       row = fill[row];
82     }
83     /* copy new filled row into permanent storage */
84     ainew[i+1] = ainew[i] + nnz;
85     if (ainew[i+1] > jmax+1) {
86       /* allocate a longer ajnew */
87       int maxadd;
88       maxadd = (int) ((f*ai[n]*(n-i+5))/n);
89       if (maxadd < nnz) maxadd = (n-i)*(nnz+1);
90       jmax += maxadd;
91       ajtmp = (int *) PETSCMALLOC( jmax*sizeof(int) );CHKPTRQ(ajtmp);
92       PETSCMEMCPY(ajtmp,ajnew,(ainew[i]-1)*sizeof(int));
93       PETSCFREE(ajnew);
94       ajnew = ajtmp;
95       realloc++; /* count how many times we realloc */
96     }
97     ajtmp = ajnew + ainew[i] - 1;
98     fm = fill[n];
99     nzi = 0;
100     im[i] = nnz;
101     while (nnz--) {
102       if (fm < i) nzi++;
103       *ajtmp++ = fm + 1;
104       fm = fill[fm];
105     }
106     idnew[i] = ainew[i] + nzi;
107   }
108 
109   PLogInfo((PetscObject)mat,
110     "Info:MatLUFactorSymbolic_AIJ:Reallocs %d Fill ratio:given %g needed %g\n",
111                              realloc,f,((double)ainew[n])/((double)ai[i]));
112 
113   ISDestroy(isicol); PETSCFREE(fill);
114 
115   /* put together the new matrix */
116   ierr = MatCreateSequentialAIJ(mat->comm,n, n, 0, 0, fact); CHKERRQ(ierr);
117   aijnew = (Mat_AIJ *) (*fact)->data;
118   PETSCFREE(aijnew->imax);
119   aijnew->singlemalloc = 0;
120   len = (ainew[n] - 1)*sizeof(Scalar);
121   /* the next line frees the default space generated by the Create() */
122   PETSCFREE(aijnew->a); PETSCFREE(aijnew->ilen);
123   aijnew->a          = (Scalar *) PETSCMALLOC( len ); CHKPTRQ(aijnew->a);
124   aijnew->j          = ajnew;
125   aijnew->i          = ainew;
126   aijnew->diag       = idnew;
127   aijnew->ilen       = 0;
128   aijnew->imax       = 0;
129   aijnew->row        = isrow;
130   aijnew->col        = iscol;
131   (*fact)->factor    = FACTOR_LU;
132   aijnew->solve_work = (Scalar *) PETSCMALLOC( n*sizeof(Scalar));
133   CHKPTRQ(aijnew->solve_work);
134   /* In aijnew structure:  Free imax, ilen, old a, old j.
135      Allocate idnew, solve_work, new a, new j */
136   aijnew->mem += (ainew[n]-1-n)*(sizeof(int) + sizeof(Scalar)) + sizeof(int);
137   aijnew->maxnz = aijnew->nz = ainew[n] - 1;
138 
139   /* Cannot do this here because child is destroyed before parent created
140      PLogObjectParent(*fact,isicol); */
141   return 0;
142 }
143 
144 int MatLUFactorNumeric_AIJ(Mat mat,Mat *infact)
145 {
146   Mat     fact = *infact;
147   Mat_AIJ *aij = (Mat_AIJ *) mat->data, *aijnew = (Mat_AIJ *)fact->data;
148   IS      iscol = aijnew->col, isrow = aijnew->row, isicol;
149   int     *r,*ic, ierr, i, j, n = aij->m, *ai = aijnew->i, *aj = aijnew->j;
150   int     *ajtmpold, *ajtmp, nz, row,*pj;
151   Scalar  *rtmp,*v, *pv, *pc, multiplier;
152 
153   ierr = ISInvertPermutation(iscol,&isicol); CHKERRQ(ierr);
154   PLogObjectParent(*infact,isicol);
155   ierr = ISGetIndices(isrow,&r); CHKERRQ(ierr);
156   ierr = ISGetIndices(isicol,&ic); CHKERRQ(ierr);
157   rtmp = (Scalar *) PETSCMALLOC( (n+1)*sizeof(Scalar) ); CHKPTRQ(rtmp);
158 
159   for ( i=0; i<n; i++ ) {
160     nz = ai[i+1] - ai[i];
161     ajtmp = aj + ai[i] - 1;
162     for  ( j=0; j<nz; j++ ) rtmp[ajtmp[j]-1] = 0.0;
163 
164     /* load in initial (unfactored row) */
165     nz = aij->i[r[i]+1] - aij->i[r[i]];
166     ajtmpold = aij->j + aij->i[r[i]] - 1;
167     v  = aij->a + aij->i[r[i]] - 1;
168     for ( j=0; j<nz; j++ ) rtmp[ic[ajtmpold[j]-1]] =  v[j];
169 
170     row = *ajtmp++ - 1;
171     while (row < i) {
172       pc = rtmp + row;
173       if (*pc != 0.0) {
174         nz = aijnew->diag[row] - ai[row];
175         pv = aijnew->a + aijnew->diag[row] - 1;
176         pj = aijnew->j + aijnew->diag[row];
177         multiplier = *pc * *pv++;
178         *pc = multiplier;
179         nz = ai[row+1] - ai[row] - 1 - nz;
180         PLogFlops(2*nz);
181         while (nz-->0) rtmp[*pj++ - 1] -= multiplier* *pv++;
182       }
183       row = *ajtmp++ - 1;
184     }
185     /* finished row so stick it into aijnew->a */
186     pv = aijnew->a + ai[i] - 1;
187     pj = aijnew->j + ai[i] - 1;
188     nz = ai[i+1] - ai[i];
189     if (rtmp[i] == 0.0) {SETERRQ(1,"MatLUFactorNumeric_AIJ:Zero pivot");}
190     rtmp[i] = 1.0/rtmp[i];
191     for ( j=0; j<nz; j++ ) {pv[j] = rtmp[pj[j]-1];}
192   }
193   PETSCFREE(rtmp);
194   ierr = ISRestoreIndices(isicol,&ic); CHKERRQ(ierr);
195   ierr = ISRestoreIndices(isrow,&r); CHKERRQ(ierr);
196   ierr = ISDestroy(isicol); CHKERRQ(ierr);
197   fact->factor      = FACTOR_LU;
198   aijnew->assembled = 1;
199   PLogFlops(aijnew->n);
200   return 0;
201 }
202 int MatLUFactor_AIJ(Mat matin,IS row,IS col,double f)
203 {
204   Mat_AIJ *mat = (Mat_AIJ *) matin->data;
205   int     ierr;
206   Mat     fact;
207   ierr = MatLUFactorSymbolic_AIJ(matin,row,col,f,&fact); CHKERRQ(ierr);
208   ierr = MatLUFactorNumeric_AIJ(matin,&fact); CHKERRQ(ierr);
209 
210   /* free all the data structures from mat */
211   PETSCFREE(mat->a);
212   if (!mat->singlemalloc) {PETSCFREE(mat->i); PETSCFREE(mat->j);}
213   if (mat->diag) PETSCFREE(mat->diag);
214   if (mat->ilen) PETSCFREE(mat->ilen);
215   if (mat->imax) PETSCFREE(mat->imax);
216   if (mat->row && mat->col && mat->row != mat->col) {
217     ISDestroy(mat->row);
218   }
219   if (mat->col) ISDestroy(mat->col);
220   PETSCFREE(mat);
221 
222   PETSCMEMCPY(matin,fact,sizeof(struct _Mat));
223   PETSCFREE(fact);
224   return 0;
225 }
226 
227 int MatSolve_AIJ(Mat mat,Vec bb, Vec xx)
228 {
229   Mat_AIJ *aij = (Mat_AIJ *) mat->data;
230   IS      iscol = aij->col, isrow = aij->row;
231   int     *r,*c, ierr, i,  n = aij->m, *vi, *ai = aij->i, *aj = aij->j;
232   int     nz;
233   Scalar  *x,*b,*tmp, *aa = aij->a, sum, *v;
234 
235   if (mat->factor != FACTOR_LU)
236     SETERRQ(1,"MatSolve_AIJ:Cannot solve with unfactored matrix");
237 
238   ierr = VecGetArray(bb,&b); CHKERRQ(ierr);
239   ierr = VecGetArray(xx,&x); CHKERRQ(ierr);
240   tmp = aij->solve_work;
241 
242   ierr = ISGetIndices(isrow,&r);CHKERRQ(ierr);
243   ierr = ISGetIndices(iscol,&c);CHKERRQ(ierr); c = c + (n-1);
244 
245   /* forward solve the lower triangular */
246   tmp[0] = b[*r++];
247   for ( i=1; i<n; i++ ) {
248     v   = aa + ai[i] - 1;
249     vi  = aj + ai[i] - 1;
250     nz  = aij->diag[i] - ai[i];
251     sum = b[*r++];
252     while (nz--) sum -= *v++ * tmp[*vi++ - 1];
253     tmp[i] = sum;
254   }
255 
256   /* backward solve the upper triangular */
257   for ( i=n-1; i>=0; i-- ){
258     v   = aa + aij->diag[i];
259     vi  = aj + aij->diag[i];
260     nz  = ai[i+1] - aij->diag[i] - 1;
261     sum = tmp[i];
262     while (nz--) sum -= *v++ * tmp[*vi++ - 1];
263     x[*c--] = tmp[i] = sum*aa[aij->diag[i]-1];
264   }
265 
266   PLogFlops(2*aij->nz - aij->n);
267   return 0;
268 }
269 int MatSolveAdd_AIJ(Mat mat,Vec bb, Vec yy, Vec xx)
270 {
271   Mat_AIJ *aij = (Mat_AIJ *) mat->data;
272   IS      iscol = aij->col, isrow = aij->row;
273   int     *r,*c, ierr, i,  n = aij->m, *vi, *ai = aij->i, *aj = aij->j;
274   int     nz;
275   Scalar  *x,*b,*tmp, *aa = aij->a, sum, *v;
276 
277   if (mat->factor != FACTOR_LU)
278     SETERRQ(1,"MatSolveAdd_AIJ: Cannot solve with unfactored matrix");
279   if (yy != xx) {ierr = VecCopy(yy,xx); CHKERRQ(ierr);}
280 
281   ierr = VecGetArray(bb,&b); CHKERRQ(ierr);
282   ierr = VecGetArray(xx,&x); CHKERRQ(ierr);
283   tmp = aij->solve_work;
284 
285   ierr = ISGetIndices(isrow,&r); CHKERRQ(ierr);
286   ierr = ISGetIndices(iscol,&c); CHKERRQ(ierr); c = c + (n-1);
287 
288   /* forward solve the lower triangular */
289   tmp[0] = b[*r++];
290   for ( i=1; i<n; i++ ) {
291     v   = aa + ai[i] - 1;
292     vi  = aj + ai[i] - 1;
293     nz  = aij->diag[i] - ai[i];
294     sum = b[*r++];
295     while (nz--) sum -= *v++ * tmp[*vi++ - 1];
296     tmp[i] = sum;
297   }
298 
299   /* backward solve the upper triangular */
300   for ( i=n-1; i>=0; i-- ){
301     v   = aa + aij->diag[i];
302     vi  = aj + aij->diag[i];
303     nz  = ai[i+1] - aij->diag[i] - 1;
304     sum = tmp[i];
305     while (nz--) sum -= *v++ * tmp[*vi++ - 1];
306     tmp[i] = sum*aa[aij->diag[i]-1];
307     x[*c--] += tmp[i];
308   }
309 
310   PLogFlops(2*aij->nz);
311   return 0;
312 }
313 /* -------------------------------------------------------------------*/
314 int MatSolveTrans_AIJ(Mat mat,Vec bb, Vec xx)
315 {
316   Mat_AIJ *aij = (Mat_AIJ *) mat->data;
317   IS      iscol = aij->col, isrow = aij->row, invisrow,inviscol;
318   int     *r,*c, ierr, i, n = aij->m, *vi, *ai = aij->i, *aj = aij->j;
319   int     nz;
320   Scalar  *x,*b,*tmp, *aa = aij->a, *v;
321 
322   if (mat->factor != FACTOR_LU)
323     SETERRQ(1,"MatSolveTrans_AIJ:Cannot solve with unfactored matrix");
324   ierr = VecGetArray(bb,&b); CHKERRQ(ierr);
325   ierr = VecGetArray(xx,&x); CHKERRQ(ierr);
326   tmp = aij->solve_work;
327 
328   /* invert the permutations */
329   ierr = ISInvertPermutation(isrow,&invisrow); CHKERRQ(ierr);
330   ierr = ISInvertPermutation(iscol,&inviscol); CHKERRQ(ierr);
331 
332 
333   ierr = ISGetIndices(invisrow,&r); CHKERRQ(ierr);
334   ierr = ISGetIndices(inviscol,&c); CHKERRQ(ierr);
335 
336   /* copy the b into temp work space according to permutation */
337   for ( i=0; i<n; i++ ) tmp[c[i]] = b[i];
338 
339   /* forward solve the U^T */
340   for ( i=0; i<n; i++ ) {
341     v   = aa + aij->diag[i] - 1;
342     vi  = aj + aij->diag[i];
343     nz  = ai[i+1] - aij->diag[i] - 1;
344     tmp[i] *= *v++;
345     while (nz--) {
346       tmp[*vi++ - 1] -= (*v++)*tmp[i];
347     }
348   }
349 
350   /* backward solve the L^T */
351   for ( i=n-1; i>=0; i-- ){
352     v   = aa + aij->diag[i] - 2;
353     vi  = aj + aij->diag[i] - 2;
354     nz  = aij->diag[i] - ai[i];
355     while (nz--) {
356       tmp[*vi-- - 1] -= (*v--)*tmp[i];
357     }
358   }
359 
360   /* copy tmp into x according to permutation */
361   for ( i=0; i<n; i++ ) x[r[i]] = tmp[i];
362 
363   ISDestroy(invisrow); ISDestroy(inviscol);
364 
365   PLogFlops(2*aij->nz-aij->n);
366   return 0;
367 }
368 
369 int MatSolveTransAdd_AIJ(Mat mat,Vec bb, Vec zz,Vec xx)
370 {
371   Mat_AIJ *aij = (Mat_AIJ *) mat->data;
372   IS      iscol = aij->col, isrow = aij->row, invisrow,inviscol;
373   int     *r,*c, ierr, i, n = aij->m, *vi, *ai = aij->i, *aj = aij->j;
374   int     nz;
375   Scalar  *x,*b,*tmp, *aa = aij->a, *v;
376 
377   if (mat->factor != FACTOR_LU)
378     SETERRQ(1,"MatSolveTransAdd_AIJ:Cannot solve with unfactored matrix");
379   if (zz != xx) VecCopy(zz,xx);
380 
381   ierr = VecGetArray(bb,&b); CHKERRQ(ierr);
382   ierr = VecGetArray(xx,&x); CHKERRQ(ierr);
383   tmp = aij->solve_work;
384 
385   /* invert the permutations */
386   ierr = ISInvertPermutation(isrow,&invisrow); CHKERRQ(ierr);
387   ierr = ISInvertPermutation(iscol,&inviscol); CHKERRQ(ierr);
388 
389 
390   ierr = ISGetIndices(invisrow,&r); CHKERRQ(ierr);
391   ierr = ISGetIndices(inviscol,&c); CHKERRQ(ierr);
392 
393   /* copy the b into temp work space according to permutation */
394   for ( i=0; i<n; i++ ) tmp[c[i]] = b[i];
395 
396   /* forward solve the U^T */
397   for ( i=0; i<n; i++ ) {
398     v   = aa + aij->diag[i] - 1;
399     vi  = aj + aij->diag[i];
400     nz  = ai[i+1] - aij->diag[i] - 1;
401     tmp[i] *= *v++;
402     while (nz--) {
403       tmp[*vi++ - 1] -= (*v++)*tmp[i];
404     }
405   }
406 
407   /* backward solve the L^T */
408   for ( i=n-1; i>=0; i-- ){
409     v   = aa + aij->diag[i] - 2;
410     vi  = aj + aij->diag[i] - 2;
411     nz  = aij->diag[i] - ai[i];
412     while (nz--) {
413       tmp[*vi-- - 1] -= (*v--)*tmp[i];
414     }
415   }
416 
417   /* copy tmp into x according to permutation */
418   for ( i=0; i<n; i++ ) x[r[i]] += tmp[i];
419 
420   ISDestroy(invisrow); ISDestroy(inviscol);
421 
422   PLogFlops(2*aij->nz);
423   return 0;
424 }
425 /* ----------------------------------------------------------------*/
426 int MatILUFactorSymbolic_AIJ(Mat mat,IS isrow,IS iscol,double f,
427                              int levels,Mat *fact)
428 {
429   Mat_AIJ *aij = (Mat_AIJ *) mat->data, *aijnew;
430   IS      isicol;
431   int     *r,*ic, ierr, i, n = aij->m, *ai = aij->i, *aj = aij->j;
432   int     *ainew,*ajnew, jmax,*fill, *ajtmp, nz, *lfill,*ajfill,*ajtmpf;
433   int     *idnew, idx, row,m,fm, nnz, nzi,len, *im, nzbd, realloc = 0;
434 
435   if (n != aij->n)
436     SETERRQ(1,"MatILUFactorSymbolic_AIJ:Matrix must be square");
437   if (!isrow)
438     SETERRQ(1,"MatILUFactorSymbolic_AIJ:Matrix must have row permutation");
439   if (!iscol) SETERRQ(1,
440     "MatILUFactorSymbolic_AIJ:Matrix must have column permutation");
441 
442   ierr = ISInvertPermutation(iscol,&isicol); CHKERRQ(ierr);
443   ISGetIndices(isrow,&r); ISGetIndices(isicol,&ic);
444 
445   /* get new row pointers */
446   ainew = (int *) PETSCMALLOC( (n+1)*sizeof(int) ); CHKPTRQ(ainew);
447   ainew[0] = 1;
448   /* don't know how many column pointers are needed so estimate */
449   jmax = (int) (f*ai[n]);
450   ajnew = (int *) PETSCMALLOC( (jmax)*sizeof(int) ); CHKPTRQ(ajnew);
451   /* ajfill is level of fill for each fill entry */
452   ajfill = (int *) PETSCMALLOC( (jmax)*sizeof(int) ); CHKPTRQ(ajfill);
453   /* fill is a linked list of nonzeros in active row */
454   fill = (int *) PETSCMALLOC( (2*n+1)*sizeof(int)); CHKPTRQ(fill);
455   im   = fill + n + 1;
456   /* lfill is level for each filled value */
457   lfill = (int *) PETSCMALLOC( (n+1)*sizeof(int)); CHKPTRQ(lfill);
458   /* idnew is location of diagonal in factor */
459   idnew = (int *) PETSCMALLOC( (n+1)*sizeof(int)); CHKPTRQ(idnew);
460   idnew[0] = 1;
461 
462   for ( i=0; i<n; i++ ) {
463     /* first copy previous fill into linked list */
464     nnz = nz    = ai[r[i]+1] - ai[r[i]];
465     ajtmp = aj + ai[r[i]] - 1;
466     fill[n] = n;
467     while (nz--) {
468       fm = n;
469       idx = ic[*ajtmp++ - 1];
470       do {
471         m = fm;
472         fm = fill[m];
473       } while (fm < idx);
474       fill[m] = idx;
475       fill[idx] = fm;
476       lfill[idx] = -1;
477  /* printf("i %d cols %d %d\n",i,nz,idx);  */
478     }
479     row = fill[n];
480     while ( row < i ) {
481       ajtmp  = ajnew + idnew[row];
482       ajtmpf = ajfill + idnew[row];
483 
484       nzbd = 1 + idnew[row] - ainew[row];
485       nz = im[row] - nzbd;
486 
487       fm = fill[row]; m = row;
488       while (nz-- > 0) {
489         idx = *ajtmp++ - 1;
490         nzbd++;
491         if (idx == i) im[row] = nzbd;
492         while (fm < idx) {
493           m = fm;
494           fm = fill[m];
495         }
496         if (fm != idx) {
497           lfill[idx] = *ajtmpf + 1;
498           if (lfill[idx] < levels) {
499             fill[m] = idx;
500             fill[idx] = fm;
501             fm = idx;
502             nnz++;
503           }
504         }
505  /* printf("i %d row %d nz %d idx %d fm %d level %d nnz %d\n",i,row,nz,idx,fm,*ajtmpf + 1,nnz); */
506         ajtmpf++;
507       }
508       row = fill[row];
509     }
510     /* copy new filled row into permanent storage */
511     ainew[i+1] = ainew[i] + nnz;
512     if (ainew[i+1] > jmax+1) {
513       /* allocate a longer ajnew */
514       int maxadd;
515       maxadd = (int) ((f*ai[n]*(n-i+5))/n);
516       if (maxadd < nnz) maxadd = (n-i)*(nnz+1);
517       jmax += maxadd;
518       ajtmp = (int *) PETSCMALLOC( jmax*sizeof(int) );CHKPTRQ(ajtmp);
519       PETSCMEMCPY(ajtmp,ajnew,(ainew[i]-1)*sizeof(int));
520       PETSCFREE(ajnew);
521       ajnew = ajtmp;
522       /* allocate a longer ajfill */
523       ajtmp = (int *) PETSCMALLOC( jmax*sizeof(int) );CHKPTRQ(ajtmp);
524       PETSCMEMCPY(ajtmp,ajfill,(ainew[i]-1)*sizeof(int));
525       PETSCFREE(ajfill);
526       ajfill = ajtmp;
527       realloc++;
528     }
529     ajtmp  = ajnew + ainew[i] - 1;
530     ajtmpf = ajfill + ainew[i] - 1;
531     fm = fill[n];
532     im[i] = nnz;
533     nzi = 0;
534     while (nnz--) {
535       if (fm < i) nzi++;
536       *ajtmp++  = fm + 1;
537       *ajtmpf++ = lfill[fm];
538 /* printf("i %d col %d level %d\n",i,fm,lfill[fm]); */
539       fm = fill[fm];
540     }
541     idnew[i] = ainew[i] + nzi;
542   }
543   PETSCFREE(ajfill);
544   ISDestroy(isicol); PETSCFREE(fill); PETSCFREE(lfill);
545 
546   PLogInfo((PetscObject)mat,
547     "Info:MatILUFactorSymbolic_AIJ:Realloc %d Fill ratio:given %g needed %g\n",
548                              realloc,f,((double)ainew[n])/((double)ai[i]));
549 
550   /* put together the new matrix */
551   ierr = MatCreateSequentialAIJ(mat->comm,n, n, 0, 0, fact); CHKERRQ(ierr);
552   aijnew = (Mat_AIJ *) (*fact)->data;
553   PETSCFREE(aijnew->imax);
554   aijnew->singlemalloc = 0;
555   len = (ainew[n] - 1)*sizeof(Scalar);
556   /* the next line frees the default space generated by the Create() */
557   PETSCFREE(aijnew->a); PETSCFREE(aijnew->ilen);
558   aijnew->a         = (Scalar *) PETSCMALLOC( len ); CHKPTRQ(aijnew->a);
559   aijnew->j         = ajnew;
560   aijnew->i         = ainew;
561   aijnew->diag      = idnew;
562   aijnew->ilen      = 0;
563   aijnew->imax      = 0;
564   aijnew->row       = isrow;
565   aijnew->col       = iscol;
566   aijnew->solve_work = (Scalar *) PETSCMALLOC( (n+1)*sizeof(Scalar));
567   CHKPTRQ(aijnew->solve_work);
568   /* In aijnew structure:  Free imax, ilen, old a, old j.
569      Allocate idnew, solve_work, new a, new j */
570   aijnew->mem += (ainew[n]-1-n)*(sizeof(int) + sizeof(Scalar)) + sizeof(int);
571   aijnew->maxnz = aijnew->nz = ainew[n] - 1;
572   (*fact)->factor   = FACTOR_LU;
573   return 0;
574 }
575