1*5d517e7eSBarry Smith #ifndef lint 2*5d517e7eSBarry Smith static char vcid[] = "$Id: aijfact.c,v 1.56 1996/01/26 04:33:46 bsmith Exp bsmith $"; 3*5d517e7eSBarry Smith #endif 4*5d517e7eSBarry Smith 5*5d517e7eSBarry Smith #include "aij.h" 6*5d517e7eSBarry Smith /* 7*5d517e7eSBarry Smith Factorization code for AIJ format. 8*5d517e7eSBarry Smith */ 9*5d517e7eSBarry Smith 10*5d517e7eSBarry Smith int MatLUFactorSymbolic_SeqAIJ(Mat A,IS isrow,IS iscol,double f,Mat *B) 11*5d517e7eSBarry Smith { 12*5d517e7eSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data, *b; 13*5d517e7eSBarry Smith IS isicol; 14*5d517e7eSBarry Smith int *r,*ic, ierr, i, n = a->m, *ai = a->i, *aj = a->j; 15*5d517e7eSBarry Smith int *ainew,*ajnew, jmax,*fill, *ajtmp, nz,shift = a->indexshift; 16*5d517e7eSBarry Smith int *idnew, idx, row,m,fm, nnz, nzi,len, realloc = 0,nzbd,*im; 17*5d517e7eSBarry Smith 18*5d517e7eSBarry Smith if (n != a->n) SETERRQ(1,"MatLUFactorSymbolic_SeqAIJ:Must be square"); 19*5d517e7eSBarry Smith if (!isrow) SETERRQ(1,"MatLUFactorSymbolic_SeqAIJ:Must have row permutation"); 20*5d517e7eSBarry Smith if (!iscol) SETERRQ(1,"MatLUFactorSymbolic_SeqAIJ:Must have col. permutation"); 21*5d517e7eSBarry Smith 22*5d517e7eSBarry Smith ierr = ISInvertPermutation(iscol,&isicol); CHKERRQ(ierr); 23*5d517e7eSBarry Smith ISGetIndices(isrow,&r); ISGetIndices(isicol,&ic); 24*5d517e7eSBarry Smith 25*5d517e7eSBarry Smith /* get new row pointers */ 26*5d517e7eSBarry Smith ainew = (int *) PetscMalloc( (n+1)*sizeof(int) ); CHKPTRQ(ainew); 27*5d517e7eSBarry Smith ainew[0] = -shift; 28*5d517e7eSBarry Smith /* don't know how many column pointers are needed so estimate */ 29*5d517e7eSBarry Smith jmax = (int) (f*ai[n]+(!shift)); 30*5d517e7eSBarry Smith ajnew = (int *) PetscMalloc( (jmax)*sizeof(int) ); CHKPTRQ(ajnew); 31*5d517e7eSBarry Smith /* fill is a linked list of nonzeros in active row */ 32*5d517e7eSBarry Smith fill = (int *) PetscMalloc( (2*n+1)*sizeof(int)); CHKPTRQ(fill); 33*5d517e7eSBarry Smith im = fill + n + 1; 34*5d517e7eSBarry Smith /* idnew is location of diagonal in factor */ 35*5d517e7eSBarry Smith idnew = (int *) PetscMalloc( (n+1)*sizeof(int)); CHKPTRQ(idnew); 36*5d517e7eSBarry Smith idnew[0] = -shift; 37*5d517e7eSBarry Smith 38*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) { 39*5d517e7eSBarry Smith /* first copy previous fill into linked list */ 40*5d517e7eSBarry Smith nnz = nz = ai[r[i]+1] - ai[r[i]]; 41*5d517e7eSBarry Smith ajtmp = aj + ai[r[i]] + shift; 42*5d517e7eSBarry Smith fill[n] = n; 43*5d517e7eSBarry Smith while (nz--) { 44*5d517e7eSBarry Smith fm = n; 45*5d517e7eSBarry Smith idx = ic[*ajtmp++ + shift]; 46*5d517e7eSBarry Smith do { 47*5d517e7eSBarry Smith m = fm; 48*5d517e7eSBarry Smith fm = fill[m]; 49*5d517e7eSBarry Smith } while (fm < idx); 50*5d517e7eSBarry Smith fill[m] = idx; 51*5d517e7eSBarry Smith fill[idx] = fm; 52*5d517e7eSBarry Smith } 53*5d517e7eSBarry Smith row = fill[n]; 54*5d517e7eSBarry Smith while ( row < i ) { 55*5d517e7eSBarry Smith ajtmp = ajnew + idnew[row] + (!shift); 56*5d517e7eSBarry Smith nzbd = 1 + idnew[row] - ainew[row]; 57*5d517e7eSBarry Smith nz = im[row] - nzbd; 58*5d517e7eSBarry Smith fm = row; 59*5d517e7eSBarry Smith while (nz-- > 0) { 60*5d517e7eSBarry Smith idx = *ajtmp++ + shift; 61*5d517e7eSBarry Smith nzbd++; 62*5d517e7eSBarry Smith if (idx == i) im[row] = nzbd; 63*5d517e7eSBarry Smith do { 64*5d517e7eSBarry Smith m = fm; 65*5d517e7eSBarry Smith fm = fill[m]; 66*5d517e7eSBarry Smith } while (fm < idx); 67*5d517e7eSBarry Smith if (fm != idx) { 68*5d517e7eSBarry Smith fill[m] = idx; 69*5d517e7eSBarry Smith fill[idx] = fm; 70*5d517e7eSBarry Smith fm = idx; 71*5d517e7eSBarry Smith nnz++; 72*5d517e7eSBarry Smith } 73*5d517e7eSBarry Smith } 74*5d517e7eSBarry Smith row = fill[row]; 75*5d517e7eSBarry Smith } 76*5d517e7eSBarry Smith /* copy new filled row into permanent storage */ 77*5d517e7eSBarry Smith ainew[i+1] = ainew[i] + nnz; 78*5d517e7eSBarry Smith if (ainew[i+1] > jmax+1) { 79*5d517e7eSBarry Smith /* allocate a longer ajnew */ 80*5d517e7eSBarry Smith int maxadd; 81*5d517e7eSBarry Smith maxadd = (int) ((f*(ai[n]+(!shift))*(n-i+5))/n); 82*5d517e7eSBarry Smith if (maxadd < nnz) maxadd = (n-i)*(nnz+1); 83*5d517e7eSBarry Smith jmax += maxadd; 84*5d517e7eSBarry Smith ajtmp = (int *) PetscMalloc( jmax*sizeof(int) );CHKPTRQ(ajtmp); 85*5d517e7eSBarry Smith PetscMemcpy(ajtmp,ajnew,(ainew[i]+shift)*sizeof(int)); 86*5d517e7eSBarry Smith PetscFree(ajnew); 87*5d517e7eSBarry Smith ajnew = ajtmp; 88*5d517e7eSBarry Smith realloc++; /* count how many times we realloc */ 89*5d517e7eSBarry Smith } 90*5d517e7eSBarry Smith ajtmp = ajnew + ainew[i] + shift; 91*5d517e7eSBarry Smith fm = fill[n]; 92*5d517e7eSBarry Smith nzi = 0; 93*5d517e7eSBarry Smith im[i] = nnz; 94*5d517e7eSBarry Smith while (nnz--) { 95*5d517e7eSBarry Smith if (fm < i) nzi++; 96*5d517e7eSBarry Smith *ajtmp++ = fm - shift; 97*5d517e7eSBarry Smith fm = fill[fm]; 98*5d517e7eSBarry Smith } 99*5d517e7eSBarry Smith idnew[i] = ainew[i] + nzi; 100*5d517e7eSBarry Smith } 101*5d517e7eSBarry Smith 102*5d517e7eSBarry Smith PLogInfo((PetscObject)A, 103*5d517e7eSBarry Smith "Info:MatLUFactorSymbolic_SeqAIJ:Reallocs %d Fill ratio:given %g needed %g\n", 104*5d517e7eSBarry Smith realloc,f,((double)ainew[n])/((double)ai[i])); 105*5d517e7eSBarry Smith 106*5d517e7eSBarry Smith ierr = ISRestoreIndices(isrow,&r); CHKERRQ(ierr); 107*5d517e7eSBarry Smith ierr = ISRestoreIndices(isicol,&ic); CHKERRQ(ierr); 108*5d517e7eSBarry Smith 109*5d517e7eSBarry Smith PetscFree(fill); 110*5d517e7eSBarry Smith 111*5d517e7eSBarry Smith /* put together the new matrix */ 112*5d517e7eSBarry Smith ierr = MatCreateSeqAIJ(A->comm,n,n,0,PETSC_NULL,B); CHKERRQ(ierr); 113*5d517e7eSBarry Smith PLogObjectParent(*B,isicol); 114*5d517e7eSBarry Smith ierr = ISDestroy(isicol); CHKERRQ(ierr); 115*5d517e7eSBarry Smith b = (Mat_SeqAIJ *) (*B)->data; 116*5d517e7eSBarry Smith PetscFree(b->imax); 117*5d517e7eSBarry Smith b->singlemalloc = 0; 118*5d517e7eSBarry Smith len = (ainew[n] + shift)*sizeof(Scalar); 119*5d517e7eSBarry Smith /* the next line frees the default space generated by the Create() */ 120*5d517e7eSBarry Smith PetscFree(b->a); PetscFree(b->ilen); 121*5d517e7eSBarry Smith b->a = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a); 122*5d517e7eSBarry Smith b->j = ajnew; 123*5d517e7eSBarry Smith b->i = ainew; 124*5d517e7eSBarry Smith b->diag = idnew; 125*5d517e7eSBarry Smith b->ilen = 0; 126*5d517e7eSBarry Smith b->imax = 0; 127*5d517e7eSBarry Smith b->row = isrow; 128*5d517e7eSBarry Smith b->col = iscol; 129*5d517e7eSBarry Smith b->solve_work = (Scalar *) PetscMalloc( n*sizeof(Scalar)); 130*5d517e7eSBarry Smith CHKPTRQ(b->solve_work); 131*5d517e7eSBarry Smith /* In b structure: Free imax, ilen, old a, old j. 132*5d517e7eSBarry Smith Allocate idnew, solve_work, new a, new j */ 133*5d517e7eSBarry Smith PLogObjectMemory(*B,(ainew[n]+shift-n)*(sizeof(int)+sizeof(Scalar))); 134*5d517e7eSBarry Smith b->maxnz = b->nz = ainew[n] + shift; 135*5d517e7eSBarry Smith 136*5d517e7eSBarry Smith return 0; 137*5d517e7eSBarry Smith } 138*5d517e7eSBarry Smith /* ----------------------------------------------------------- */ 139*5d517e7eSBarry Smith int Mat_AIJ_CheckInode(Mat); 140*5d517e7eSBarry Smith 141*5d517e7eSBarry Smith int MatLUFactorNumeric_SeqAIJ(Mat A,Mat *B) 142*5d517e7eSBarry Smith { 143*5d517e7eSBarry Smith Mat C = *B; 144*5d517e7eSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data, *b = (Mat_SeqAIJ *)C->data; 145*5d517e7eSBarry Smith IS iscol = b->col, isrow = b->row, isicol; 146*5d517e7eSBarry Smith int *r,*ic, ierr, i, j, n = a->m, *ai = b->i, *aj = b->j; 147*5d517e7eSBarry Smith int *ajtmpold, *ajtmp, nz, row, *ics, shift = a->indexshift; 148*5d517e7eSBarry Smith int *diag_offset = b->diag,diag,k; 149*5d517e7eSBarry Smith int preserve_row_sums = (int) a->ilu_preserve_row_sums; 150*5d517e7eSBarry Smith Scalar *rtmp,*v, *pc, multiplier,sum,inner_sum,*rowsums; 151*5d517e7eSBarry Smith double ssum; 152*5d517e7eSBarry Smith /* These declarations are for optimizations. They reduce the number of 153*5d517e7eSBarry Smith memory references that are made by locally storing information; the 154*5d517e7eSBarry Smith word "register" used here with pointers can be viewed as "private" or 155*5d517e7eSBarry Smith "known only to me" 156*5d517e7eSBarry Smith */ 157*5d517e7eSBarry Smith register Scalar *pv, *rtmps,*u_values; 158*5d517e7eSBarry Smith register int *pj; 159*5d517e7eSBarry Smith 160*5d517e7eSBarry Smith ierr = ISInvertPermutation(iscol,&isicol); CHKERRQ(ierr); 161*5d517e7eSBarry Smith PLogObjectParent(*B,isicol); 162*5d517e7eSBarry Smith ierr = ISGetIndices(isrow,&r); CHKERRQ(ierr); 163*5d517e7eSBarry Smith ierr = ISGetIndices(isicol,&ic); CHKERRQ(ierr); 164*5d517e7eSBarry Smith rtmp = (Scalar *) PetscMalloc( (n+1)*sizeof(Scalar) ); CHKPTRQ(rtmp); 165*5d517e7eSBarry Smith rtmps = rtmp + shift; ics = ic + shift; 166*5d517e7eSBarry Smith 167*5d517e7eSBarry Smith /* precalcuate row sums */ 168*5d517e7eSBarry Smith if (preserve_row_sums) { 169*5d517e7eSBarry Smith rowsums = (Scalar *) PetscMalloc( n*sizeof(Scalar) ); CHKPTRQ(rowsums); 170*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) { 171*5d517e7eSBarry Smith nz = a->i[r[i]+1] - a->i[r[i]]; 172*5d517e7eSBarry Smith v = a->a + a->i[r[i]] + shift; 173*5d517e7eSBarry Smith sum = 0.0; 174*5d517e7eSBarry Smith for ( j=0; j<nz; j++ ) sum += v[j]; 175*5d517e7eSBarry Smith rowsums[i] = sum; 176*5d517e7eSBarry Smith } 177*5d517e7eSBarry Smith } 178*5d517e7eSBarry Smith 179*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) { 180*5d517e7eSBarry Smith nz = ai[i+1] - ai[i]; 181*5d517e7eSBarry Smith ajtmp = aj + ai[i] + shift; 182*5d517e7eSBarry Smith for ( j=0; j<nz; j++ ) rtmps[ajtmp[j]] = 0.0; 183*5d517e7eSBarry Smith 184*5d517e7eSBarry Smith /* load in initial (unfactored row) */ 185*5d517e7eSBarry Smith nz = a->i[r[i]+1] - a->i[r[i]]; 186*5d517e7eSBarry Smith ajtmpold = a->j + a->i[r[i]] + shift; 187*5d517e7eSBarry Smith v = a->a + a->i[r[i]] + shift; 188*5d517e7eSBarry Smith for ( j=0; j<nz; j++ ) rtmp[ics[ajtmpold[j]]] = v[j]; 189*5d517e7eSBarry Smith 190*5d517e7eSBarry Smith row = *ajtmp++ + shift; 191*5d517e7eSBarry Smith while (row < i) { 192*5d517e7eSBarry Smith pc = rtmp + row; 193*5d517e7eSBarry Smith if (*pc != 0.0) { 194*5d517e7eSBarry Smith pv = b->a + diag_offset[row] + shift; 195*5d517e7eSBarry Smith pj = b->j + diag_offset[row] + (!shift); 196*5d517e7eSBarry Smith multiplier = *pc / *pv++; 197*5d517e7eSBarry Smith *pc = multiplier; 198*5d517e7eSBarry Smith nz = ai[row+1] - diag_offset[row] - 1; 199*5d517e7eSBarry Smith for (j=0; j<nz; j++) rtmps[pj[j]] -= multiplier * pv[j]; 200*5d517e7eSBarry Smith PLogFlops(2*nz); 201*5d517e7eSBarry Smith } 202*5d517e7eSBarry Smith row = *ajtmp++ + shift; 203*5d517e7eSBarry Smith } 204*5d517e7eSBarry Smith /* finished row so stick it into b->a */ 205*5d517e7eSBarry Smith pv = b->a + ai[i] + shift; 206*5d517e7eSBarry Smith pj = b->j + ai[i] + shift; 207*5d517e7eSBarry Smith nz = ai[i+1] - ai[i]; 208*5d517e7eSBarry Smith for ( j=0; j<nz; j++ ) {pv[j] = rtmps[pj[j]];} 209*5d517e7eSBarry Smith diag = diag_offset[i] - ai[i]; 210*5d517e7eSBarry Smith /* 211*5d517e7eSBarry Smith Possibly adjust diagonal entry on current row to force 212*5d517e7eSBarry Smith LU matrix to have same row sum as initial matrix. 213*5d517e7eSBarry Smith */ 214*5d517e7eSBarry Smith if (preserve_row_sums) { 215*5d517e7eSBarry Smith pj = b->j + ai[i] + shift; 216*5d517e7eSBarry Smith sum = rowsums[i]; 217*5d517e7eSBarry Smith for ( j=0; j<diag; j++ ) { 218*5d517e7eSBarry Smith u_values = b->a + diag_offset[pj[j]] + shift; 219*5d517e7eSBarry Smith nz = ai[pj[j]+1] - diag_offset[pj[j]]; 220*5d517e7eSBarry Smith inner_sum = 0.0; 221*5d517e7eSBarry Smith for ( k=0; k<nz; k++ ) { 222*5d517e7eSBarry Smith inner_sum += u_values[k]; 223*5d517e7eSBarry Smith } 224*5d517e7eSBarry Smith sum -= pv[j]*inner_sum; 225*5d517e7eSBarry Smith 226*5d517e7eSBarry Smith } 227*5d517e7eSBarry Smith nz = ai[i+1] - diag_offset[i] - 1; 228*5d517e7eSBarry Smith u_values = b->a + diag_offset[i] + 1 + shift; 229*5d517e7eSBarry Smith for ( k=0; k<nz; k++ ) { 230*5d517e7eSBarry Smith sum -= u_values[k]; 231*5d517e7eSBarry Smith } 232*5d517e7eSBarry Smith ssum = PetscAbsScalar(sum/pv[diag]); 233*5d517e7eSBarry Smith if (ssum < 1000. && ssum > .001) pv[diag] = sum; 234*5d517e7eSBarry Smith } 235*5d517e7eSBarry Smith /* check pivot entry for current row */ 236*5d517e7eSBarry Smith if (pv[diag] == 0.0) { 237*5d517e7eSBarry Smith SETERRQ(1,"MatLUFactorNumeric_SeqAIJ:Zero pivot"); 238*5d517e7eSBarry Smith } 239*5d517e7eSBarry Smith } 240*5d517e7eSBarry Smith 241*5d517e7eSBarry Smith /* invert diagonal entries for simplier triangular solves */ 242*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) { 243*5d517e7eSBarry Smith b->a[diag_offset[i]+shift] = 1.0/b->a[diag_offset[i]+shift]; 244*5d517e7eSBarry Smith } 245*5d517e7eSBarry Smith 246*5d517e7eSBarry Smith if (preserve_row_sums) PetscFree(rowsums); 247*5d517e7eSBarry Smith PetscFree(rtmp); 248*5d517e7eSBarry Smith ierr = ISRestoreIndices(isicol,&ic); CHKERRQ(ierr); 249*5d517e7eSBarry Smith ierr = ISRestoreIndices(isrow,&r); CHKERRQ(ierr); 250*5d517e7eSBarry Smith ierr = ISDestroy(isicol); CHKERRQ(ierr); 251*5d517e7eSBarry Smith C->factor = FACTOR_LU; 252*5d517e7eSBarry Smith ierr = Mat_AIJ_CheckInode(C); CHKERRQ(ierr); 253*5d517e7eSBarry Smith C->assembled = PETSC_TRUE; 254*5d517e7eSBarry Smith PLogFlops(b->n); 255*5d517e7eSBarry Smith return 0; 256*5d517e7eSBarry Smith } 257*5d517e7eSBarry Smith /* ----------------------------------------------------------- */ 258*5d517e7eSBarry Smith int MatLUFactor_SeqAIJ(Mat A,IS row,IS col,double f) 259*5d517e7eSBarry Smith { 260*5d517e7eSBarry Smith Mat_SeqAIJ *mat = (Mat_SeqAIJ *) A->data; 261*5d517e7eSBarry Smith int ierr; 262*5d517e7eSBarry Smith Mat C; 263*5d517e7eSBarry Smith 264*5d517e7eSBarry Smith ierr = MatLUFactorSymbolic_SeqAIJ(A,row,col,f,&C); CHKERRQ(ierr); 265*5d517e7eSBarry Smith ierr = MatLUFactorNumeric_SeqAIJ(A,&C); CHKERRQ(ierr); 266*5d517e7eSBarry Smith 267*5d517e7eSBarry Smith /* free all the data structures from mat */ 268*5d517e7eSBarry Smith PetscFree(mat->a); 269*5d517e7eSBarry Smith if (!mat->singlemalloc) {PetscFree(mat->i); PetscFree(mat->j);} 270*5d517e7eSBarry Smith if (mat->diag) PetscFree(mat->diag); 271*5d517e7eSBarry Smith if (mat->ilen) PetscFree(mat->ilen); 272*5d517e7eSBarry Smith if (mat->imax) PetscFree(mat->imax); 273*5d517e7eSBarry Smith if (mat->solve_work) PetscFree(mat->solve_work); 274*5d517e7eSBarry Smith if (mat->inode.size) PetscFree(mat->inode.size); 275*5d517e7eSBarry Smith PetscFree(mat); 276*5d517e7eSBarry Smith 277*5d517e7eSBarry Smith PetscMemcpy(A,C,sizeof(struct _Mat)); 278*5d517e7eSBarry Smith PetscHeaderDestroy(C); 279*5d517e7eSBarry Smith return 0; 280*5d517e7eSBarry Smith } 281*5d517e7eSBarry Smith /* ----------------------------------------------------------- */ 282*5d517e7eSBarry Smith int MatSolve_SeqAIJ(Mat A,Vec bb, Vec xx) 283*5d517e7eSBarry Smith { 284*5d517e7eSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 285*5d517e7eSBarry Smith IS iscol = a->col, isrow = a->row; 286*5d517e7eSBarry Smith int *r,*c, ierr, i, n = a->m, *vi, *ai = a->i, *aj = a->j; 287*5d517e7eSBarry Smith int nz,shift = a->indexshift; 288*5d517e7eSBarry Smith Scalar *x,*b,*tmp, *tmps, *aa = a->a, sum, *v; 289*5d517e7eSBarry Smith 290*5d517e7eSBarry Smith if (A->factor != FACTOR_LU) SETERRQ(1,"MatSolve_SeqAIJ:Not for unfactored matrix"); 291*5d517e7eSBarry Smith 292*5d517e7eSBarry Smith ierr = VecGetArray(bb,&b); CHKERRQ(ierr); 293*5d517e7eSBarry Smith ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 294*5d517e7eSBarry Smith tmp = a->solve_work; 295*5d517e7eSBarry Smith 296*5d517e7eSBarry Smith ierr = ISGetIndices(isrow,&r);CHKERRQ(ierr); 297*5d517e7eSBarry Smith ierr = ISGetIndices(iscol,&c);CHKERRQ(ierr); c = c + (n-1); 298*5d517e7eSBarry Smith 299*5d517e7eSBarry Smith /* forward solve the lower triangular */ 300*5d517e7eSBarry Smith tmp[0] = b[*r++]; 301*5d517e7eSBarry Smith tmps = tmp + shift; 302*5d517e7eSBarry Smith for ( i=1; i<n; i++ ) { 303*5d517e7eSBarry Smith v = aa + ai[i] + shift; 304*5d517e7eSBarry Smith vi = aj + ai[i] + shift; 305*5d517e7eSBarry Smith nz = a->diag[i] - ai[i]; 306*5d517e7eSBarry Smith sum = b[*r++]; 307*5d517e7eSBarry Smith while (nz--) sum -= *v++ * tmps[*vi++]; 308*5d517e7eSBarry Smith tmp[i] = sum; 309*5d517e7eSBarry Smith } 310*5d517e7eSBarry Smith 311*5d517e7eSBarry Smith /* backward solve the upper triangular */ 312*5d517e7eSBarry Smith for ( i=n-1; i>=0; i-- ){ 313*5d517e7eSBarry Smith v = aa + a->diag[i] + (!shift); 314*5d517e7eSBarry Smith vi = aj + a->diag[i] + (!shift); 315*5d517e7eSBarry Smith nz = ai[i+1] - a->diag[i] - 1; 316*5d517e7eSBarry Smith sum = tmp[i]; 317*5d517e7eSBarry Smith while (nz--) sum -= *v++ * tmps[*vi++]; 318*5d517e7eSBarry Smith x[*c--] = tmp[i] = sum*aa[a->diag[i]+shift]; 319*5d517e7eSBarry Smith } 320*5d517e7eSBarry Smith 321*5d517e7eSBarry Smith ierr = ISRestoreIndices(isrow,&r); CHKERRQ(ierr); 322*5d517e7eSBarry Smith ierr = ISRestoreIndices(iscol,&c); CHKERRQ(ierr); 323*5d517e7eSBarry Smith PLogFlops(2*a->nz - a->n); 324*5d517e7eSBarry Smith return 0; 325*5d517e7eSBarry Smith } 326*5d517e7eSBarry Smith int MatSolveAdd_SeqAIJ(Mat A,Vec bb, Vec yy, Vec xx) 327*5d517e7eSBarry Smith { 328*5d517e7eSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 329*5d517e7eSBarry Smith IS iscol = a->col, isrow = a->row; 330*5d517e7eSBarry Smith int *r,*c, ierr, i, n = a->m, *vi, *ai = a->i, *aj = a->j; 331*5d517e7eSBarry Smith int nz, shift = a->indexshift; 332*5d517e7eSBarry Smith Scalar *x,*b,*tmp, *aa = a->a, sum, *v; 333*5d517e7eSBarry Smith 334*5d517e7eSBarry Smith if (A->factor != FACTOR_LU) SETERRQ(1,"MatSolveAdd_SeqAIJ:Not for unfactored matrix"); 335*5d517e7eSBarry Smith if (yy != xx) {ierr = VecCopy(yy,xx); CHKERRQ(ierr);} 336*5d517e7eSBarry Smith 337*5d517e7eSBarry Smith ierr = VecGetArray(bb,&b); CHKERRQ(ierr); 338*5d517e7eSBarry Smith ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 339*5d517e7eSBarry Smith tmp = a->solve_work; 340*5d517e7eSBarry Smith 341*5d517e7eSBarry Smith ierr = ISGetIndices(isrow,&r); CHKERRQ(ierr); 342*5d517e7eSBarry Smith ierr = ISGetIndices(iscol,&c); CHKERRQ(ierr); c = c + (n-1); 343*5d517e7eSBarry Smith 344*5d517e7eSBarry Smith /* forward solve the lower triangular */ 345*5d517e7eSBarry Smith tmp[0] = b[*r++]; 346*5d517e7eSBarry Smith for ( i=1; i<n; i++ ) { 347*5d517e7eSBarry Smith v = aa + ai[i] + shift; 348*5d517e7eSBarry Smith vi = aj + ai[i] + shift; 349*5d517e7eSBarry Smith nz = a->diag[i] - ai[i]; 350*5d517e7eSBarry Smith sum = b[*r++]; 351*5d517e7eSBarry Smith while (nz--) sum -= *v++ * tmp[*vi++ + shift]; 352*5d517e7eSBarry Smith tmp[i] = sum; 353*5d517e7eSBarry Smith } 354*5d517e7eSBarry Smith 355*5d517e7eSBarry Smith /* backward solve the upper triangular */ 356*5d517e7eSBarry Smith for ( i=n-1; i>=0; i-- ){ 357*5d517e7eSBarry Smith v = aa + a->diag[i] + (!shift); 358*5d517e7eSBarry Smith vi = aj + a->diag[i] + (!shift); 359*5d517e7eSBarry Smith nz = ai[i+1] - a->diag[i] - 1; 360*5d517e7eSBarry Smith sum = tmp[i]; 361*5d517e7eSBarry Smith while (nz--) sum -= *v++ * tmp[*vi++ + shift]; 362*5d517e7eSBarry Smith tmp[i] = sum*aa[a->diag[i]+shift]; 363*5d517e7eSBarry Smith x[*c--] += tmp[i]; 364*5d517e7eSBarry Smith } 365*5d517e7eSBarry Smith 366*5d517e7eSBarry Smith ierr = ISRestoreIndices(isrow,&r); CHKERRQ(ierr); 367*5d517e7eSBarry Smith ierr = ISRestoreIndices(iscol,&c); CHKERRQ(ierr); 368*5d517e7eSBarry Smith PLogFlops(2*a->nz); 369*5d517e7eSBarry Smith 370*5d517e7eSBarry Smith return 0; 371*5d517e7eSBarry Smith } 372*5d517e7eSBarry Smith /* -------------------------------------------------------------------*/ 373*5d517e7eSBarry Smith int MatSolveTrans_SeqAIJ(Mat A,Vec bb, Vec xx) 374*5d517e7eSBarry Smith { 375*5d517e7eSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 376*5d517e7eSBarry Smith IS iscol = a->col, isrow = a->row, invisrow,inviscol; 377*5d517e7eSBarry Smith int *r,*c, ierr, i, n = a->m, *vi, *ai = a->i, *aj = a->j; 378*5d517e7eSBarry Smith int nz,shift = a->indexshift; 379*5d517e7eSBarry Smith Scalar *x,*b,*tmp, *aa = a->a, *v; 380*5d517e7eSBarry Smith 381*5d517e7eSBarry Smith if (A->factor != FACTOR_LU) SETERRQ(1,"MatSolveTrans_SeqAIJ:Not unfactored matrix"); 382*5d517e7eSBarry Smith ierr = VecGetArray(bb,&b); CHKERRQ(ierr); 383*5d517e7eSBarry Smith ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 384*5d517e7eSBarry Smith tmp = a->solve_work; 385*5d517e7eSBarry Smith 386*5d517e7eSBarry Smith /* invert the permutations */ 387*5d517e7eSBarry Smith ierr = ISInvertPermutation(isrow,&invisrow); CHKERRQ(ierr); 388*5d517e7eSBarry Smith ierr = ISInvertPermutation(iscol,&inviscol); CHKERRQ(ierr); 389*5d517e7eSBarry Smith 390*5d517e7eSBarry Smith ierr = ISGetIndices(invisrow,&r); CHKERRQ(ierr); 391*5d517e7eSBarry Smith ierr = ISGetIndices(inviscol,&c); CHKERRQ(ierr); 392*5d517e7eSBarry Smith 393*5d517e7eSBarry Smith /* copy the b into temp work space according to permutation */ 394*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) tmp[c[i]] = b[i]; 395*5d517e7eSBarry Smith 396*5d517e7eSBarry Smith /* forward solve the U^T */ 397*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) { 398*5d517e7eSBarry Smith v = aa + a->diag[i] + shift; 399*5d517e7eSBarry Smith vi = aj + a->diag[i] + (!shift); 400*5d517e7eSBarry Smith nz = ai[i+1] - a->diag[i] - 1; 401*5d517e7eSBarry Smith tmp[i] *= *v++; 402*5d517e7eSBarry Smith while (nz--) { 403*5d517e7eSBarry Smith tmp[*vi++ + shift] -= (*v++)*tmp[i]; 404*5d517e7eSBarry Smith } 405*5d517e7eSBarry Smith } 406*5d517e7eSBarry Smith 407*5d517e7eSBarry Smith /* backward solve the L^T */ 408*5d517e7eSBarry Smith for ( i=n-1; i>=0; i-- ){ 409*5d517e7eSBarry Smith v = aa + a->diag[i] - 1 + shift; 410*5d517e7eSBarry Smith vi = aj + a->diag[i] - 1 + shift; 411*5d517e7eSBarry Smith nz = a->diag[i] - ai[i]; 412*5d517e7eSBarry Smith while (nz--) { 413*5d517e7eSBarry Smith tmp[*vi-- + shift] -= (*v--)*tmp[i]; 414*5d517e7eSBarry Smith } 415*5d517e7eSBarry Smith } 416*5d517e7eSBarry Smith 417*5d517e7eSBarry Smith /* copy tmp into x according to permutation */ 418*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) x[r[i]] = tmp[i]; 419*5d517e7eSBarry Smith 420*5d517e7eSBarry Smith ierr = ISRestoreIndices(invisrow,&r); CHKERRQ(ierr); 421*5d517e7eSBarry Smith ierr = ISRestoreIndices(inviscol,&c); CHKERRQ(ierr); 422*5d517e7eSBarry Smith ierr = ISDestroy(invisrow); CHKERRQ(ierr); 423*5d517e7eSBarry Smith ierr = ISDestroy(inviscol); CHKERRQ(ierr); 424*5d517e7eSBarry Smith 425*5d517e7eSBarry Smith PLogFlops(2*a->nz-a->n); 426*5d517e7eSBarry Smith return 0; 427*5d517e7eSBarry Smith } 428*5d517e7eSBarry Smith 429*5d517e7eSBarry Smith int MatSolveTransAdd_SeqAIJ(Mat A,Vec bb, Vec zz,Vec xx) 430*5d517e7eSBarry Smith { 431*5d517e7eSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 432*5d517e7eSBarry Smith IS iscol = a->col, isrow = a->row, invisrow,inviscol; 433*5d517e7eSBarry Smith int *r,*c, ierr, i, n = a->m, *vi, *ai = a->i, *aj = a->j; 434*5d517e7eSBarry Smith int nz,shift = a->indexshift; 435*5d517e7eSBarry Smith Scalar *x,*b,*tmp, *aa = a->a, *v; 436*5d517e7eSBarry Smith 437*5d517e7eSBarry Smith if (A->factor != FACTOR_LU)SETERRQ(1,"MatSolveTransAdd_SeqAIJ:Not unfactored matrix"); 438*5d517e7eSBarry Smith if (zz != xx) VecCopy(zz,xx); 439*5d517e7eSBarry Smith 440*5d517e7eSBarry Smith ierr = VecGetArray(bb,&b); CHKERRQ(ierr); 441*5d517e7eSBarry Smith ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 442*5d517e7eSBarry Smith tmp = a->solve_work; 443*5d517e7eSBarry Smith 444*5d517e7eSBarry Smith /* invert the permutations */ 445*5d517e7eSBarry Smith ierr = ISInvertPermutation(isrow,&invisrow); CHKERRQ(ierr); 446*5d517e7eSBarry Smith ierr = ISInvertPermutation(iscol,&inviscol); CHKERRQ(ierr); 447*5d517e7eSBarry Smith ierr = ISGetIndices(invisrow,&r); CHKERRQ(ierr); 448*5d517e7eSBarry Smith ierr = ISGetIndices(inviscol,&c); CHKERRQ(ierr); 449*5d517e7eSBarry Smith 450*5d517e7eSBarry Smith /* copy the b into temp work space according to permutation */ 451*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) tmp[c[i]] = b[i]; 452*5d517e7eSBarry Smith 453*5d517e7eSBarry Smith /* forward solve the U^T */ 454*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) { 455*5d517e7eSBarry Smith v = aa + a->diag[i] + shift; 456*5d517e7eSBarry Smith vi = aj + a->diag[i] + (!shift); 457*5d517e7eSBarry Smith nz = ai[i+1] - a->diag[i] - 1; 458*5d517e7eSBarry Smith tmp[i] *= *v++; 459*5d517e7eSBarry Smith while (nz--) { 460*5d517e7eSBarry Smith tmp[*vi++ + shift] -= (*v++)*tmp[i]; 461*5d517e7eSBarry Smith } 462*5d517e7eSBarry Smith } 463*5d517e7eSBarry Smith 464*5d517e7eSBarry Smith /* backward solve the L^T */ 465*5d517e7eSBarry Smith for ( i=n-1; i>=0; i-- ){ 466*5d517e7eSBarry Smith v = aa + a->diag[i] - 1 + shift; 467*5d517e7eSBarry Smith vi = aj + a->diag[i] - 1 + shift; 468*5d517e7eSBarry Smith nz = a->diag[i] - ai[i]; 469*5d517e7eSBarry Smith while (nz--) { 470*5d517e7eSBarry Smith tmp[*vi-- + shift] -= (*v--)*tmp[i]; 471*5d517e7eSBarry Smith } 472*5d517e7eSBarry Smith } 473*5d517e7eSBarry Smith 474*5d517e7eSBarry Smith /* copy tmp into x according to permutation */ 475*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) x[r[i]] += tmp[i]; 476*5d517e7eSBarry Smith 477*5d517e7eSBarry Smith ierr = ISRestoreIndices(invisrow,&r); CHKERRQ(ierr); 478*5d517e7eSBarry Smith ierr = ISRestoreIndices(inviscol,&c); CHKERRQ(ierr); 479*5d517e7eSBarry Smith ierr = ISDestroy(invisrow); CHKERRQ(ierr); 480*5d517e7eSBarry Smith ierr = ISDestroy(inviscol); CHKERRQ(ierr); 481*5d517e7eSBarry Smith 482*5d517e7eSBarry Smith PLogFlops(2*a->nz); 483*5d517e7eSBarry Smith return 0; 484*5d517e7eSBarry Smith } 485*5d517e7eSBarry Smith /* ----------------------------------------------------------------*/ 486*5d517e7eSBarry Smith 487*5d517e7eSBarry Smith int MatILUFactorSymbolic_SeqAIJ(Mat A,IS isrow,IS iscol,double f,int levels,Mat *fact) 488*5d517e7eSBarry Smith { 489*5d517e7eSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data, *b; 490*5d517e7eSBarry Smith IS isicol; 491*5d517e7eSBarry Smith int *r,*ic, ierr, prow, n = a->m, *ai = a->i, *aj = a->j; 492*5d517e7eSBarry Smith int *ainew,*ajnew, jmax,*fill, *xi, nz, *im,*ajfill,*flev; 493*5d517e7eSBarry Smith int *dloc, idx, row,m,fm, nzf, nzi,len, realloc = 0; 494*5d517e7eSBarry Smith int incrlev,nnz,i,shift = a->indexshift; 495*5d517e7eSBarry Smith 496*5d517e7eSBarry Smith if (n != a->n) SETERRQ(1,"MatILUFactorSymbolic_SeqAIJ:Matrix must be square"); 497*5d517e7eSBarry Smith if (!isrow) SETERRQ(1,"MatILUFactorSymbolic_SeqAIJ:Must have row permutation"); 498*5d517e7eSBarry Smith if (!iscol) SETERRQ(1,"MatILUFactorSymbolic_SeqAIJ:Must have column permutation"); 499*5d517e7eSBarry Smith 500*5d517e7eSBarry Smith /* special case that simply copies fill pattern */ 501*5d517e7eSBarry Smith if (levels == 0 && ISIsIdentity(isrow) && ISIsIdentity(iscol)) { 502*5d517e7eSBarry Smith ierr = MatConvertSameType_SeqAIJ(A,fact,DO_NOT_COPY_VALUES); CHKERRQ(ierr); 503*5d517e7eSBarry Smith (*fact)->factor = FACTOR_LU; 504*5d517e7eSBarry Smith b = (Mat_SeqAIJ *) (*fact)->data; 505*5d517e7eSBarry Smith if (!b->diag) { 506*5d517e7eSBarry Smith ierr = MatMarkDiag_SeqAIJ(*fact); CHKERRQ(ierr); 507*5d517e7eSBarry Smith } 508*5d517e7eSBarry Smith b->row = isrow; 509*5d517e7eSBarry Smith b->col = iscol; 510*5d517e7eSBarry Smith b->solve_work = (Scalar *) PetscMalloc((b->m+1)*sizeof(Scalar));CHKPTRQ(b->solve_work); 511*5d517e7eSBarry Smith return 0; 512*5d517e7eSBarry Smith } 513*5d517e7eSBarry Smith 514*5d517e7eSBarry Smith ierr = ISInvertPermutation(iscol,&isicol); CHKERRQ(ierr); 515*5d517e7eSBarry Smith ierr = ISGetIndices(isrow,&r); CHKERRQ(ierr); 516*5d517e7eSBarry Smith ierr = ISGetIndices(isicol,&ic); CHKERRQ(ierr); 517*5d517e7eSBarry Smith 518*5d517e7eSBarry Smith /* get new row pointers */ 519*5d517e7eSBarry Smith ainew = (int *) PetscMalloc( (n+1)*sizeof(int) ); CHKPTRQ(ainew); 520*5d517e7eSBarry Smith ainew[0] = -shift; 521*5d517e7eSBarry Smith /* don't know how many column pointers are needed so estimate */ 522*5d517e7eSBarry Smith jmax = (int) (f*(ai[n]+!shift)); 523*5d517e7eSBarry Smith ajnew = (int *) PetscMalloc( (jmax)*sizeof(int) ); CHKPTRQ(ajnew); 524*5d517e7eSBarry Smith /* ajfill is level of fill for each fill entry */ 525*5d517e7eSBarry Smith ajfill = (int *) PetscMalloc( (jmax)*sizeof(int) ); CHKPTRQ(ajfill); 526*5d517e7eSBarry Smith /* fill is a linked list of nonzeros in active row */ 527*5d517e7eSBarry Smith fill = (int *) PetscMalloc( (n+1)*sizeof(int)); CHKPTRQ(fill); 528*5d517e7eSBarry Smith /* im is level for each filled value */ 529*5d517e7eSBarry Smith im = (int *) PetscMalloc( (n+1)*sizeof(int)); CHKPTRQ(im); 530*5d517e7eSBarry Smith /* dloc is location of diagonal in factor */ 531*5d517e7eSBarry Smith dloc = (int *) PetscMalloc( (n+1)*sizeof(int)); CHKPTRQ(dloc); 532*5d517e7eSBarry Smith dloc[0] = 0; 533*5d517e7eSBarry Smith for ( prow=0; prow<n; prow++ ) { 534*5d517e7eSBarry Smith /* first copy previous fill into linked list */ 535*5d517e7eSBarry Smith nzf = nz = ai[r[prow]+1] - ai[r[prow]]; 536*5d517e7eSBarry Smith xi = aj + ai[r[prow]] + shift; 537*5d517e7eSBarry Smith fill[n] = n; 538*5d517e7eSBarry Smith while (nz--) { 539*5d517e7eSBarry Smith fm = n; 540*5d517e7eSBarry Smith idx = ic[*xi++ + shift]; 541*5d517e7eSBarry Smith do { 542*5d517e7eSBarry Smith m = fm; 543*5d517e7eSBarry Smith fm = fill[m]; 544*5d517e7eSBarry Smith } while (fm < idx); 545*5d517e7eSBarry Smith fill[m] = idx; 546*5d517e7eSBarry Smith fill[idx] = fm; 547*5d517e7eSBarry Smith im[idx] = 0; 548*5d517e7eSBarry Smith } 549*5d517e7eSBarry Smith nzi = 0; 550*5d517e7eSBarry Smith row = fill[n]; 551*5d517e7eSBarry Smith while ( row < prow ) { 552*5d517e7eSBarry Smith incrlev = im[row] + 1; 553*5d517e7eSBarry Smith nz = dloc[row]; 554*5d517e7eSBarry Smith xi = ajnew + ainew[row] + shift + nz; 555*5d517e7eSBarry Smith flev = ajfill + ainew[row] + shift + nz + 1; 556*5d517e7eSBarry Smith nnz = ainew[row+1] - ainew[row] - nz - 1; 557*5d517e7eSBarry Smith if (*xi++ + shift != row) { 558*5d517e7eSBarry Smith SETERRQ(1,"MatILUFactorSymbolic_SeqAIJ:zero pivot"); 559*5d517e7eSBarry Smith } 560*5d517e7eSBarry Smith fm = row; 561*5d517e7eSBarry Smith while (nnz-- > 0) { 562*5d517e7eSBarry Smith idx = *xi++ + shift; 563*5d517e7eSBarry Smith if (*flev + incrlev > levels) { 564*5d517e7eSBarry Smith flev++; 565*5d517e7eSBarry Smith continue; 566*5d517e7eSBarry Smith } 567*5d517e7eSBarry Smith do { 568*5d517e7eSBarry Smith m = fm; 569*5d517e7eSBarry Smith fm = fill[m]; 570*5d517e7eSBarry Smith } while (fm < idx); 571*5d517e7eSBarry Smith if (fm != idx) { 572*5d517e7eSBarry Smith im[idx] = *flev + incrlev; 573*5d517e7eSBarry Smith fill[m] = idx; 574*5d517e7eSBarry Smith fill[idx] = fm; 575*5d517e7eSBarry Smith fm = idx; 576*5d517e7eSBarry Smith nzf++; 577*5d517e7eSBarry Smith } 578*5d517e7eSBarry Smith else { 579*5d517e7eSBarry Smith if (im[idx] > *flev + incrlev) im[idx] = *flev+incrlev; 580*5d517e7eSBarry Smith } 581*5d517e7eSBarry Smith flev++; 582*5d517e7eSBarry Smith } 583*5d517e7eSBarry Smith row = fill[row]; 584*5d517e7eSBarry Smith nzi++; 585*5d517e7eSBarry Smith } 586*5d517e7eSBarry Smith /* copy new filled row into permanent storage */ 587*5d517e7eSBarry Smith ainew[prow+1] = ainew[prow] + nzf; 588*5d517e7eSBarry Smith if (ainew[prow+1] > jmax-shift) { 589*5d517e7eSBarry Smith /* allocate a longer ajnew */ 590*5d517e7eSBarry Smith int maxadd; 591*5d517e7eSBarry Smith maxadd = (int) ((f*(ai[n]+!shift)*(n-prow+5))/n); 592*5d517e7eSBarry Smith if (maxadd < nzf) maxadd = (n-prow)*(nzf+1); 593*5d517e7eSBarry Smith jmax += maxadd; 594*5d517e7eSBarry Smith xi = (int *) PetscMalloc( jmax*sizeof(int) );CHKPTRQ(xi); 595*5d517e7eSBarry Smith PetscMemcpy(xi,ajnew,(ainew[prow]+shift)*sizeof(int)); 596*5d517e7eSBarry Smith PetscFree(ajnew); 597*5d517e7eSBarry Smith ajnew = xi; 598*5d517e7eSBarry Smith /* allocate a longer ajfill */ 599*5d517e7eSBarry Smith xi = (int *) PetscMalloc( jmax*sizeof(int) );CHKPTRQ(xi); 600*5d517e7eSBarry Smith PetscMemcpy(xi,ajfill,(ainew[prow]+shift)*sizeof(int)); 601*5d517e7eSBarry Smith PetscFree(ajfill); 602*5d517e7eSBarry Smith ajfill = xi; 603*5d517e7eSBarry Smith realloc++; 604*5d517e7eSBarry Smith } 605*5d517e7eSBarry Smith xi = ajnew + ainew[prow] + shift; 606*5d517e7eSBarry Smith flev = ajfill + ainew[prow] + shift; 607*5d517e7eSBarry Smith dloc[prow] = nzi; 608*5d517e7eSBarry Smith fm = fill[n]; 609*5d517e7eSBarry Smith while (nzf--) { 610*5d517e7eSBarry Smith *xi++ = fm - shift; 611*5d517e7eSBarry Smith *flev++ = im[fm]; 612*5d517e7eSBarry Smith fm = fill[fm]; 613*5d517e7eSBarry Smith } 614*5d517e7eSBarry Smith } 615*5d517e7eSBarry Smith PetscFree(ajfill); 616*5d517e7eSBarry Smith ierr = ISRestoreIndices(isrow,&r); CHKERRQ(ierr); 617*5d517e7eSBarry Smith ierr = ISRestoreIndices(isicol,&ic); CHKERRQ(ierr); 618*5d517e7eSBarry Smith ierr = ISDestroy(isicol); CHKERRQ(ierr); 619*5d517e7eSBarry Smith PetscFree(fill); PetscFree(im); 620*5d517e7eSBarry Smith 621*5d517e7eSBarry Smith PLogInfo((PetscObject)A, 622*5d517e7eSBarry Smith "Info:MatILUFactorSymbolic_SeqAIJ:Realloc %d Fill ratio:given %g needed %g\n", 623*5d517e7eSBarry Smith realloc,f,((double)ainew[n])/((double)ai[prow])); 624*5d517e7eSBarry Smith 625*5d517e7eSBarry Smith /* put together the new matrix */ 626*5d517e7eSBarry Smith ierr = MatCreateSeqAIJ(A->comm,n,n,0,PETSC_NULL,fact); CHKERRQ(ierr); 627*5d517e7eSBarry Smith b = (Mat_SeqAIJ *) (*fact)->data; 628*5d517e7eSBarry Smith PetscFree(b->imax); 629*5d517e7eSBarry Smith b->singlemalloc = 0; 630*5d517e7eSBarry Smith len = (ainew[n] + shift)*sizeof(Scalar); 631*5d517e7eSBarry Smith /* the next line frees the default space generated by the Create() */ 632*5d517e7eSBarry Smith PetscFree(b->a); PetscFree(b->ilen); 633*5d517e7eSBarry Smith b->a = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a); 634*5d517e7eSBarry Smith b->j = ajnew; 635*5d517e7eSBarry Smith b->i = ainew; 636*5d517e7eSBarry Smith for ( i=0; i<n; i++ ) dloc[i] += ainew[i]; 637*5d517e7eSBarry Smith b->diag = dloc; 638*5d517e7eSBarry Smith b->ilen = 0; 639*5d517e7eSBarry Smith b->imax = 0; 640*5d517e7eSBarry Smith b->row = isrow; 641*5d517e7eSBarry Smith b->col = iscol; 642*5d517e7eSBarry Smith b->solve_work = (Scalar *) PetscMalloc( (n+1)*sizeof(Scalar)); 643*5d517e7eSBarry Smith CHKPTRQ(b->solve_work); 644*5d517e7eSBarry Smith /* In b structure: Free imax, ilen, old a, old j. 645*5d517e7eSBarry Smith Allocate dloc, solve_work, new a, new j */ 646*5d517e7eSBarry Smith PLogObjectMemory(*fact,(ainew[n]+shift-n) * (sizeof(int)+sizeof(Scalar))); 647*5d517e7eSBarry Smith b->maxnz = b->nz = ainew[n] + shift; 648*5d517e7eSBarry Smith (*fact)->factor = FACTOR_LU; 649*5d517e7eSBarry Smith return 0; 650*5d517e7eSBarry Smith } 651*5d517e7eSBarry Smith 652*5d517e7eSBarry Smith 653*5d517e7eSBarry Smith 654*5d517e7eSBarry Smith 655