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