1 /*$Id: aijfact.c,v 1.165 2001/08/07 03:02:47 balay Exp bsmith $*/ 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 PetscFunctionReturn(0); 536 } 537 /* ----------------------------------------------------------- */ 538 #undef __FUNCT__ 539 #define __FUNCT__ "MatSolve_SeqAIJ" 540 int MatSolve_SeqAIJ(Mat A,Vec bb,Vec xx) 541 { 542 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 543 IS iscol = a->col,isrow = a->row; 544 int *r,*c,ierr,i, n = A->m,*vi,*ai = a->i,*aj = a->j; 545 int nz,shift = a->indexshift,*rout,*cout; 546 PetscScalar *x,*b,*tmp,*tmps,*aa = a->a,sum,*v; 547 548 PetscFunctionBegin; 549 if (!n) PetscFunctionReturn(0); 550 551 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 552 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 553 tmp = a->solve_work; 554 555 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 556 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout + (n-1); 557 558 /* forward solve the lower triangular */ 559 tmp[0] = b[*r++]; 560 tmps = tmp + shift; 561 for (i=1; i<n; i++) { 562 v = aa + ai[i] + shift; 563 vi = aj + ai[i] + shift; 564 nz = a->diag[i] - ai[i]; 565 sum = b[*r++]; 566 while (nz--) sum -= *v++ * tmps[*vi++]; 567 tmp[i] = sum; 568 } 569 570 /* backward solve the upper triangular */ 571 for (i=n-1; i>=0; i--){ 572 v = aa + a->diag[i] + (!shift); 573 vi = aj + a->diag[i] + (!shift); 574 nz = ai[i+1] - a->diag[i] - 1; 575 sum = tmp[i]; 576 while (nz--) sum -= *v++ * tmps[*vi++]; 577 x[*c--] = tmp[i] = sum*aa[a->diag[i]+shift]; 578 } 579 580 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 581 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 582 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 583 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 584 PetscLogFlops(2*a->nz - A->n); 585 PetscFunctionReturn(0); 586 } 587 588 /* ----------------------------------------------------------- */ 589 #undef __FUNCT__ 590 #define __FUNCT__ "MatSolve_SeqAIJ_NaturalOrdering" 591 int MatSolve_SeqAIJ_NaturalOrdering(Mat A,Vec bb,Vec xx) 592 { 593 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 594 int n = A->m,*ai = a->i,*aj = a->j,*adiag = a->diag,ierr; 595 PetscScalar *x,*b,*aa = a->a,sum; 596 #if !defined(PETSC_USE_FORTRAN_KERNEL_SOLVEAIJ) 597 int adiag_i,i,*vi,nz,ai_i; 598 PetscScalar *v; 599 #endif 600 601 PetscFunctionBegin; 602 if (!n) PetscFunctionReturn(0); 603 if (a->indexshift) { 604 ierr = MatSolve_SeqAIJ(A,bb,xx);CHKERRQ(ierr); 605 PetscFunctionReturn(0); 606 } 607 608 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 609 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 610 611 #if defined(PETSC_USE_FORTRAN_KERNEL_SOLVEAIJ) 612 fortransolveaij_(&n,x,ai,aj,adiag,aa,b); 613 #else 614 /* forward solve the lower triangular */ 615 x[0] = b[0]; 616 for (i=1; i<n; i++) { 617 ai_i = ai[i]; 618 v = aa + ai_i; 619 vi = aj + ai_i; 620 nz = adiag[i] - ai_i; 621 sum = b[i]; 622 while (nz--) sum -= *v++ * x[*vi++]; 623 x[i] = sum; 624 } 625 626 /* backward solve the upper triangular */ 627 for (i=n-1; i>=0; i--){ 628 adiag_i = adiag[i]; 629 v = aa + adiag_i + 1; 630 vi = aj + adiag_i + 1; 631 nz = ai[i+1] - adiag_i - 1; 632 sum = x[i]; 633 while (nz--) sum -= *v++ * x[*vi++]; 634 x[i] = sum*aa[adiag_i]; 635 } 636 #endif 637 PetscLogFlops(2*a->nz - A->n); 638 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 639 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 640 PetscFunctionReturn(0); 641 } 642 643 #undef __FUNCT__ 644 #define __FUNCT__ "MatSolveAdd_SeqAIJ" 645 int MatSolveAdd_SeqAIJ(Mat A,Vec bb,Vec yy,Vec xx) 646 { 647 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 648 IS iscol = a->col,isrow = a->row; 649 int *r,*c,ierr,i, n = A->m,*vi,*ai = a->i,*aj = a->j; 650 int nz,shift = a->indexshift,*rout,*cout; 651 PetscScalar *x,*b,*tmp,*aa = a->a,sum,*v; 652 653 PetscFunctionBegin; 654 if (yy != xx) {ierr = VecCopy(yy,xx);CHKERRQ(ierr);} 655 656 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 657 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 658 tmp = a->solve_work; 659 660 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 661 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout + (n-1); 662 663 /* forward solve the lower triangular */ 664 tmp[0] = b[*r++]; 665 for (i=1; i<n; i++) { 666 v = aa + ai[i] + shift; 667 vi = aj + ai[i] + shift; 668 nz = a->diag[i] - ai[i]; 669 sum = b[*r++]; 670 while (nz--) sum -= *v++ * tmp[*vi++ + shift]; 671 tmp[i] = sum; 672 } 673 674 /* backward solve the upper triangular */ 675 for (i=n-1; i>=0; i--){ 676 v = aa + a->diag[i] + (!shift); 677 vi = aj + a->diag[i] + (!shift); 678 nz = ai[i+1] - a->diag[i] - 1; 679 sum = tmp[i]; 680 while (nz--) sum -= *v++ * tmp[*vi++ + shift]; 681 tmp[i] = sum*aa[a->diag[i]+shift]; 682 x[*c--] += tmp[i]; 683 } 684 685 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 686 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 687 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 688 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 689 PetscLogFlops(2*a->nz); 690 691 PetscFunctionReturn(0); 692 } 693 /* -------------------------------------------------------------------*/ 694 #undef __FUNCT__ 695 #define __FUNCT__ "MatSolveTranspose_SeqAIJ" 696 int MatSolveTranspose_SeqAIJ(Mat A,Vec bb,Vec xx) 697 { 698 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 699 IS iscol = a->col,isrow = a->row; 700 int *r,*c,ierr,i,n = A->m,*vi,*ai = a->i,*aj = a->j; 701 int nz,shift = a->indexshift,*rout,*cout,*diag = a->diag; 702 PetscScalar *x,*b,*tmp,*aa = a->a,*v,s1; 703 704 PetscFunctionBegin; 705 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 706 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 707 tmp = a->solve_work; 708 709 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 710 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout; 711 712 /* copy the b into temp work space according to permutation */ 713 for (i=0; i<n; i++) tmp[i] = b[c[i]]; 714 715 /* forward solve the U^T */ 716 for (i=0; i<n; i++) { 717 v = aa + diag[i] + shift; 718 vi = aj + diag[i] + (!shift); 719 nz = ai[i+1] - diag[i] - 1; 720 s1 = tmp[i]; 721 s1 *= (*v++); /* multiply by inverse of diagonal entry */ 722 while (nz--) { 723 tmp[*vi++ + shift] -= (*v++)*s1; 724 } 725 tmp[i] = s1; 726 } 727 728 /* backward solve the L^T */ 729 for (i=n-1; i>=0; i--){ 730 v = aa + diag[i] - 1 + shift; 731 vi = aj + diag[i] - 1 + shift; 732 nz = diag[i] - ai[i]; 733 s1 = tmp[i]; 734 while (nz--) { 735 tmp[*vi-- + shift] -= (*v--)*s1; 736 } 737 } 738 739 /* copy tmp into x according to permutation */ 740 for (i=0; i<n; i++) x[r[i]] = tmp[i]; 741 742 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 743 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 744 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 745 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 746 747 PetscLogFlops(2*a->nz-A->n); 748 PetscFunctionReturn(0); 749 } 750 751 #undef __FUNCT__ 752 #define __FUNCT__ "MatSolveTransposeAdd_SeqAIJ" 753 int MatSolveTransposeAdd_SeqAIJ(Mat A,Vec bb,Vec zz,Vec xx) 754 { 755 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 756 IS iscol = a->col,isrow = a->row; 757 int *r,*c,ierr,i,n = A->m,*vi,*ai = a->i,*aj = a->j; 758 int nz,shift = a->indexshift,*rout,*cout,*diag = a->diag; 759 PetscScalar *x,*b,*tmp,*aa = a->a,*v; 760 761 PetscFunctionBegin; 762 if (zz != xx) VecCopy(zz,xx); 763 764 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 765 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 766 tmp = a->solve_work; 767 768 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 769 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout; 770 771 /* copy the b into temp work space according to permutation */ 772 for (i=0; i<n; i++) tmp[i] = b[c[i]]; 773 774 /* forward solve the U^T */ 775 for (i=0; i<n; i++) { 776 v = aa + diag[i] + shift; 777 vi = aj + diag[i] + (!shift); 778 nz = ai[i+1] - diag[i] - 1; 779 tmp[i] *= *v++; 780 while (nz--) { 781 tmp[*vi++ + shift] -= (*v++)*tmp[i]; 782 } 783 } 784 785 /* backward solve the L^T */ 786 for (i=n-1; i>=0; i--){ 787 v = aa + diag[i] - 1 + shift; 788 vi = aj + diag[i] - 1 + shift; 789 nz = diag[i] - ai[i]; 790 while (nz--) { 791 tmp[*vi-- + shift] -= (*v--)*tmp[i]; 792 } 793 } 794 795 /* copy tmp into x according to permutation */ 796 for (i=0; i<n; i++) x[r[i]] += tmp[i]; 797 798 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 799 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 800 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 801 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 802 803 PetscLogFlops(2*a->nz); 804 PetscFunctionReturn(0); 805 } 806 /* ----------------------------------------------------------------*/ 807 EXTERN int MatMissingDiagonal_SeqAIJ(Mat); 808 809 #undef __FUNCT__ 810 #define __FUNCT__ "MatILUFactorSymbolic_SeqAIJ" 811 int MatILUFactorSymbolic_SeqAIJ(Mat A,IS isrow,IS iscol,MatILUInfo *info,Mat *fact) 812 { 813 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b; 814 IS isicol; 815 int *r,*ic,ierr,prow,n = A->m,*ai = a->i,*aj = a->j; 816 int *ainew,*ajnew,jmax,*fill,*xi,nz,*im,*ajfill,*flev; 817 int *dloc,idx,row,m,fm,nzf,nzi,len, realloc = 0,dcount = 0; 818 int incrlev,nnz,i,shift = a->indexshift,levels,diagonal_fill; 819 PetscTruth col_identity,row_identity; 820 PetscReal f; 821 822 PetscFunctionBegin; 823 if (info) { 824 f = info->fill; 825 levels = (int)info->levels; 826 diagonal_fill = (int)info->diagonal_fill; 827 } else { 828 f = 1.0; 829 levels = 0; 830 diagonal_fill = 0; 831 } 832 ierr = ISInvertPermutation(iscol,PETSC_DECIDE,&isicol);CHKERRQ(ierr); 833 834 /* special case that simply copies fill pattern */ 835 ierr = ISIdentity(isrow,&row_identity);CHKERRQ(ierr); 836 ierr = ISIdentity(iscol,&col_identity);CHKERRQ(ierr); 837 if (!levels && row_identity && col_identity) { 838 ierr = MatDuplicate_SeqAIJ(A,MAT_DO_NOT_COPY_VALUES,fact);CHKERRQ(ierr); 839 (*fact)->factor = FACTOR_LU; 840 b = (Mat_SeqAIJ*)(*fact)->data; 841 if (!b->diag) { 842 ierr = MatMarkDiagonal_SeqAIJ(*fact);CHKERRQ(ierr); 843 } 844 ierr = MatMissingDiagonal_SeqAIJ(*fact);CHKERRQ(ierr); 845 b->row = isrow; 846 b->col = iscol; 847 b->icol = isicol; 848 if (info) { 849 b->lu_damp = (PetscTruth)((int)info->damp); 850 b->lu_damping = info->damping; 851 b->lu_zeropivot = info->zeropivot; 852 } else { 853 b->lu_damp = PETSC_FALSE; 854 b->lu_damping = 0.0; 855 b->lu_zeropivot = 1.e-12; 856 } 857 ierr = PetscMalloc(((*fact)->m+1)*sizeof(PetscScalar),&b->solve_work);CHKERRQ(ierr); 858 (*fact)->ops->solve = MatSolve_SeqAIJ_NaturalOrdering; 859 ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr); 860 ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr); 861 PetscFunctionReturn(0); 862 } 863 864 ierr = ISGetIndices(isrow,&r);CHKERRQ(ierr); 865 ierr = ISGetIndices(isicol,&ic);CHKERRQ(ierr); 866 867 /* get new row pointers */ 868 ierr = PetscMalloc((n+1)*sizeof(int),&ainew);CHKERRQ(ierr); 869 ainew[0] = -shift; 870 /* don't know how many column pointers are needed so estimate */ 871 jmax = (int)(f*(ai[n]+!shift)); 872 ierr = PetscMalloc((jmax)*sizeof(int),&ajnew);CHKERRQ(ierr); 873 /* ajfill is level of fill for each fill entry */ 874 ierr = PetscMalloc((jmax)*sizeof(int),&ajfill);CHKERRQ(ierr); 875 /* fill is a linked list of nonzeros in active row */ 876 ierr = PetscMalloc((n+1)*sizeof(int),&fill);CHKERRQ(ierr); 877 /* im is level for each filled value */ 878 ierr = PetscMalloc((n+1)*sizeof(int),&im);CHKERRQ(ierr); 879 /* dloc is location of diagonal in factor */ 880 ierr = PetscMalloc((n+1)*sizeof(int),&dloc);CHKERRQ(ierr); 881 dloc[0] = 0; 882 for (prow=0; prow<n; prow++) { 883 884 /* copy current row into linked list */ 885 nzf = nz = ai[r[prow]+1] - ai[r[prow]]; 886 if (!nz) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Empty row in matrix"); 887 xi = aj + ai[r[prow]] + shift; 888 fill[n] = n; 889 fill[prow] = -1; /* marker to indicate if diagonal exists */ 890 while (nz--) { 891 fm = n; 892 idx = ic[*xi++ + shift]; 893 do { 894 m = fm; 895 fm = fill[m]; 896 } while (fm < idx); 897 fill[m] = idx; 898 fill[idx] = fm; 899 im[idx] = 0; 900 } 901 902 /* make sure diagonal entry is included */ 903 if (diagonal_fill && fill[prow] == -1) { 904 fm = n; 905 while (fill[fm] < prow) fm = fill[fm]; 906 fill[prow] = fill[fm]; /* insert diagonal into linked list */ 907 fill[fm] = prow; 908 im[prow] = 0; 909 nzf++; 910 dcount++; 911 } 912 913 nzi = 0; 914 row = fill[n]; 915 while (row < prow) { 916 incrlev = im[row] + 1; 917 nz = dloc[row]; 918 xi = ajnew + ainew[row] + shift + nz + 1; 919 flev = ajfill + ainew[row] + shift + nz + 1; 920 nnz = ainew[row+1] - ainew[row] - nz - 1; 921 fm = row; 922 while (nnz-- > 0) { 923 idx = *xi++ + shift; 924 if (*flev + incrlev > levels) { 925 flev++; 926 continue; 927 } 928 do { 929 m = fm; 930 fm = fill[m]; 931 } while (fm < idx); 932 if (fm != idx) { 933 im[idx] = *flev + incrlev; 934 fill[m] = idx; 935 fill[idx] = fm; 936 fm = idx; 937 nzf++; 938 } else { 939 if (im[idx] > *flev + incrlev) im[idx] = *flev+incrlev; 940 } 941 flev++; 942 } 943 row = fill[row]; 944 nzi++; 945 } 946 /* copy new filled row into permanent storage */ 947 ainew[prow+1] = ainew[prow] + nzf; 948 if (ainew[prow+1] > jmax-shift) { 949 950 /* estimate how much additional space we will need */ 951 /* use the strategy suggested by David Hysom <hysom@perch-t.icase.edu> */ 952 /* just double the memory each time */ 953 /* maxadd = (int)((f*(ai[n]+!shift)*(n-prow+5))/n); */ 954 int maxadd = jmax; 955 if (maxadd < nzf) maxadd = (n-prow)*(nzf+1); 956 jmax += maxadd; 957 958 /* allocate a longer ajnew and ajfill */ 959 ierr = PetscMalloc(jmax*sizeof(int),&xi);CHKERRQ(ierr); 960 ierr = PetscMemcpy(xi,ajnew,(ainew[prow]+shift)*sizeof(int));CHKERRQ(ierr); 961 ierr = PetscFree(ajnew);CHKERRQ(ierr); 962 ajnew = xi; 963 ierr = PetscMalloc(jmax*sizeof(int),&xi);CHKERRQ(ierr); 964 ierr = PetscMemcpy(xi,ajfill,(ainew[prow]+shift)*sizeof(int));CHKERRQ(ierr); 965 ierr = PetscFree(ajfill);CHKERRQ(ierr); 966 ajfill = xi; 967 realloc++; /* count how many times we realloc */ 968 } 969 xi = ajnew + ainew[prow] + shift; 970 flev = ajfill + ainew[prow] + shift; 971 dloc[prow] = nzi; 972 fm = fill[n]; 973 while (nzf--) { 974 *xi++ = fm - shift; 975 *flev++ = im[fm]; 976 fm = fill[fm]; 977 } 978 /* make sure row has diagonal entry */ 979 if (ajnew[ainew[prow]+shift+dloc[prow]]+shift != prow) { 980 SETERRQ1(PETSC_ERR_MAT_LU_ZRPVT,"Row %d has missing diagonal in factored matrix\n\ 981 try running with -pc_ilu_nonzeros_along_diagonal or -pc_ilu_diagonal_fill",prow); 982 } 983 } 984 ierr = PetscFree(ajfill);CHKERRQ(ierr); 985 ierr = ISRestoreIndices(isrow,&r);CHKERRQ(ierr); 986 ierr = ISRestoreIndices(isicol,&ic);CHKERRQ(ierr); 987 ierr = PetscFree(fill);CHKERRQ(ierr); 988 ierr = PetscFree(im);CHKERRQ(ierr); 989 990 { 991 PetscReal af = ((PetscReal)ainew[n])/((PetscReal)ai[n]); 992 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:Reallocs %d Fill ratio:given %g needed %g\n",realloc,f,af); 993 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:Run with -[sub_]pc_ilu_fill %g or use \n",af); 994 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:PCILUSetFill([sub]pc,%g);\n",af); 995 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:for best performance.\n"); 996 if (diagonal_fill) { 997 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:Detected and replace %d missing diagonals",dcount); 998 } 999 } 1000 1001 /* put together the new matrix */ 1002 ierr = MatCreateSeqAIJ(A->comm,n,n,0,PETSC_NULL,fact);CHKERRQ(ierr); 1003 PetscLogObjectParent(*fact,isicol); 1004 b = (Mat_SeqAIJ*)(*fact)->data; 1005 ierr = PetscFree(b->imax);CHKERRQ(ierr); 1006 b->singlemalloc = PETSC_FALSE; 1007 len = (ainew[n] + shift)*sizeof(PetscScalar); 1008 /* the next line frees the default space generated by the Create() */ 1009 ierr = PetscFree(b->a);CHKERRQ(ierr); 1010 ierr = PetscFree(b->ilen);CHKERRQ(ierr); 1011 ierr = PetscMalloc(len+1,&b->a);CHKERRQ(ierr); 1012 b->j = ajnew; 1013 b->i = ainew; 1014 for (i=0; i<n; i++) dloc[i] += ainew[i]; 1015 b->diag = dloc; 1016 b->ilen = 0; 1017 b->imax = 0; 1018 b->row = isrow; 1019 b->col = iscol; 1020 ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr); 1021 ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr); 1022 b->icol = isicol; 1023 ierr = PetscMalloc((n+1)*sizeof(PetscScalar),&b->solve_work);CHKERRQ(ierr); 1024 /* In b structure: Free imax, ilen, old a, old j. 1025 Allocate dloc, solve_work, new a, new j */ 1026 PetscLogObjectMemory(*fact,(ainew[n]+shift-n) * (sizeof(int)+sizeof(PetscScalar))); 1027 b->maxnz = b->nz = ainew[n] + shift; 1028 if (info) { 1029 b->lu_damp = (PetscTruth)((int)info->damp); 1030 b->lu_damping = info->damping; 1031 b->lu_zeropivot = info->zeropivot; 1032 } else { 1033 b->lu_damp = PETSC_FALSE; 1034 b->lu_damping = 0.0; 1035 b->lu_zeropivot = 1.e-12; 1036 } 1037 (*fact)->factor = FACTOR_LU; 1038 ierr = Mat_AIJ_CheckInode(*fact,PETSC_FALSE);CHKERRQ(ierr); 1039 (*fact)->ops->lufactornumeric = A->ops->lufactornumeric; /* Use Inode variant ONLY if A has inodes */ 1040 1041 (*fact)->info.factor_mallocs = realloc; 1042 (*fact)->info.fill_ratio_given = f; 1043 (*fact)->info.fill_ratio_needed = ((PetscReal)ainew[n])/((PetscReal)ai[prow]); 1044 (*fact)->factor = FACTOR_LU; 1045 PetscFunctionReturn(0); 1046 } 1047 1048 1049 1050 1051