1 /*$Id: aijfact.c,v 1.161 2001/04/23 15:12:05 bsmith 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); 22 23 EXTERN int SPARSEKIT2dperm(int*,Scalar*,int*,int*,Scalar*,int*,int*,int*,int*,int*); 24 EXTERN int SPARSEKIT2ilutp(int*,Scalar*,int*,int*,int*,PetscReal*,PetscReal*,int*,Scalar*,int*,int*,int*,Scalar*,int*,int*,int*); 25 EXTERN int SPARSEKIT2msrcsr(int*,Scalar*,int*,Scalar*,int*,int*,Scalar*,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 Scalar *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(Scalar),&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(Scalar),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(Scalar),&w);CHKERRQ(ierr); 145 146 SPARSEKIT2ilutp(&n,o_a,o_j,o_i,&lfill,&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(Scalar),&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(Scalar),&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);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(Scalar),&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 } else { 402 b->lu_damp = PETSC_FALSE; 403 b->lu_damping = 0.0; 404 } 405 ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr); 406 ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr); 407 b->icol = isicol; 408 ierr = PetscMalloc((n+1)*sizeof(Scalar),&b->solve_work);CHKERRQ(ierr); 409 /* In b structure: Free imax, ilen, old a, old j. 410 Allocate idnew, solve_work, new a, new j */ 411 PetscLogObjectMemory(*B,(ainew[n]+shift-n)*(sizeof(int)+sizeof(Scalar))); 412 b->maxnz = b->nz = ainew[n] + shift; 413 414 (*B)->factor = FACTOR_LU; 415 (*B)->info.factor_mallocs = realloc; 416 (*B)->info.fill_ratio_given = f; 417 (*B)->ops->lufactornumeric = A->ops->lufactornumeric; /* Use Inode variant ONLY if A has inodes */ 418 419 if (ai[n] != 0) { 420 (*B)->info.fill_ratio_needed = ((PetscReal)ainew[n])/((PetscReal)ai[n]); 421 } else { 422 (*B)->info.fill_ratio_needed = 0.0; 423 } 424 PetscFunctionReturn(0); 425 } 426 /* ----------------------------------------------------------- */ 427 EXTERN int Mat_AIJ_CheckInode(Mat); 428 429 #undef __FUNCT__ 430 #define __FUNCT__ "MatLUFactorNumeric_SeqAIJ" 431 int MatLUFactorNumeric_SeqAIJ(Mat A,Mat *B) 432 { 433 Mat C = *B; 434 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ *)C->data; 435 IS isrow = b->row,isicol = b->icol; 436 int *r,*ic,ierr,i,j,n = A->m,*ai = b->i,*aj = b->j; 437 int *ajtmpold,*ajtmp,nz,row,*ics,shift = a->indexshift; 438 int *diag_offset = b->diag,diag; 439 int *pj,ndamp = 0; 440 Scalar *rtmp,*v,*pc,multiplier,*pv,*rtmps; 441 PetscReal damping = b->lu_damping; 442 PetscTruth damp; 443 444 PetscFunctionBegin; 445 446 ierr = ISGetIndices(isrow,&r);CHKERRQ(ierr); 447 ierr = ISGetIndices(isicol,&ic);CHKERRQ(ierr); 448 ierr = PetscMalloc((n+1)*sizeof(Scalar),&rtmp);CHKERRQ(ierr); 449 ierr = PetscMemzero(rtmp,(n+1)*sizeof(Scalar));CHKERRQ(ierr); 450 rtmps = rtmp + shift; ics = ic + shift; 451 452 do { 453 damp = PETSC_FALSE; 454 for (i=0; i<n; i++) { 455 nz = ai[i+1] - ai[i]; 456 ajtmp = aj + ai[i] + shift; 457 for (j=0; j<nz; j++) rtmps[ajtmp[j]] = 0.0; 458 459 /* load in initial (unfactored row) */ 460 nz = a->i[r[i]+1] - a->i[r[i]]; 461 ajtmpold = a->j + a->i[r[i]] + shift; 462 v = a->a + a->i[r[i]] + shift; 463 for (j=0; j<nz; j++) { 464 rtmp[ics[ajtmpold[j]]] = v[j]; 465 if (ajtmpold[j] == r[i]) { /* damp the diagonal of the matrix */ 466 rtmp[ics[ajtmpold[j]]] += damping; 467 } 468 } 469 470 row = *ajtmp++ + shift; 471 while (row < i) { 472 pc = rtmp + row; 473 if (*pc != 0.0) { 474 pv = b->a + diag_offset[row] + shift; 475 pj = b->j + diag_offset[row] + (!shift); 476 multiplier = *pc / *pv++; 477 *pc = multiplier; 478 nz = ai[row+1] - diag_offset[row] - 1; 479 for (j=0; j<nz; j++) rtmps[pj[j]] -= multiplier * pv[j]; 480 PetscLogFlops(2*nz); 481 } 482 row = *ajtmp++ + shift; 483 } 484 /* finished row so stick it into b->a */ 485 pv = b->a + ai[i] + shift; 486 pj = b->j + ai[i] + shift; 487 nz = ai[i+1] - ai[i]; 488 for (j=0; j<nz; j++) {pv[j] = rtmps[pj[j]];} 489 diag = diag_offset[i] - ai[i]; 490 if (PetscAbsScalar(pv[diag]) < 1.e-12) { 491 if (b->lu_damp) { 492 damp = PETSC_TRUE; 493 if (damping) damping *= 2.0; 494 else damping = 1.e-12; 495 ndamp++; 496 break; 497 } else { 498 SETERRQ1(PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot row %d",i); 499 } 500 } 501 } 502 } while (damp); 503 504 /* invert diagonal entries for simplier triangular solves */ 505 for (i=0; i<n; i++) { 506 b->a[diag_offset[i]+shift] = 1.0/b->a[diag_offset[i]+shift]; 507 } 508 509 ierr = PetscFree(rtmp);CHKERRQ(ierr); 510 ierr = ISRestoreIndices(isicol,&ic);CHKERRQ(ierr); 511 ierr = ISRestoreIndices(isrow,&r);CHKERRQ(ierr); 512 C->factor = FACTOR_LU; 513 ierr = Mat_AIJ_CheckInode(C);CHKERRQ(ierr); 514 (*B)->ops->lufactornumeric = A->ops->lufactornumeric; /* Use Inode variant ONLY if A has inodes */ 515 C->assembled = PETSC_TRUE; 516 PetscLogFlops(C->n); 517 if (ndamp || b->lu_damping) { 518 PetscLogInfo(0,"MatLUFactorNumerical_SeqAIJ: number of damping tries %d damping value %g\n",ndamp,damping); 519 } 520 PetscFunctionReturn(0); 521 } 522 /* ----------------------------------------------------------- */ 523 #undef __FUNCT__ 524 #define __FUNCT__ "MatLUFactor_SeqAIJ" 525 int MatLUFactor_SeqAIJ(Mat A,IS row,IS col,MatLUInfo *info) 526 { 527 int ierr; 528 Mat C; 529 530 PetscFunctionBegin; 531 ierr = MatLUFactorSymbolic(A,row,col,info,&C);CHKERRQ(ierr); 532 ierr = MatLUFactorNumeric(A,&C);CHKERRQ(ierr); 533 ierr = MatHeaderCopy(A,C);CHKERRQ(ierr); 534 PetscFunctionReturn(0); 535 } 536 /* ----------------------------------------------------------- */ 537 #undef __FUNCT__ 538 #define __FUNCT__ "MatSolve_SeqAIJ" 539 int MatSolve_SeqAIJ(Mat A,Vec bb,Vec xx) 540 { 541 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 542 IS iscol = a->col,isrow = a->row; 543 int *r,*c,ierr,i, n = A->m,*vi,*ai = a->i,*aj = a->j; 544 int nz,shift = a->indexshift,*rout,*cout; 545 Scalar *x,*b,*tmp,*tmps,*aa = a->a,sum,*v; 546 547 PetscFunctionBegin; 548 if (!n) PetscFunctionReturn(0); 549 550 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 551 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 552 tmp = a->solve_work; 553 554 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 555 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout + (n-1); 556 557 /* forward solve the lower triangular */ 558 tmp[0] = b[*r++]; 559 tmps = tmp + shift; 560 for (i=1; i<n; i++) { 561 v = aa + ai[i] + shift; 562 vi = aj + ai[i] + shift; 563 nz = a->diag[i] - ai[i]; 564 sum = b[*r++]; 565 while (nz--) sum -= *v++ * tmps[*vi++]; 566 tmp[i] = sum; 567 } 568 569 /* backward solve the upper triangular */ 570 for (i=n-1; i>=0; i--){ 571 v = aa + a->diag[i] + (!shift); 572 vi = aj + a->diag[i] + (!shift); 573 nz = ai[i+1] - a->diag[i] - 1; 574 sum = tmp[i]; 575 while (nz--) sum -= *v++ * tmps[*vi++]; 576 x[*c--] = tmp[i] = sum*aa[a->diag[i]+shift]; 577 } 578 579 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 580 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 581 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 582 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 583 PetscLogFlops(2*a->nz - A->n); 584 PetscFunctionReturn(0); 585 } 586 587 /* ----------------------------------------------------------- */ 588 #undef __FUNCT__ 589 #define __FUNCT__ "MatSolve_SeqAIJ_NaturalOrdering" 590 int MatSolve_SeqAIJ_NaturalOrdering(Mat A,Vec bb,Vec xx) 591 { 592 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 593 int n = A->m,*ai = a->i,*aj = a->j,*adiag = a->diag,ierr; 594 Scalar *x,*b,*aa = a->a,sum; 595 #if !defined(PETSC_USE_FORTRAN_KERNEL_SOLVEAIJ) 596 int adiag_i,i,*vi,nz,ai_i; 597 Scalar *v; 598 #endif 599 600 PetscFunctionBegin; 601 if (!n) PetscFunctionReturn(0); 602 if (a->indexshift) { 603 ierr = MatSolve_SeqAIJ(A,bb,xx);CHKERRQ(ierr); 604 PetscFunctionReturn(0); 605 } 606 607 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 608 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 609 610 #if defined(PETSC_USE_FORTRAN_KERNEL_SOLVEAIJ) 611 fortransolveaij_(&n,x,ai,aj,adiag,aa,b); 612 #else 613 /* forward solve the lower triangular */ 614 x[0] = b[0]; 615 for (i=1; i<n; i++) { 616 ai_i = ai[i]; 617 v = aa + ai_i; 618 vi = aj + ai_i; 619 nz = adiag[i] - ai_i; 620 sum = b[i]; 621 while (nz--) sum -= *v++ * x[*vi++]; 622 x[i] = sum; 623 } 624 625 /* backward solve the upper triangular */ 626 for (i=n-1; i>=0; i--){ 627 adiag_i = adiag[i]; 628 v = aa + adiag_i + 1; 629 vi = aj + adiag_i + 1; 630 nz = ai[i+1] - adiag_i - 1; 631 sum = x[i]; 632 while (nz--) sum -= *v++ * x[*vi++]; 633 x[i] = sum*aa[adiag_i]; 634 } 635 #endif 636 PetscLogFlops(2*a->nz - A->n); 637 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 638 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 639 PetscFunctionReturn(0); 640 } 641 642 #undef __FUNCT__ 643 #define __FUNCT__ "MatSolveAdd_SeqAIJ" 644 int MatSolveAdd_SeqAIJ(Mat A,Vec bb,Vec yy,Vec xx) 645 { 646 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 647 IS iscol = a->col,isrow = a->row; 648 int *r,*c,ierr,i, n = A->m,*vi,*ai = a->i,*aj = a->j; 649 int nz,shift = a->indexshift,*rout,*cout; 650 Scalar *x,*b,*tmp,*aa = a->a,sum,*v; 651 652 PetscFunctionBegin; 653 if (yy != xx) {ierr = VecCopy(yy,xx);CHKERRQ(ierr);} 654 655 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 656 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 657 tmp = a->solve_work; 658 659 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 660 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout + (n-1); 661 662 /* forward solve the lower triangular */ 663 tmp[0] = b[*r++]; 664 for (i=1; i<n; i++) { 665 v = aa + ai[i] + shift; 666 vi = aj + ai[i] + shift; 667 nz = a->diag[i] - ai[i]; 668 sum = b[*r++]; 669 while (nz--) sum -= *v++ * tmp[*vi++ + shift]; 670 tmp[i] = sum; 671 } 672 673 /* backward solve the upper triangular */ 674 for (i=n-1; i>=0; i--){ 675 v = aa + a->diag[i] + (!shift); 676 vi = aj + a->diag[i] + (!shift); 677 nz = ai[i+1] - a->diag[i] - 1; 678 sum = tmp[i]; 679 while (nz--) sum -= *v++ * tmp[*vi++ + shift]; 680 tmp[i] = sum*aa[a->diag[i]+shift]; 681 x[*c--] += tmp[i]; 682 } 683 684 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 685 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 686 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 687 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 688 PetscLogFlops(2*a->nz); 689 690 PetscFunctionReturn(0); 691 } 692 /* -------------------------------------------------------------------*/ 693 #undef __FUNCT__ 694 #define __FUNCT__ "MatSolveTranspose_SeqAIJ" 695 int MatSolveTranspose_SeqAIJ(Mat A,Vec bb,Vec xx) 696 { 697 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 698 IS iscol = a->col,isrow = a->row; 699 int *r,*c,ierr,i,n = A->m,*vi,*ai = a->i,*aj = a->j; 700 int nz,shift = a->indexshift,*rout,*cout,*diag = a->diag; 701 Scalar *x,*b,*tmp,*aa = a->a,*v,s1; 702 703 PetscFunctionBegin; 704 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 705 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 706 tmp = a->solve_work; 707 708 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 709 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout; 710 711 /* copy the b into temp work space according to permutation */ 712 for (i=0; i<n; i++) tmp[i] = b[c[i]]; 713 714 /* forward solve the U^T */ 715 for (i=0; i<n; i++) { 716 v = aa + diag[i] + shift; 717 vi = aj + diag[i] + (!shift); 718 nz = ai[i+1] - diag[i] - 1; 719 s1 = tmp[i]; 720 s1 *= *(v++); /* multiply by inverse of diagonal entry */ 721 while (nz--) { 722 tmp[*vi++ + shift] -= (*v++)*s1; 723 } 724 tmp[i] = s1; 725 } 726 727 /* backward solve the L^T */ 728 for (i=n-1; i>=0; i--){ 729 v = aa + diag[i] - 1 + shift; 730 vi = aj + diag[i] - 1 + shift; 731 nz = diag[i] - ai[i]; 732 s1 = tmp[i]; 733 while (nz--) { 734 tmp[*vi-- + shift] -= (*v--)*s1; 735 } 736 } 737 738 /* copy tmp into x according to permutation */ 739 for (i=0; i<n; i++) x[r[i]] = tmp[i]; 740 741 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 742 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 743 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 744 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 745 746 PetscLogFlops(2*a->nz-A->n); 747 PetscFunctionReturn(0); 748 } 749 750 #undef __FUNCT__ 751 #define __FUNCT__ "MatSolveTransposeAdd_SeqAIJ" 752 int MatSolveTransposeAdd_SeqAIJ(Mat A,Vec bb,Vec zz,Vec xx) 753 { 754 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 755 IS iscol = a->col,isrow = a->row; 756 int *r,*c,ierr,i,n = A->m,*vi,*ai = a->i,*aj = a->j; 757 int nz,shift = a->indexshift,*rout,*cout,*diag = a->diag; 758 Scalar *x,*b,*tmp,*aa = a->a,*v; 759 760 PetscFunctionBegin; 761 if (zz != xx) VecCopy(zz,xx); 762 763 ierr = VecGetArray(bb,&b);CHKERRQ(ierr); 764 ierr = VecGetArray(xx,&x);CHKERRQ(ierr); 765 tmp = a->solve_work; 766 767 ierr = ISGetIndices(isrow,&rout);CHKERRQ(ierr); r = rout; 768 ierr = ISGetIndices(iscol,&cout);CHKERRQ(ierr); c = cout; 769 770 /* copy the b into temp work space according to permutation */ 771 for (i=0; i<n; i++) tmp[i] = b[c[i]]; 772 773 /* forward solve the U^T */ 774 for (i=0; i<n; i++) { 775 v = aa + diag[i] + shift; 776 vi = aj + diag[i] + (!shift); 777 nz = ai[i+1] - diag[i] - 1; 778 tmp[i] *= *v++; 779 while (nz--) { 780 tmp[*vi++ + shift] -= (*v++)*tmp[i]; 781 } 782 } 783 784 /* backward solve the L^T */ 785 for (i=n-1; i>=0; i--){ 786 v = aa + diag[i] - 1 + shift; 787 vi = aj + diag[i] - 1 + shift; 788 nz = diag[i] - ai[i]; 789 while (nz--) { 790 tmp[*vi-- + shift] -= (*v--)*tmp[i]; 791 } 792 } 793 794 /* copy tmp into x according to permutation */ 795 for (i=0; i<n; i++) x[r[i]] += tmp[i]; 796 797 ierr = ISRestoreIndices(isrow,&rout);CHKERRQ(ierr); 798 ierr = ISRestoreIndices(iscol,&cout);CHKERRQ(ierr); 799 ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr); 800 ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr); 801 802 PetscLogFlops(2*a->nz); 803 PetscFunctionReturn(0); 804 } 805 /* ----------------------------------------------------------------*/ 806 EXTERN int MatMissingDiagonal_SeqAIJ(Mat); 807 808 #undef __FUNCT__ 809 #define __FUNCT__ "MatILUFactorSymbolic_SeqAIJ" 810 int MatILUFactorSymbolic_SeqAIJ(Mat A,IS isrow,IS iscol,MatILUInfo *info,Mat *fact) 811 { 812 Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data,*b; 813 IS isicol; 814 int *r,*ic,ierr,prow,n = A->m,*ai = a->i,*aj = a->j; 815 int *ainew,*ajnew,jmax,*fill,*xi,nz,*im,*ajfill,*flev; 816 int *dloc,idx,row,m,fm,nzf,nzi,len, realloc = 0,dcount = 0; 817 int incrlev,nnz,i,shift = a->indexshift,levels,diagonal_fill; 818 PetscTruth col_identity,row_identity; 819 PetscReal f; 820 821 PetscFunctionBegin; 822 if (info) { 823 f = info->fill; 824 levels = (int)info->levels; 825 diagonal_fill = (int)info->diagonal_fill; 826 } else { 827 f = 1.0; 828 levels = 0; 829 diagonal_fill = 0; 830 } 831 ierr = ISInvertPermutation(iscol,PETSC_DECIDE,&isicol);CHKERRQ(ierr); 832 833 /* special case that simply copies fill pattern */ 834 ierr = ISIdentity(isrow,&row_identity);CHKERRQ(ierr); 835 ierr = ISIdentity(iscol,&col_identity);CHKERRQ(ierr); 836 if (!levels && row_identity && col_identity) { 837 ierr = MatDuplicate_SeqAIJ(A,MAT_DO_NOT_COPY_VALUES,fact);CHKERRQ(ierr); 838 (*fact)->factor = FACTOR_LU; 839 b = (Mat_SeqAIJ*)(*fact)->data; 840 if (!b->diag) { 841 ierr = MatMarkDiagonal_SeqAIJ(*fact);CHKERRQ(ierr); 842 } 843 ierr = MatMissingDiagonal_SeqAIJ(*fact);CHKERRQ(ierr); 844 b->row = isrow; 845 b->col = iscol; 846 b->icol = isicol; 847 if (info) { 848 b->lu_damp = (PetscTruth)((int)info->damp); 849 b->lu_damping = info->damping; 850 } else { 851 b->lu_damp = PETSC_FALSE; 852 b->lu_damping = 0.0; 853 } 854 ierr = PetscMalloc(((*fact)->m+1)*sizeof(Scalar),&b->solve_work);CHKERRQ(ierr); 855 (*fact)->ops->solve = MatSolve_SeqAIJ_NaturalOrdering; 856 ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr); 857 ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr); 858 PetscFunctionReturn(0); 859 } 860 861 ierr = ISGetIndices(isrow,&r);CHKERRQ(ierr); 862 ierr = ISGetIndices(isicol,&ic);CHKERRQ(ierr); 863 864 /* get new row pointers */ 865 ierr = PetscMalloc((n+1)*sizeof(int),&ainew);CHKERRQ(ierr); 866 ainew[0] = -shift; 867 /* don't know how many column pointers are needed so estimate */ 868 jmax = (int)(f*(ai[n]+!shift)); 869 ierr = PetscMalloc((jmax)*sizeof(int),&ajnew);CHKERRQ(ierr); 870 /* ajfill is level of fill for each fill entry */ 871 ierr = PetscMalloc((jmax)*sizeof(int),&ajfill);CHKERRQ(ierr); 872 /* fill is a linked list of nonzeros in active row */ 873 ierr = PetscMalloc((n+1)*sizeof(int),&fill);CHKERRQ(ierr); 874 /* im is level for each filled value */ 875 ierr = PetscMalloc((n+1)*sizeof(int),&im);CHKERRQ(ierr); 876 /* dloc is location of diagonal in factor */ 877 ierr = PetscMalloc((n+1)*sizeof(int),&dloc);CHKERRQ(ierr); 878 dloc[0] = 0; 879 for (prow=0; prow<n; prow++) { 880 881 /* copy current row into linked list */ 882 nzf = nz = ai[r[prow]+1] - ai[r[prow]]; 883 if (!nz) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Empty row in matrix"); 884 xi = aj + ai[r[prow]] + shift; 885 fill[n] = n; 886 fill[prow] = -1; /* marker to indicate if diagonal exists */ 887 while (nz--) { 888 fm = n; 889 idx = ic[*xi++ + shift]; 890 do { 891 m = fm; 892 fm = fill[m]; 893 } while (fm < idx); 894 fill[m] = idx; 895 fill[idx] = fm; 896 im[idx] = 0; 897 } 898 899 /* make sure diagonal entry is included */ 900 if (diagonal_fill && fill[prow] == -1) { 901 fm = n; 902 while (fill[fm] < prow) fm = fill[fm]; 903 fill[prow] = fill[fm]; /* insert diagonal into linked list */ 904 fill[fm] = prow; 905 im[prow] = 0; 906 nzf++; 907 dcount++; 908 } 909 910 nzi = 0; 911 row = fill[n]; 912 while (row < prow) { 913 incrlev = im[row] + 1; 914 nz = dloc[row]; 915 xi = ajnew + ainew[row] + shift + nz + 1; 916 flev = ajfill + ainew[row] + shift + nz + 1; 917 nnz = ainew[row+1] - ainew[row] - nz - 1; 918 fm = row; 919 while (nnz-- > 0) { 920 idx = *xi++ + shift; 921 if (*flev + incrlev > levels) { 922 flev++; 923 continue; 924 } 925 do { 926 m = fm; 927 fm = fill[m]; 928 } while (fm < idx); 929 if (fm != idx) { 930 im[idx] = *flev + incrlev; 931 fill[m] = idx; 932 fill[idx] = fm; 933 fm = idx; 934 nzf++; 935 } else { 936 if (im[idx] > *flev + incrlev) im[idx] = *flev+incrlev; 937 } 938 flev++; 939 } 940 row = fill[row]; 941 nzi++; 942 } 943 /* copy new filled row into permanent storage */ 944 ainew[prow+1] = ainew[prow] + nzf; 945 if (ainew[prow+1] > jmax-shift) { 946 947 /* estimate how much additional space we will need */ 948 /* use the strategy suggested by David Hysom <hysom@perch-t.icase.edu> */ 949 /* just double the memory each time */ 950 /* maxadd = (int)((f*(ai[n]+!shift)*(n-prow+5))/n); */ 951 int maxadd = jmax; 952 if (maxadd < nzf) maxadd = (n-prow)*(nzf+1); 953 jmax += maxadd; 954 955 /* allocate a longer ajnew and ajfill */ 956 ierr = PetscMalloc(jmax*sizeof(int),&xi);CHKERRQ(ierr); 957 ierr = PetscMemcpy(xi,ajnew,(ainew[prow]+shift)*sizeof(int));CHKERRQ(ierr); 958 ierr = PetscFree(ajnew);CHKERRQ(ierr); 959 ajnew = xi; 960 ierr = PetscMalloc(jmax*sizeof(int),&xi);CHKERRQ(ierr); 961 ierr = PetscMemcpy(xi,ajfill,(ainew[prow]+shift)*sizeof(int));CHKERRQ(ierr); 962 ierr = PetscFree(ajfill);CHKERRQ(ierr); 963 ajfill = xi; 964 realloc++; /* count how many times we realloc */ 965 } 966 xi = ajnew + ainew[prow] + shift; 967 flev = ajfill + ainew[prow] + shift; 968 dloc[prow] = nzi; 969 fm = fill[n]; 970 while (nzf--) { 971 *xi++ = fm - shift; 972 *flev++ = im[fm]; 973 fm = fill[fm]; 974 } 975 /* make sure row has diagonal entry */ 976 if (ajnew[ainew[prow]+shift+dloc[prow]]+shift != prow) { 977 SETERRQ1(PETSC_ERR_MAT_LU_ZRPVT,"Row %d has missing diagonal in factored matrix\n\ 978 try running with -pc_ilu_nonzeros_along_diagonal or -pc_ilu_diagonal_fill",prow); 979 } 980 } 981 ierr = PetscFree(ajfill);CHKERRQ(ierr); 982 ierr = ISRestoreIndices(isrow,&r);CHKERRQ(ierr); 983 ierr = ISRestoreIndices(isicol,&ic);CHKERRQ(ierr); 984 ierr = PetscFree(fill);CHKERRQ(ierr); 985 ierr = PetscFree(im);CHKERRQ(ierr); 986 987 { 988 PetscReal af = ((PetscReal)ainew[n])/((PetscReal)ai[n]); 989 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:Reallocs %d Fill ratio:given %g needed %g\n",realloc,f,af); 990 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:Run with -[sub_]pc_ilu_fill %g or use \n",af); 991 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:PCILUSetFill([sub]pc,%g);\n",af); 992 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:for best performance.\n"); 993 if (diagonal_fill) { 994 PetscLogInfo(A,"MatILUFactorSymbolic_SeqAIJ:Detected and replace %d missing diagonals",dcount); 995 } 996 } 997 998 /* put together the new matrix */ 999 ierr = MatCreateSeqAIJ(A->comm,n,n,0,PETSC_NULL,fact);CHKERRQ(ierr); 1000 PetscLogObjectParent(*fact,isicol); 1001 b = (Mat_SeqAIJ*)(*fact)->data; 1002 ierr = PetscFree(b->imax);CHKERRQ(ierr); 1003 b->singlemalloc = PETSC_FALSE; 1004 len = (ainew[n] + shift)*sizeof(Scalar); 1005 /* the next line frees the default space generated by the Create() */ 1006 ierr = PetscFree(b->a);CHKERRQ(ierr); 1007 ierr = PetscFree(b->ilen);CHKERRQ(ierr); 1008 ierr = PetscMalloc(len+1,&b->a);CHKERRQ(ierr); 1009 b->j = ajnew; 1010 b->i = ainew; 1011 for (i=0; i<n; i++) dloc[i] += ainew[i]; 1012 b->diag = dloc; 1013 b->ilen = 0; 1014 b->imax = 0; 1015 b->row = isrow; 1016 b->col = iscol; 1017 ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr); 1018 ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr); 1019 b->icol = isicol; 1020 ierr = PetscMalloc((n+1)*sizeof(Scalar),&b->solve_work);CHKERRQ(ierr); 1021 /* In b structure: Free imax, ilen, old a, old j. 1022 Allocate dloc, solve_work, new a, new j */ 1023 PetscLogObjectMemory(*fact,(ainew[n]+shift-n) * (sizeof(int)+sizeof(Scalar))); 1024 b->maxnz = b->nz = ainew[n] + shift; 1025 if (info) { 1026 b->lu_damp = (PetscTruth)((int)info->damp); 1027 b->lu_damping = info->damping; 1028 } else { 1029 b->lu_damp = PETSC_FALSE; 1030 b->lu_damping = 0.0; 1031 } 1032 (*fact)->factor = FACTOR_LU; 1033 1034 (*fact)->info.factor_mallocs = realloc; 1035 (*fact)->info.fill_ratio_given = f; 1036 (*fact)->info.fill_ratio_needed = ((PetscReal)ainew[n])/((PetscReal)ai[prow]); 1037 (*fact)->factor = FACTOR_LU; 1038 1039 PetscFunctionReturn(0); 1040 } 1041 1042 1043 1044 1045