1 /*$Id: aijfact.c,v 1.167 2001/09/11 16:32:26 bsmith Exp $*/ 2 3 #include "src/mat/impls/aij/seq/aij.h" 4 #include "src/vec/vecimpl.h" 5 #include "src/inline/dot.h" 6 7 #undef __FUNCT__ 8 #define __FUNCT__ "MatOrdering_Flow_SeqAIJ" 9 int MatOrdering_Flow_SeqAIJ(Mat mat,MatOrderingType type,IS *irow,IS *icol) 10 { 11 PetscFunctionBegin; 12 13 SETERRQ(PETSC_ERR_SUP,"Code not written"); 14 #if !defined(PETSC_USE_DEBUG) 15 PetscFunctionReturn(0); 16 #endif 17 } 18 19 20 EXTERN int MatMarkDiagonal_SeqAIJ(Mat); 21 EXTERN int Mat_AIJ_CheckInode(Mat,PetscTruth); 22 23 EXTERN int SPARSEKIT2dperm(int*,PetscScalar*,int*,int*,PetscScalar*,int*,int*,int*,int*,int*); 24 EXTERN int SPARSEKIT2ilutp(int*,PetscScalar*,int*,int*,int*,PetscReal,PetscReal*,int*,PetscScalar*,int*,int*,int*,PetscScalar*,int*,int*,int*); 25 EXTERN int SPARSEKIT2msrcsr(int*,PetscScalar*,int*,PetscScalar*,int*,int*,PetscScalar*,int*); 26 27 #undef __FUNCT__ 28 #define __FUNCT__ "MatILUDTFactor_SeqAIJ" 29 /* ------------------------------------------------------------ 30 31 This interface was contribed by Tony Caola 32 33 This routine is an interface to the pivoting drop-tolerance 34 ILU routine written by Yousef Saad (saad@cs.umn.edu) as part of 35 SPARSEKIT2. 36 37 The SPARSEKIT2 routines used here are covered by the GNU 38 copyright; see the file gnu in this directory. 39 40 Thanks to Prof. Saad, Dr. Hysom, and Dr. Smith for their 41 help in getting this routine ironed out. 42 43 The major drawback to this routine is that if info->fill is 44 not large enough it fails rather than allocating more space; 45 this can be fixed by hacking/improving the f2c version of 46 Yousef Saad's code. 47 48 ishift = 0, for indices start at 1 49 ishift = 1, for indices starting at 0 50 ------------------------------------------------------------ 51 */ 52 53 int MatILUDTFactor_SeqAIJ(Mat A,MatILUInfo *info,IS isrow,IS iscol,Mat *fact) 54 { 55 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b; 56 IS iscolf,isicol,isirow; 57 PetscTruth reorder; 58 int *c,*r,*ic,ierr,i,n = A->m; 59 int *old_i = a->i,*old_j = a->j,*new_i,*old_i2 = 0,*old_j2 = 0,*new_j; 60 int *ordcol,*iwk,*iperm,*jw; 61 int ishift = !a->indexshift; 62 int jmax,lfill,job,*o_i,*o_j; 63 PetscScalar *old_a = a->a,*w,*new_a,*old_a2 = 0,*wk,*o_a; 64 PetscReal permtol,af; 65 66 PetscFunctionBegin; 67 68 if (info->dt == PETSC_DEFAULT) info->dt = .005; 69 if (info->dtcount == PETSC_DEFAULT) info->dtcount = (int)(1.5*a->rmax); 70 if (info->dtcol == PETSC_DEFAULT) info->dtcol = .01; 71 if (info->fill == PETSC_DEFAULT) info->fill = ((double)(n*(info->dtcount+1)))/a->nz; 72 lfill = (int)(info->dtcount/2.0); 73 jmax = (int)(info->fill*a->nz); 74 permtol = info->dtcol; 75 76 77 /* ------------------------------------------------------------ 78 If reorder=.TRUE., then the original matrix has to be 79 reordered to reflect the user selected ordering scheme, and 80 then de-reordered so it is in it's original format. 81 Because Saad's dperm() is NOT in place, we have to copy 82 the original matrix and allocate more storage. . . 83 ------------------------------------------------------------ 84 */ 85 86 /* set reorder to true if either isrow or iscol is not identity */ 87 ierr = ISIdentity(isrow,&reorder);CHKERRQ(ierr); 88 if (reorder) {ierr = ISIdentity(iscol,&reorder);CHKERRQ(ierr);} 89 reorder = PetscNot(reorder); 90 91 92 /* storage for ilu factor */ 93 ierr = PetscMalloc((n+1)*sizeof(int),&new_i);CHKERRQ(ierr); 94 ierr = PetscMalloc(jmax*sizeof(int),&new_j);CHKERRQ(ierr); 95 ierr = PetscMalloc(jmax*sizeof(PetscScalar),&new_a);CHKERRQ(ierr); 96 ierr = PetscMalloc(n*sizeof(int),&ordcol);CHKERRQ(ierr); 97 98 /* ------------------------------------------------------------ 99 Make sure that everything is Fortran formatted (1-Based) 100 ------------------------------------------------------------ 101 */ 102 if (ishift) { 103 for (i=old_i[0];i<old_i[n];i++) { 104 old_j[i]++; 105 } 106 for(i=0;i<n+1;i++) { 107 old_i[i]++; 108 }; 109 }; 110 111 if (reorder) { 112 ierr = ISGetIndices(iscol,&c); CHKERRQ(ierr); 113 ierr = ISGetIndices(isrow,&r); CHKERRQ(ierr); 114 for(i=0;i<n;i++) { 115 r[i] = r[i]+1; 116 c[i] = c[i]+1; 117 } 118 ierr = PetscMalloc((n+1)*sizeof(int),&old_i2);CHKERRQ(ierr); 119 ierr = PetscMalloc((old_i[n]-old_i[0]+1)*sizeof(int),&old_j2);CHKERRQ(ierr); 120 ierr = PetscMalloc((old_i[n]-old_i[0]+1)*sizeof(PetscScalar),&old_a2);CHKERRQ(ierr); 121 job = 3; SPARSEKIT2dperm(&n,old_a,old_j,old_i,old_a2,old_j2,old_i2,r,c,&job); 122 for (i=0;i<n;i++) { 123 r[i] = r[i]-1; 124 c[i] = c[i]-1; 125 } 126 ierr = ISRestoreIndices(iscol,&c);CHKERRQ(ierr); 127 ierr = ISRestoreIndices(isrow,&r);CHKERRQ(ierr); 128 o_a = old_a2; 129 o_j = old_j2; 130 o_i = old_i2; 131 } else { 132 o_a = old_a; 133 o_j = old_j; 134 o_i = old_i; 135 } 136 137 /* ------------------------------------------------------------ 138 Call Saad's ilutp() routine to generate the factorization 139 ------------------------------------------------------------ 140 */ 141 142 ierr = PetscMalloc(2*n*sizeof(int),&iperm);CHKERRQ(ierr); 143 ierr = PetscMalloc(2*n*sizeof(int),&jw);CHKERRQ(ierr); 144 ierr = PetscMalloc(n*sizeof(PetscScalar),&w);CHKERRQ(ierr); 145 146 SPARSEKIT2ilutp(&n,o_a,o_j,o_i,&lfill,(PetscReal)info->dt,&permtol,&n,new_a,new_j,new_i,&jmax,w,jw,iperm,&ierr); 147 if (ierr) { 148 switch (ierr) { 149 case -3: SETERRQ2(1,"ilutp(), matrix U overflows, need larger info->fill current fill %g space allocated %d",info->fill,jmax); 150 case -2: SETERRQ2(1,"ilutp(), matrix L overflows, need larger info->fill current fill %g space allocated %d",info->fill,jmax); 151 case -5: SETERRQ(1,"ilutp(), zero row encountered"); 152 case -1: SETERRQ(1,"ilutp(), input matrix may be wrong"); 153 case -4: SETERRQ1(1,"ilutp(), illegal info->fill value %d",jmax); 154 default: SETERRQ1(1,"ilutp(), zero pivot detected on row %d",ierr); 155 } 156 } 157 158 ierr = PetscFree(w);CHKERRQ(ierr); 159 ierr = PetscFree(jw);CHKERRQ(ierr); 160 161 /* ------------------------------------------------------------ 162 Saad's routine gives the result in Modified Sparse Row (msr) 163 Convert to Compressed Sparse Row format (csr) 164 ------------------------------------------------------------ 165 */ 166 167 ierr = PetscMalloc(n*sizeof(PetscScalar),&wk);CHKERRQ(ierr); 168 ierr = PetscMalloc((n+1)*sizeof(int),&iwk);CHKERRQ(ierr); 169 170 SPARSEKIT2msrcsr(&n,new_a,new_j,new_a,new_j,new_i,wk,iwk); 171 172 ierr = PetscFree(iwk);CHKERRQ(ierr); 173 ierr = PetscFree(wk);CHKERRQ(ierr); 174 175 if (reorder) { 176 ierr = PetscFree(old_a2);CHKERRQ(ierr); 177 ierr = PetscFree(old_j2);CHKERRQ(ierr); 178 ierr = PetscFree(old_i2);CHKERRQ(ierr); 179 } else { 180 /* fix permutation of old_j that the factorization introduced */ 181 for (i=old_i[0]; i<old_i[n]; i++) { 182 old_j[i-1] = iperm[old_j[i-1]-1]; 183 } 184 } 185 186 /* get rid of the shift to indices starting at 1 */ 187 if (ishift) { 188 for (i=0; i<n+1; i++) { 189 old_i[i]--; 190 } 191 for (i=old_i[0];i<old_i[n];i++) { 192 old_j[i]--; 193 } 194 } 195 196 /* Make the factored matrix 0-based */ 197 if (ishift) { 198 for (i=0; i<n+1; i++) { 199 new_i[i]--; 200 } 201 for (i=new_i[0];i<new_i[n];i++) { 202 new_j[i]--; 203 } 204 } 205 206 /*-- due to the pivoting, we need to reorder iscol to correctly --*/ 207 /*-- permute the right-hand-side and solution vectors --*/ 208 ierr = ISInvertPermutation(iscol,PETSC_DECIDE,&isicol);CHKERRQ(ierr); 209 ierr = ISInvertPermutation(isrow,PETSC_DECIDE,&isirow);CHKERRQ(ierr); 210 ierr = ISGetIndices(isicol,&ic);CHKERRQ(ierr); 211 for(i=0; i<n; i++) { 212 ordcol[i] = ic[iperm[i]-1]; 213 }; 214 ierr = ISRestoreIndices(isicol,&ic);CHKERRQ(ierr); 215 ierr = ISDestroy(isicol);CHKERRQ(ierr); 216 217 ierr = PetscFree(iperm);CHKERRQ(ierr); 218 219 ierr = ISCreateGeneral(PETSC_COMM_SELF,n,ordcol,&iscolf);CHKERRQ(ierr); 220 ierr = PetscFree(ordcol);CHKERRQ(ierr); 221 222 /*----- put together the new matrix -----*/ 223 224 ierr = MatCreateSeqAIJ(A->comm,n,n,0,PETSC_NULL,fact);CHKERRQ(ierr); 225 (*fact)->factor = FACTOR_LU; 226 (*fact)->assembled = PETSC_TRUE; 227 228 b = (Mat_SeqAIJ*)(*fact)->data; 229 ierr = PetscFree(b->imax);CHKERRQ(ierr); 230 b->sorted = PETSC_FALSE; 231 b->singlemalloc = PETSC_FALSE; 232 /* the next line frees the default space generated by the MatCreate() */ 233 ierr = PetscFree(b->a);CHKERRQ(ierr); 234 ierr = PetscFree(b->ilen);CHKERRQ(ierr); 235 b->a = new_a; 236 b->j = new_j; 237 b->i = new_i; 238 b->ilen = 0; 239 b->imax = 0; 240 /* I am not sure why these are the inverses of the row and column permutations; but the other way is NO GOOD */ 241 b->row = isirow; 242 b->col = iscolf; 243 ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&b->solve_work);CHKERRQ(ierr); 244 b->maxnz = b->nz = new_i[n]; 245 b->indexshift = a->indexshift; 246 ierr = MatMarkDiagonal_SeqAIJ(*fact);CHKERRQ(ierr); 247 (*fact)->info.factor_mallocs = 0; 248 249 ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr); 250 251 /* check out for identical nodes. If found, use inode functions */ 252 ierr = Mat_AIJ_CheckInode(*fact,PETSC_FALSE);CHKERRQ(ierr); 253 254 af = ((double)b->nz)/((double)a->nz) + .001; 255 PetscLogInfo(A,"MatILUDTFactor_SeqAIJ:Fill ratio:given %g needed %g\n",info->fill,af); 256 PetscLogInfo(A,"MatILUDTFactor_SeqAIJ:Run with -pc_ilu_fill %g or use \n",af); 257 PetscLogInfo(A,"MatILUDTFactor_SeqAIJ:PCILUSetFill(pc,%g);\n",af); 258 PetscLogInfo(A,"MatILUDTFactor_SeqAIJ:for best performance.\n"); 259 260 PetscFunctionReturn(0); 261 } 262 263 /* 264 Factorization code for AIJ format. 265 */ 266 #undef __FUNCT__ 267 #define __FUNCT__ "MatLUFactorSymbolic_SeqAIJ" 268 int MatLUFactorSymbolic_SeqAIJ(Mat A,IS isrow,IS iscol,MatLUInfo *info,Mat *B) 269 { 270 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b; 271 IS isicol; 272 int *r,*ic,ierr,i,n = A->m,*ai = a->i,*aj = a->j; 273 int *ainew,*ajnew,jmax,*fill,*ajtmp,nz,shift = a->indexshift; 274 int *idnew,idx,row,m,fm,nnz,nzi,realloc = 0,nzbd,*im; 275 PetscReal f; 276 277 PetscFunctionBegin; 278 if (A->M != A->N) SETERRQ(PETSC_ERR_ARG_WRONG,"matrix must be square"); 279 ierr = ISInvertPermutation(iscol,PETSC_DECIDE,&isicol);CHKERRQ(ierr); 280 ierr = ISGetIndices(isrow,&r);CHKERRQ(ierr); 281 ierr = ISGetIndices(isicol,&ic);CHKERRQ(ierr); 282 283 /* get new row pointers */ 284 ierr = PetscMalloc((n+1)*sizeof(int),&ainew);CHKERRQ(ierr); 285 ainew[0] = -shift; 286 /* don't know how many column pointers are needed so estimate */ 287 if (info) f = info->fill; else f = 1.0; 288 jmax = (int)(f*ai[n]+(!shift)); 289 ierr = PetscMalloc((jmax)*sizeof(int),&ajnew);CHKERRQ(ierr); 290 /* fill is a linked list of nonzeros in active row */ 291 ierr = PetscMalloc((2*n+1)*sizeof(int),&fill);CHKERRQ(ierr); 292 im = fill + n + 1; 293 /* idnew is location of diagonal in factor */ 294 ierr = PetscMalloc((n+1)*sizeof(int),&idnew);CHKERRQ(ierr); 295 idnew[0] = -shift; 296 297 for (i=0; i<n; i++) { 298 /* first copy previous fill into linked list */ 299 nnz = nz = ai[r[i]+1] - ai[r[i]]; 300 if (!nz) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Empty row in matrix"); 301 ajtmp = aj + ai[r[i]] + shift; 302 fill[n] = n; 303 while (nz--) { 304 fm = n; 305 idx = ic[*ajtmp++ + shift]; 306 do { 307 m = fm; 308 fm = fill[m]; 309 } while (fm < idx); 310 fill[m] = idx; 311 fill[idx] = fm; 312 } 313 row = fill[n]; 314 while (row < i) { 315 ajtmp = ajnew + idnew[row] + (!shift); 316 nzbd = 1 + idnew[row] - ainew[row]; 317 nz = im[row] - nzbd; 318 fm = row; 319 while (nz-- > 0) { 320 idx = *ajtmp++ + shift; 321 nzbd++; 322 if (idx == i) im[row] = nzbd; 323 do { 324 m = fm; 325 fm = fill[m]; 326 } while (fm < idx); 327 if (fm != idx) { 328 fill[m] = idx; 329 fill[idx] = fm; 330 fm = idx; 331 nnz++; 332 } 333 } 334 row = fill[row]; 335 } 336 /* copy new filled row into permanent storage */ 337 ainew[i+1] = ainew[i] + nnz; 338 if (ainew[i+1] > jmax) { 339 340 /* estimate how much additional space we will need */ 341 /* use the strategy suggested by David Hysom <hysom@perch-t.icase.edu> */ 342 /* just double the memory each time */ 343 int maxadd = jmax; 344 /* maxadd = (int)((f*(ai[n]+(!shift))*(n-i+5))/n); */ 345 if (maxadd < nnz) maxadd = (n-i)*(nnz+1); 346 jmax += maxadd; 347 348 /* allocate a longer ajnew */ 349 ierr = PetscMalloc(jmax*sizeof(int),&ajtmp);CHKERRQ(ierr); 350 ierr = PetscMemcpy(ajtmp,ajnew,(ainew[i]+shift)*sizeof(int));CHKERRQ(ierr); 351 ierr = PetscFree(ajnew);CHKERRQ(ierr); 352 ajnew = ajtmp; 353 realloc++; /* count how many times we realloc */ 354 } 355 ajtmp = ajnew + ainew[i] + shift; 356 fm = fill[n]; 357 nzi = 0; 358 im[i] = nnz; 359 while (nnz--) { 360 if (fm < i) nzi++; 361 *ajtmp++ = fm - shift; 362 fm = fill[fm]; 363 } 364 idnew[i] = ainew[i] + nzi; 365 } 366 if (ai[n] != 0) { 367 PetscReal af = ((PetscReal)ainew[n])/((PetscReal)ai[n]); 368 PetscLogInfo(A,"MatLUFactorSymbolic_SeqAIJ:Reallocs %d Fill ratio:given %g needed %g\n",realloc,f,af); 369 PetscLogInfo(A,"MatLUFactorSymbolic_SeqAIJ:Run with -pc_lu_fill %g or use \n",af); 370 PetscLogInfo(A,"MatLUFactorSymbolic_SeqAIJ:PCLUSetFill(pc,%g);\n",af); 371 PetscLogInfo(A,"MatLUFactorSymbolic_SeqAIJ:for best performance.\n"); 372 } else { 373 PetscLogInfo(A,"MatLUFactorSymbolic_SeqAIJ: Empty matrix\n"); 374 } 375 376 ierr = ISRestoreIndices(isrow,&r);CHKERRQ(ierr); 377 ierr = ISRestoreIndices(isicol,&ic);CHKERRQ(ierr); 378 379 ierr = PetscFree(fill);CHKERRQ(ierr); 380 381 /* put together the new matrix */ 382 ierr = MatCreateSeqAIJ(A->comm,n,n,0,PETSC_NULL,B);CHKERRQ(ierr); 383 PetscLogObjectParent(*B,isicol); 384 b = (Mat_SeqAIJ*)(*B)->data; 385 ierr = PetscFree(b->imax);CHKERRQ(ierr); 386 b->singlemalloc = PETSC_FALSE; 387 /* the next line frees the default space generated by the Create() */ 388 ierr = PetscFree(b->a);CHKERRQ(ierr); 389 ierr = PetscFree(b->ilen);CHKERRQ(ierr); 390 ierr = PetscMalloc((ainew[n]+shift+1)*sizeof(PetscScalar),&b->a);CHKERRQ(ierr); 391 b->j = ajnew; 392 b->i = ainew; 393 b->diag = idnew; 394 b->ilen = 0; 395 b->imax = 0; 396 b->row = isrow; 397 b->col = iscol; 398 if (info) { 399 b->lu_damp = (PetscTruth) ((int)info->damp); 400 b->lu_damping = info->damping; 401 b->lu_zeropivot = info->zeropivot; 402 } else { 403 b->lu_damp = PETSC_FALSE; 404 b->lu_damping = 0.0; 405 b->lu_zeropivot = 1.e-12; 406 } 407 ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr); 408 ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr); 409 b->icol = isicol; 410 ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&b->solve_work);CHKERRQ(ierr); 411 /* In b structure: Free imax, ilen, old a, old j. 412 Allocate idnew, solve_work, new a, new j */ 413 PetscLogObjectMemory(*B,(ainew[n]+shift-n)*(sizeof(int)+sizeof(PetscScalar))); 414 b->maxnz = b->nz = ainew[n] + shift; 415 416 (*B)->factor = FACTOR_LU; 417 (*B)->info.factor_mallocs = realloc; 418 (*B)->info.fill_ratio_given = f; 419 ierr = Mat_AIJ_CheckInode(*B,PETSC_FALSE);CHKERRQ(ierr); 420 (*B)->ops->lufactornumeric = A->ops->lufactornumeric; /* Use Inode variant ONLY if A has inodes */ 421 422 if (ai[n] != 0) { 423 (*B)->info.fill_ratio_needed = ((PetscReal)ainew[n])/((PetscReal)ai[n]); 424 } else { 425 (*B)->info.fill_ratio_needed = 0.0; 426 } 427 PetscFunctionReturn(0); 428 } 429 /* ----------------------------------------------------------- */ 430 EXTERN int Mat_AIJ_CheckInode(Mat,PetscTruth); 431 432 #undef __FUNCT__ 433 #define __FUNCT__ "MatLUFactorNumeric_SeqAIJ" 434 int MatLUFactorNumeric_SeqAIJ(Mat A,Mat *B) 435 { 436 Mat C = *B; 437 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ *)C->data; 438 IS isrow = b->row,isicol = b->icol; 439 int *r,*ic,ierr,i,j,n = A->m,*ai = b->i,*aj = b->j; 440 int *ajtmpold,*ajtmp,nz,row,*ics,shift = a->indexshift; 441 int *diag_offset = b->diag,diag; 442 int *pj,ndamp = 0; 443 PetscScalar *rtmp,*v,*pc,multiplier,*pv,*rtmps; 444 PetscReal damping = b->lu_damping, zeropivot = b->lu_zeropivot; 445 PetscTruth damp; 446 447 PetscFunctionBegin; 448 ierr = ISGetIndices(isrow,&r);CHKERRQ(ierr); 449 ierr = ISGetIndices(isicol,&ic);CHKERRQ(ierr); 450 ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&rtmp);CHKERRQ(ierr); 451 ierr = PetscMemzero(rtmp,(n+1)*sizeof(PetscScalar));CHKERRQ(ierr); 452 rtmps = rtmp + shift; ics = ic + shift; 453 454 do { 455 damp = PETSC_FALSE; 456 for (i=0; i<n; i++) { 457 nz = ai[i+1] - ai[i]; 458 ajtmp = aj + ai[i] + shift; 459 for (j=0; j<nz; j++) rtmps[ajtmp[j]] = 0.0; 460 461 /* load in initial (unfactored row) */ 462 nz = a->i[r[i]+1] - a->i[r[i]]; 463 ajtmpold = a->j + a->i[r[i]] + shift; 464 v = a->a + a->i[r[i]] + shift; 465 for (j=0; j<nz; j++) { 466 rtmp[ics[ajtmpold[j]]] = v[j]; 467 if (ajtmpold[j] == r[i]) { /* damp the diagonal of the matrix */ 468 rtmp[ics[ajtmpold[j]]] += damping; 469 } 470 } 471 472 row = *ajtmp++ + shift; 473 while (row < i) { 474 pc = rtmp + row; 475 if (*pc != 0.0) { 476 pv = b->a + diag_offset[row] + shift; 477 pj = b->j + diag_offset[row] + (!shift); 478 multiplier = *pc / *pv++; 479 *pc = multiplier; 480 nz = ai[row+1] - diag_offset[row] - 1; 481 for (j=0; j<nz; j++) rtmps[pj[j]] -= multiplier * pv[j]; 482 PetscLogFlops(2*nz); 483 } 484 row = *ajtmp++ + shift; 485 } 486 /* finished row so stick it into b->a */ 487 pv = b->a + ai[i] + shift; 488 pj = b->j + ai[i] + shift; 489 nz = ai[i+1] - ai[i]; 490 for (j=0; j<nz; j++) {pv[j] = rtmps[pj[j]];} 491 diag = diag_offset[i] - ai[i]; 492 if (PetscAbsScalar(pv[diag]) < zeropivot) { 493 if (b->lu_damp) { 494 damp = PETSC_TRUE; 495 if (damping) damping *= 2.0; 496 else damping = 1.e-12; 497 ndamp++; 498 break; 499 } else { 500 SETERRQ3(PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot row %d value %g tolerance %g",i,PetscAbsScalar(pv[diag]),zeropivot); 501 } 502 } 503 } 504 } while (damp); 505 506 /* invert diagonal entries for simplier triangular solves */ 507 for (i=0; i<n; i++) { 508 b->a[diag_offset[i]+shift] = 1.0/b->a[diag_offset[i]+shift]; 509 } 510 511 ierr = PetscFree(rtmp);CHKERRQ(ierr); 512 ierr = ISRestoreIndices(isicol,&ic);CHKERRQ(ierr); 513 ierr = ISRestoreIndices(isrow,&r);CHKERRQ(ierr); 514 C->factor = FACTOR_LU; 515 (*B)->ops->lufactornumeric = A->ops->lufactornumeric; /* Use Inode variant ONLY if A has inodes */ 516 C->assembled = PETSC_TRUE; 517 PetscLogFlops(C->n); 518 if (ndamp || b->lu_damping) { 519 PetscLogInfo(0,"MatLUFactorNumerical_SeqAIJ: number of damping tries %d damping value %g\n",ndamp,damping); 520 } 521 PetscFunctionReturn(0); 522 } 523 /* ----------------------------------------------------------- */ 524 #undef __FUNCT__ 525 #define __FUNCT__ "MatLUFactor_SeqAIJ" 526 int MatLUFactor_SeqAIJ(Mat A,IS row,IS col,MatLUInfo *info) 527 { 528 int ierr; 529 Mat C; 530 531 PetscFunctionBegin; 532 ierr = MatLUFactorSymbolic(A,row,col,info,&C);CHKERRQ(ierr); 533 ierr = MatLUFactorNumeric(A,&C);CHKERRQ(ierr); 534 ierr = MatHeaderCopy(A,C);CHKERRQ(ierr); 535 PetscLogObjectParent(A,((Mat_SeqAIJ*)(A->data))->icol); 536 PetscFunctionReturn(0); 537 } 538 /* ----------------------------------------------------------- */ 539 #undef __FUNCT__ 540 #define __FUNCT__ "MatSolve_SeqAIJ" 541 int MatSolve_SeqAIJ(Mat A,Vec bb,Vec xx) 542 { 543 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 544 IS iscol = a->col,isrow = a->row; 545 int *r,*c,ierr,i, n = A->m,*vi,*ai = a->i,*aj = a->j; 546 int nz,shift = a->indexshift,*rout,*cout; 547 PetscScalar *x,*b,*tmp,*tmps,*aa = a->a,sum,*v; 548 549 PetscFunctionBegin; 550 if (!n) PetscFunctionReturn(0); 551 552 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 553 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 554 tmp = a->solve_work; 555 556 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 557 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout + (n-1); 558 559 /* forward solve the lower triangular */ 560 tmp[0] = b[*r++]; 561 tmps = tmp + shift; 562 for (i=1; i<n; i++) { 563 v = aa + ai[i] + shift; 564 vi = aj + ai[i] + shift; 565 nz = a->diag[i] - ai[i]; 566 sum = b[*r++]; 567 while (nz--) sum -= *v++ * tmps[*vi++]; 568 tmp[i] = sum; 569 } 570 571 /* backward solve the upper triangular */ 572 for (i=n-1; i>=0; i--){ 573 v = aa + a->diag[i] + (!shift); 574 vi = aj + a->diag[i] + (!shift); 575 nz = ai[i+1] - a->diag[i] - 1; 576 sum = tmp[i]; 577 while (nz--) sum -= *v++ * tmps[*vi++]; 578 x[*c--] = tmp[i] = sum*aa[a->diag[i]+shift]; 579 } 580 581 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 582 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 583 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 584 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 585 PetscLogFlops(2*a->nz - A->n); 586 PetscFunctionReturn(0); 587 } 588 589 /* ----------------------------------------------------------- */ 590 #undef __FUNCT__ 591 #define __FUNCT__ "MatSolve_SeqAIJ_NaturalOrdering" 592 int MatSolve_SeqAIJ_NaturalOrdering(Mat A,Vec bb,Vec xx) 593 { 594 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 595 int n = A->m,*ai = a->i,*aj = a->j,*adiag = a->diag,ierr; 596 PetscScalar *x,*b,*aa = a->a,sum; 597 #if !defined(PETSC_USE_FORTRAN_KERNEL_SOLVEAIJ) 598 int adiag_i,i,*vi,nz,ai_i; 599 PetscScalar *v; 600 #endif 601 602 PetscFunctionBegin; 603 if (!n) PetscFunctionReturn(0); 604 if (a->indexshift) { 605 ierr = MatSolve_SeqAIJ(A,bb,xx);CHKERRQ(ierr); 606 PetscFunctionReturn(0); 607 } 608 609 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 610 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 611 612 #if defined(PETSC_USE_FORTRAN_KERNEL_SOLVEAIJ) 613 fortransolveaij_(&n,x,ai,aj,adiag,aa,b); 614 #else 615 /* forward solve the lower triangular */ 616 x[0] = b[0]; 617 for (i=1; i<n; i++) { 618 ai_i = ai[i]; 619 v = aa + ai_i; 620 vi = aj + ai_i; 621 nz = adiag[i] - ai_i; 622 sum = b[i]; 623 while (nz--) sum -= *v++ * x[*vi++]; 624 x[i] = sum; 625 } 626 627 /* backward solve the upper triangular */ 628 for (i=n-1; i>=0; i--){ 629 adiag_i = adiag[i]; 630 v = aa + adiag_i + 1; 631 vi = aj + adiag_i + 1; 632 nz = ai[i+1] - adiag_i - 1; 633 sum = x[i]; 634 while (nz--) sum -= *v++ * x[*vi++]; 635 x[i] = sum*aa[adiag_i]; 636 } 637 #endif 638 PetscLogFlops(2*a->nz - A->n); 639 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 640 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 641 PetscFunctionReturn(0); 642 } 643 644 #undef __FUNCT__ 645 #define __FUNCT__ "MatSolveAdd_SeqAIJ" 646 int MatSolveAdd_SeqAIJ(Mat A,Vec bb,Vec yy,Vec xx) 647 { 648 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 649 IS iscol = a->col,isrow = a->row; 650 int *r,*c,ierr,i, n = A->m,*vi,*ai = a->i,*aj = a->j; 651 int nz,shift = a->indexshift,*rout,*cout; 652 PetscScalar *x,*b,*tmp,*aa = a->a,sum,*v; 653 654 PetscFunctionBegin; 655 if (yy != xx) {ierr = VecCopy(yy,xx);CHKERRQ(ierr);} 656 657 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 658 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 659 tmp = a->solve_work; 660 661 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 662 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout + (n-1); 663 664 /* forward solve the lower triangular */ 665 tmp[0] = b[*r++]; 666 for (i=1; i<n; i++) { 667 v = aa + ai[i] + shift; 668 vi = aj + ai[i] + shift; 669 nz = a->diag[i] - ai[i]; 670 sum = b[*r++]; 671 while (nz--) sum -= *v++ * tmp[*vi++ + shift]; 672 tmp[i] = sum; 673 } 674 675 /* backward solve the upper triangular */ 676 for (i=n-1; i>=0; i--){ 677 v = aa + a->diag[i] + (!shift); 678 vi = aj + a->diag[i] + (!shift); 679 nz = ai[i+1] - a->diag[i] - 1; 680 sum = tmp[i]; 681 while (nz--) sum -= *v++ * tmp[*vi++ + shift]; 682 tmp[i] = sum*aa[a->diag[i]+shift]; 683 x[*c--] += tmp[i]; 684 } 685 686 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 687 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 688 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 689 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 690 PetscLogFlops(2*a->nz); 691 692 PetscFunctionReturn(0); 693 } 694 /* -------------------------------------------------------------------*/ 695 #undef __FUNCT__ 696 #define __FUNCT__ "MatSolveTranspose_SeqAIJ" 697 int MatSolveTranspose_SeqAIJ(Mat A,Vec bb,Vec xx) 698 { 699 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 700 IS iscol = a->col,isrow = a->row; 701 int *r,*c,ierr,i,n = A->m,*vi,*ai = a->i,*aj = a->j; 702 int nz,shift = a->indexshift,*rout,*cout,*diag = a->diag; 703 PetscScalar *x,*b,*tmp,*aa = a->a,*v,s1; 704 705 PetscFunctionBegin; 706 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 707 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 708 tmp = a->solve_work; 709 710 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 711 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout; 712 713 /* copy the b into temp work space according to permutation */ 714 for (i=0; i<n; i++) tmp[i] = b[c[i]]; 715 716 /* forward solve the U^T */ 717 for (i=0; i<n; i++) { 718 v = aa + diag[i] + shift; 719 vi = aj + diag[i] + (!shift); 720 nz = ai[i+1] - diag[i] - 1; 721 s1 = tmp[i]; 722 s1 *= (*v++); /* multiply by inverse of diagonal entry */ 723 while (nz--) { 724 tmp[*vi++ + shift] -= (*v++)*s1; 725 } 726 tmp[i] = s1; 727 } 728 729 /* backward solve the L^T */ 730 for (i=n-1; i>=0; i--){ 731 v = aa + diag[i] - 1 + shift; 732 vi = aj + diag[i] - 1 + shift; 733 nz = diag[i] - ai[i]; 734 s1 = tmp[i]; 735 while (nz--) { 736 tmp[*vi-- + shift] -= (*v--)*s1; 737 } 738 } 739 740 /* copy tmp into x according to permutation */ 741 for (i=0; i<n; i++) x[r[i]] = tmp[i]; 742 743 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 744 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 745 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 746 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 747 748 PetscLogFlops(2*a->nz-A->n); 749 PetscFunctionReturn(0); 750 } 751 752 #undef __FUNCT__ 753 #define __FUNCT__ "MatSolveTransposeAdd_SeqAIJ" 754 int MatSolveTransposeAdd_SeqAIJ(Mat A,Vec bb,Vec zz,Vec xx) 755 { 756 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 757 IS iscol = a->col,isrow = a->row; 758 int *r,*c,ierr,i,n = A->m,*vi,*ai = a->i,*aj = a->j; 759 int nz,shift = a->indexshift,*rout,*cout,*diag = a->diag; 760 PetscScalar *x,*b,*tmp,*aa = a->a,*v; 761 762 PetscFunctionBegin; 763 if (zz != xx) VecCopy(zz,xx); 764 765 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 766 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 767 tmp = a->solve_work; 768 769 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 770 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout; 771 772 /* copy the b into temp work space according to permutation */ 773 for (i=0; i<n; i++) tmp[i] = b[c[i]]; 774 775 /* forward solve the U^T */ 776 for (i=0; i<n; i++) { 777 v = aa + diag[i] + shift; 778 vi = aj + diag[i] + (!shift); 779 nz = ai[i+1] - diag[i] - 1; 780 tmp[i] *= *v++; 781 while (nz--) { 782 tmp[*vi++ + shift] -= (*v++)*tmp[i]; 783 } 784 } 785 786 /* backward solve the L^T */ 787 for (i=n-1; i>=0; i--){ 788 v = aa + diag[i] - 1 + shift; 789 vi = aj + diag[i] - 1 + shift; 790 nz = diag[i] - ai[i]; 791 while (nz--) { 792 tmp[*vi-- + shift] -= (*v--)*tmp[i]; 793 } 794 } 795 796 /* copy tmp into x according to permutation */ 797 for (i=0; i<n; i++) x[r[i]] += tmp[i]; 798 799 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 800 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 801 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 802 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 803 804 PetscLogFlops(2*a->nz); 805 PetscFunctionReturn(0); 806 } 807 /* ----------------------------------------------------------------*/ 808 EXTERN int MatMissingDiagonal_SeqAIJ(Mat); 809 810 #undef __FUNCT__ 811 #define __FUNCT__ "MatILUFactorSymbolic_SeqAIJ" 812 int MatILUFactorSymbolic_SeqAIJ(Mat A,IS isrow,IS iscol,MatILUInfo *info,Mat *fact) 813 { 814 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b; 815 IS isicol; 816 int *r,*ic,ierr,prow,n = A->m,*ai = a->i,*aj = a->j; 817 int *ainew,*ajnew,jmax,*fill,*xi,nz,*im,*ajfill,*flev; 818 int *dloc,idx,row,m,fm,nzf,nzi,len, realloc = 0,dcount = 0; 819 int incrlev,nnz,i,shift = a->indexshift,levels,diagonal_fill; 820 PetscTruth col_identity,row_identity; 821 PetscReal f; 822 823 PetscFunctionBegin; 824 if (info) { 825 f = info->fill; 826 levels = (int)info->levels; 827 diagonal_fill = (int)info->diagonal_fill; 828 } else { 829 f = 1.0; 830 levels = 0; 831 diagonal_fill = 0; 832 } 833 ierr = ISInvertPermutation(iscol,PETSC_DECIDE,&isicol);CHKERRQ(ierr); 834 835 /* special case that simply copies fill pattern */ 836 ierr = ISIdentity(isrow,&row_identity);CHKERRQ(ierr); 837 ierr = ISIdentity(iscol,&col_identity);CHKERRQ(ierr); 838 if (!levels && row_identity && col_identity) { 839 ierr = MatDuplicate_SeqAIJ(A,MAT_DO_NOT_COPY_VALUES,fact);CHKERRQ(ierr); 840 (*fact)->factor = FACTOR_LU; 841 b = (Mat_SeqAIJ*)(*fact)->data; 842 if (!b->diag) { 843 ierr = MatMarkDiagonal_SeqAIJ(*fact);CHKERRQ(ierr); 844 } 845 ierr = MatMissingDiagonal_SeqAIJ(*fact);CHKERRQ(ierr); 846 b->row = isrow; 847 b->col = iscol; 848 b->icol = isicol; 849 if (info) { 850 b->lu_damp = (PetscTruth)((int)info->damp); 851 b->lu_damping = info->damping; 852 b->lu_zeropivot = info->zeropivot; 853 } else { 854 b->lu_damp = PETSC_FALSE; 855 b->lu_damping = 0.0; 856 b->lu_zeropivot = 1.e-12; 857 } 858 ierr = PetscMalloc(((*fact)->m+1)*sizeof(PetscScalar),&b->solve_work);CHKERRQ(ierr); 859 (*fact)->ops->solve = MatSolve_SeqAIJ_NaturalOrdering; 860 ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr); 861 ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr); 862 PetscFunctionReturn(0); 863 } 864 865 ierr = ISGetIndices(isrow,&r);CHKERRQ(ierr); 866 ierr = ISGetIndices(isicol,&ic);CHKERRQ(ierr); 867 868 /* get new row pointers */ 869 ierr = PetscMalloc((n+1)*sizeof(int),&ainew);CHKERRQ(ierr); 870 ainew[0] = -shift; 871 /* don't know how many column pointers are needed so estimate */ 872 jmax = (int)(f*(ai[n]+!shift)); 873 ierr = PetscMalloc((jmax)*sizeof(int),&ajnew);CHKERRQ(ierr); 874 /* ajfill is level of fill for each fill entry */ 875 ierr = PetscMalloc((jmax)*sizeof(int),&ajfill);CHKERRQ(ierr); 876 /* fill is a linked list of nonzeros in active row */ 877 ierr = PetscMalloc((n+1)*sizeof(int),&fill);CHKERRQ(ierr); 878 /* im is level for each filled value */ 879 ierr = PetscMalloc((n+1)*sizeof(int),&im);CHKERRQ(ierr); 880 /* dloc is location of diagonal in factor */ 881 ierr = PetscMalloc((n+1)*sizeof(int),&dloc);CHKERRQ(ierr); 882 dloc[0] = 0; 883 for (prow=0; prow<n; prow++) { 884 885 /* copy current row into linked list */ 886 nzf = nz = ai[r[prow]+1] - ai[r[prow]]; 887 if (!nz) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Empty row in matrix"); 888 xi = aj + ai[r[prow]] + shift; 889 fill[n] = n; 890 fill[prow] = -1; /* marker to indicate if diagonal exists */ 891 while (nz--) { 892 fm = n; 893 idx = ic[*xi++ + shift]; 894 do { 895 m = fm; 896 fm = fill[m]; 897 } while (fm < idx); 898 fill[m] = idx; 899 fill[idx] = fm; 900 im[idx] = 0; 901 } 902 903 /* make sure diagonal entry is included */ 904 if (diagonal_fill && fill[prow] == -1) { 905 fm = n; 906 while (fill[fm] < prow) fm = fill[fm]; 907 fill[prow] = fill[fm]; /* insert diagonal into linked list */ 908 fill[fm] = prow; 909 im[prow] = 0; 910 nzf++; 911 dcount++; 912 } 913 914 nzi = 0; 915 row = fill[n]; 916 while (row < prow) { 917 incrlev = im[row] + 1; 918 nz = dloc[row]; 919 xi = ajnew + ainew[row] + shift + nz + 1; 920 flev = ajfill + ainew[row] + shift + nz + 1; 921 nnz = ainew[row+1] - ainew[row] - nz - 1; 922 fm = row; 923 while (nnz-- > 0) { 924 idx = *xi++ + shift; 925 if (*flev + incrlev > levels) { 926 flev++; 927 continue; 928 } 929 do { 930 m = fm; 931 fm = fill[m]; 932 } while (fm < idx); 933 if (fm != idx) { 934 im[idx] = *flev + incrlev; 935 fill[m] = idx; 936 fill[idx] = fm; 937 fm = idx; 938 nzf++; 939 } else { 940 if (im[idx] > *flev + incrlev) im[idx] = *flev+incrlev; 941 } 942 flev++; 943 } 944 row = fill[row]; 945 nzi++; 946 } 947 /* copy new filled row into permanent storage */ 948 ainew[prow+1] = ainew[prow] + nzf; 949 if (ainew[prow+1] > jmax-shift) { 950 951 /* estimate how much additional space we will need */ 952 /* use the strategy suggested by David Hysom <hysom@perch-t.icase.edu> */ 953 /* just double the memory each time */ 954 /* maxadd = (int)((f*(ai[n]+!shift)*(n-prow+5))/n); */ 955 int maxadd = jmax; 956 if (maxadd < nzf) maxadd = (n-prow)*(nzf+1); 957 jmax += maxadd; 958 959 /* allocate a longer ajnew and ajfill */ 960 ierr = PetscMalloc(jmax*sizeof(int),&xi);CHKERRQ(ierr); 961 ierr = PetscMemcpy(xi,ajnew,(ainew[prow]+shift)*sizeof(int));CHKERRQ(ierr); 962 ierr = PetscFree(ajnew);CHKERRQ(ierr); 963 ajnew = xi; 964 ierr = PetscMalloc(jmax*sizeof(int),&xi);CHKERRQ(ierr); 965 ierr = PetscMemcpy(xi,ajfill,(ainew[prow]+shift)*sizeof(int));CHKERRQ(ierr); 966 ierr = PetscFree(ajfill);CHKERRQ(ierr); 967 ajfill = xi; 968 realloc++; /* count how many times we realloc */ 969 } 970 xi = ajnew + ainew[prow] + shift; 971 flev = ajfill + ainew[prow] + shift; 972 dloc[prow] = nzi; 973 fm = fill[n]; 974 while (nzf--) { 975 *xi++ = fm - shift; 976 *flev++ = im[fm]; 977 fm = fill[fm]; 978 } 979 /* make sure row has diagonal entry */ 980 if (ajnew[ainew[prow]+shift+dloc[prow]]+shift != prow) { 981 SETERRQ1(PETSC_ERR_MAT_LU_ZRPVT,"Row %d has missing diagonal in factored matrix\n\ 982 try running with -pc_ilu_nonzeros_along_diagonal or -pc_ilu_diagonal_fill",prow); 983 } 984 } 985 ierr = PetscFree(ajfill);CHKERRQ(ierr); 986 ierr = ISRestoreIndices(isrow,&r);CHKERRQ(ierr); 987 ierr = ISRestoreIndices(isicol,&ic);CHKERRQ(ierr); 988 ierr = PetscFree(fill);CHKERRQ(ierr); 989 ierr = PetscFree(im);CHKERRQ(ierr); 990 991 { 992 PetscReal af = ((PetscReal)ainew[n])/((PetscReal)ai[n]); 993 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:Reallocs %d Fill ratio:given %g needed %g\n",realloc,f,af); 994 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:Run with -[sub_]pc_ilu_fill %g or use \n",af); 995 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:PCILUSetFill([sub]pc,%g);\n",af); 996 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:for best performance.\n"); 997 if (diagonal_fill) { 998 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:Detected and replaced %d missing diagonals",dcount); 999 } 1000 } 1001 1002 /* put together the new matrix */ 1003 ierr = MatCreateSeqAIJ(A->comm,n,n,0,PETSC_NULL,fact);CHKERRQ(ierr); 1004 PetscLogObjectParent(*fact,isicol); 1005 b = (Mat_SeqAIJ*)(*fact)->data; 1006 ierr = PetscFree(b->imax);CHKERRQ(ierr); 1007 b->singlemalloc = PETSC_FALSE; 1008 len = (ainew[n] + shift)*sizeof(PetscScalar); 1009 /* the next line frees the default space generated by the Create() */ 1010 ierr = PetscFree(b->a);CHKERRQ(ierr); 1011 ierr = PetscFree(b->ilen);CHKERRQ(ierr); 1012 ierr = PetscMalloc(len+1,&b->a);CHKERRQ(ierr); 1013 b->j = ajnew; 1014 b->i = ainew; 1015 for (i=0; i<n; i++) dloc[i] += ainew[i]; 1016 b->diag = dloc; 1017 b->ilen = 0; 1018 b->imax = 0; 1019 b->row = isrow; 1020 b->col = iscol; 1021 ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr); 1022 ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr); 1023 b->icol = isicol; 1024 ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&b->solve_work);CHKERRQ(ierr); 1025 /* In b structure: Free imax, ilen, old a, old j. 1026 Allocate dloc, solve_work, new a, new j */ 1027 PetscLogObjectMemory(*fact,(ainew[n]+shift-n) * (sizeof(int)+sizeof(PetscScalar))); 1028 b->maxnz = b->nz = ainew[n] + shift; 1029 if (info) { 1030 b->lu_damp = (PetscTruth)((int)info->damp); 1031 b->lu_damping = info->damping; 1032 b->lu_zeropivot = info->zeropivot; 1033 } else { 1034 b->lu_damp = PETSC_FALSE; 1035 b->lu_damping = 0.0; 1036 b->lu_zeropivot = 1.e-12; 1037 } 1038 (*fact)->factor = FACTOR_LU; 1039 ierr = Mat_AIJ_CheckInode(*fact,PETSC_FALSE);CHKERRQ(ierr); 1040 (*fact)->ops->lufactornumeric = A->ops->lufactornumeric; /* Use Inode variant ONLY if A has inodes */ 1041 1042 (*fact)->info.factor_mallocs = realloc; 1043 (*fact)->info.fill_ratio_given = f; 1044 (*fact)->info.fill_ratio_needed = ((PetscReal)ainew[n])/((PetscReal)ai[prow]); 1045 (*fact)->factor = FACTOR_LU; 1046 PetscFunctionReturn(0); 1047 } 1048 1049 1050 1051 1052