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