1 #ifndef lint 2 static char vcid[] = "$Id: aijfact.c,v 1.22 1995/06/27 21:26:14 curfman Exp bsmith $"; 3 #endif 4 5 6 #include "aij.h" 7 #include "inline/spops.h" 8 /* 9 Factorization code for AIJ format. 10 */ 11 12 int MatLUFactorSymbolic_AIJ(Mat mat,IS isrow,IS iscol,Mat *fact) 13 { 14 Mat_AIJ *aij = (Mat_AIJ *) mat->data, *aijnew; 15 IS isicol; 16 int *r,*ic, ierr, i, n = aij->m, *ai = aij->i, *aj = aij->j; 17 int *ainew,*ajnew, jmax,*fill, *ajtmp, nz; 18 int *idnew, idx, row,m,fm, nnz, nzi,len; 19 20 if (n != aij->n) 21 SETERRQ(1,"MatLUFactorSymbolic_AIJ: Matrix must be square."); 22 if (!isrow) 23 SETERRQ(1,"MatLUFactorSymbolic_AIJ: Matrix must have row permutation."); 24 if (!iscol) 25 SETERRQ(1,"MatLUFactorSymbolic_AIJ: Matrix must have column permutation."); 26 27 ierr = ISInvertPermutation(iscol,&isicol); CHKERRQ(ierr); 28 ISGetIndices(isrow,&r); ISGetIndices(isicol,&ic); 29 30 /* get new row pointers */ 31 ainew = (int *) PETSCMALLOC( (n+1)*sizeof(int) ); CHKPTRQ(ainew); 32 ainew[0] = 1; 33 /* don't know how many column pointers are needed so estimate */ 34 jmax = 2*ai[n]; 35 ajnew = (int *) PETSCMALLOC( (jmax)*sizeof(int) ); CHKPTRQ(ajnew); 36 /* fill is a linked list of nonzeros in active row */ 37 fill = (int *) PETSCMALLOC( (n+1)*sizeof(int)); CHKPTRQ(fill); 38 /* idnew is location of diagonal in factor */ 39 idnew = (int *) PETSCMALLOC( (n+1)*sizeof(int)); CHKPTRQ(idnew); 40 idnew[0] = 1; 41 42 for ( i=0; i<n; i++ ) { 43 /* first copy previous fill into linked list */ 44 nnz = nz = ai[r[i]+1] - ai[r[i]]; 45 ajtmp = aj + ai[r[i]] - 1; 46 fill[n] = n; 47 while (nz--) { 48 fm = n; 49 idx = ic[*ajtmp++ - 1]; 50 do { 51 m = fm; 52 fm = fill[m]; 53 } while (fm < idx); 54 fill[m] = idx; 55 fill[idx] = fm; 56 } 57 row = fill[n]; 58 while ( row < i ) { 59 ajtmp = ajnew + idnew[row] - 1; 60 nz = ainew[row+1] - idnew[row]; 61 fm = row; 62 while (nz--) { 63 fm = n; 64 idx = *ajtmp++ - 1; 65 do { 66 m = fm; 67 fm = fill[m]; 68 } while (fm < idx); 69 if (fm != idx) { 70 fill[m] = idx; 71 fill[idx] = fm; 72 fm = idx; 73 nnz++; 74 } 75 } 76 row = fill[row]; 77 } 78 /* copy new filled row into permanent storage */ 79 ainew[i+1] = ainew[i] + nnz; 80 if (ainew[i+1] > jmax+1) { 81 /* allocate a longer ajnew */ 82 jmax += nnz*(n-i); 83 ajtmp = (int *) PETSCMALLOC( jmax*sizeof(int) );CHKPTRQ(ajtmp); 84 PETSCMEMCPY(ajtmp,ajnew,(ainew[i]-1)*sizeof(int)); 85 PETSCFREE(ajnew); 86 ajnew = ajtmp; 87 } 88 ajtmp = ajnew + ainew[i] - 1; 89 fm = fill[n]; 90 nzi = 0; 91 while (nnz--) { 92 if (fm < i) nzi++; 93 *ajtmp++ = fm + 1; 94 fm = fill[fm]; 95 } 96 idnew[i] = ainew[i] + nzi; 97 } 98 99 ISDestroy(isicol); PETSCFREE(fill); 100 101 /* put together the new matrix */ 102 ierr = MatCreateSequentialAIJ(mat->comm,n, n, 0, 0, fact); CHKERRQ(ierr); 103 aijnew = (Mat_AIJ *) (*fact)->data; 104 PETSCFREE(aijnew->imax); 105 aijnew->singlemalloc = 0; 106 len = (ainew[n] - 1)*sizeof(Scalar); 107 /* the next line frees the default space generated by the Create() */ 108 PETSCFREE(aijnew->a); PETSCFREE(aijnew->ilen); 109 aijnew->a = (Scalar *) PETSCMALLOC( len ); CHKPTRQ(aijnew->a); 110 aijnew->j = ajnew; 111 aijnew->i = ainew; 112 aijnew->diag = idnew; 113 aijnew->ilen = 0; 114 aijnew->imax = 0; 115 aijnew->row = isrow; 116 aijnew->col = iscol; 117 (*fact)->factor = FACTOR_LU; 118 aijnew->solve_work = (Scalar *) PETSCMALLOC( n*sizeof(Scalar)); 119 CHKPTRQ(aijnew->solve_work); 120 /* In aijnew structure: Free imax, ilen, old a, old j. 121 Allocate idnew, solve_work, new a, new j */ 122 aijnew->mem += (ainew[n]-1-n)*(sizeof(int) + sizeof(Scalar)) + sizeof(int); 123 aijnew->maxnz = aijnew->nz = ainew[n] - 1; 124 125 /* Cannot do this here because child is destroyed before parent created 126 PLogObjectParent(*fact,isicol); */ 127 return 0; 128 } 129 130 int MatLUFactorNumeric_AIJ(Mat mat,Mat *infact) 131 { 132 Mat fact = *infact; 133 Mat_AIJ *aij = (Mat_AIJ *) mat->data, *aijnew = (Mat_AIJ *)fact->data; 134 IS iscol = aijnew->col, isrow = aijnew->row, isicol; 135 int *r,*ic, ierr, i, j, n = aij->m, *ai = aijnew->i, *aj = aijnew->j; 136 int *ajtmpold, *ajtmp, nz, row,*pj; 137 Scalar *rtmp,*v, *pv, *pc, multiplier; 138 139 ierr = ISInvertPermutation(iscol,&isicol); CHKERRQ(ierr); 140 PLogObjectParent(*infact,isicol); 141 ierr = ISGetIndices(isrow,&r); CHKERRQ(ierr); 142 ierr = ISGetIndices(isicol,&ic); CHKERRQ(ierr); 143 rtmp = (Scalar *) PETSCMALLOC( (n+1)*sizeof(Scalar) ); CHKPTRQ(rtmp); 144 145 for ( i=0; i<n; i++ ) { 146 nz = ai[i+1] - ai[i]; 147 ajtmp = aj + ai[i] - 1; 148 for ( j=0; j<nz; j++ ) rtmp[ajtmp[j]-1] = 0.0; 149 150 /* load in initial (unfactored row) */ 151 nz = aij->i[r[i]+1] - aij->i[r[i]]; 152 ajtmpold = aij->j + aij->i[r[i]] - 1; 153 v = aij->a + aij->i[r[i]] - 1; 154 for ( j=0; j<nz; j++ ) rtmp[ic[ajtmpold[j]-1]] = v[j]; 155 156 row = *ajtmp++ - 1; 157 while (row < i) { 158 pc = rtmp + row; 159 if (*pc != 0.0) { 160 nz = aijnew->diag[row] - ai[row]; 161 pv = aijnew->a + aijnew->diag[row] - 1; 162 pj = aijnew->j + aijnew->diag[row]; 163 multiplier = *pc * *pv++; 164 *pc = multiplier; 165 nz = ai[row+1] - ai[row] - 1 - nz; 166 PLogFlops(2*nz); 167 while (nz-->0) rtmp[*pj++ - 1] -= multiplier* *pv++; 168 } 169 row = *ajtmp++ - 1; 170 } 171 /* finished row so stick it into aijnew->a */ 172 pv = aijnew->a + ai[i] - 1; 173 pj = aijnew->j + ai[i] - 1; 174 nz = ai[i+1] - ai[i]; 175 if (rtmp[i] == 0.0) {SETERRQ(1,"Zero pivot detected, sorry");} 176 rtmp[i] = 1.0/rtmp[i]; 177 for ( j=0; j<nz; j++ ) {pv[j] = rtmp[pj[j]-1];} 178 } 179 PETSCFREE(rtmp); 180 ierr = ISRestoreIndices(isicol,&ic); CHKERRQ(ierr); 181 ierr = ISRestoreIndices(isrow,&r); CHKERRQ(ierr); 182 ierr = ISDestroy(isicol); CHKERRQ(ierr); 183 fact->factor = FACTOR_LU; 184 aijnew->assembled = 1; 185 PLogFlops(aijnew->n); 186 return 0; 187 } 188 int MatLUFactor_AIJ(Mat matin,IS row,IS col) 189 { 190 Mat_AIJ *mat = (Mat_AIJ *) matin->data; 191 int ierr; 192 Mat fact; 193 ierr = MatLUFactorSymbolic_AIJ(matin,row,col,&fact); CHKERRQ(ierr); 194 ierr = MatLUFactorNumeric_AIJ(matin,&fact); CHKERRQ(ierr); 195 196 /* free all the data structures from mat */ 197 PETSCFREE(mat->a); 198 if (!mat->singlemalloc) {PETSCFREE(mat->i); PETSCFREE(mat->j);} 199 if (mat->diag) PETSCFREE(mat->diag); 200 if (mat->ilen) PETSCFREE(mat->ilen); 201 if (mat->imax) PETSCFREE(mat->imax); 202 if (mat->row && mat->col && mat->row != mat->col) { 203 ISDestroy(mat->row); 204 } 205 if (mat->col) ISDestroy(mat->col); 206 PETSCFREE(mat); 207 208 PETSCMEMCPY(matin,fact,sizeof(struct _Mat)); 209 PETSCFREE(fact); 210 return 0; 211 } 212 213 int MatSolve_AIJ(Mat mat,Vec bb, Vec xx) 214 { 215 Mat_AIJ *aij = (Mat_AIJ *) mat->data; 216 IS iscol = aij->col, isrow = aij->row; 217 int *r,*c, ierr, i, n = aij->m, *vi, *ai = aij->i, *aj = aij->j; 218 int nz; 219 Scalar *x,*b,*tmp, *aa = aij->a, sum, *v; 220 221 if (mat->factor != FACTOR_LU) 222 SETERRQ(1,"MatSolve_AIJ: Cannot solve with factor."); 223 224 ierr = VecGetArray(bb,&b); CHKERRQ(ierr); 225 ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 226 tmp = aij->solve_work; 227 228 ierr = ISGetIndices(isrow,&r);CHKERRQ(ierr); 229 ierr = ISGetIndices(iscol,&c);CHKERRQ(ierr); c = c + (n-1); 230 231 /* forward solve the lower triangular */ 232 tmp[0] = b[*r++]; 233 for ( i=1; i<n; i++ ) { 234 v = aa + ai[i] - 1; 235 vi = aj + ai[i] - 1; 236 nz = aij->diag[i] - ai[i]; 237 sum = b[*r++]; 238 while (nz--) sum -= *v++ * tmp[*vi++ - 1]; 239 tmp[i] = sum; 240 } 241 242 /* backward solve the upper triangular */ 243 for ( i=n-1; i>=0; i-- ){ 244 v = aa + aij->diag[i]; 245 vi = aj + aij->diag[i]; 246 nz = ai[i+1] - aij->diag[i] - 1; 247 sum = tmp[i]; 248 while (nz--) sum -= *v++ * tmp[*vi++ - 1]; 249 x[*c--] = tmp[i] = sum*aa[aij->diag[i]-1]; 250 } 251 252 PLogFlops(2*aij->nz - aij->n); 253 return 0; 254 } 255 int MatSolveAdd_AIJ(Mat mat,Vec bb, Vec yy, Vec xx) 256 { 257 Mat_AIJ *aij = (Mat_AIJ *) mat->data; 258 IS iscol = aij->col, isrow = aij->row; 259 int *r,*c, ierr, i, n = aij->m, *vi, *ai = aij->i, *aj = aij->j; 260 int nz; 261 Scalar *x,*b,*tmp, *aa = aij->a, sum, *v; 262 263 if (mat->factor != FACTOR_LU) 264 SETERRQ(1,"MatSolveAdd_AIJ: Cannot solve with factor."); 265 if (yy != xx) {ierr = VecCopy(yy,xx); CHKERRQ(ierr);} 266 267 ierr = VecGetArray(bb,&b); CHKERRQ(ierr); 268 ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 269 tmp = aij->solve_work; 270 271 ierr = ISGetIndices(isrow,&r); CHKERRQ(ierr); 272 ierr = ISGetIndices(iscol,&c); CHKERRQ(ierr); c = c + (n-1); 273 274 /* forward solve the lower triangular */ 275 tmp[0] = b[*r++]; 276 for ( i=1; i<n; i++ ) { 277 v = aa + ai[i] - 1; 278 vi = aj + ai[i] - 1; 279 nz = aij->diag[i] - ai[i]; 280 sum = b[*r++]; 281 while (nz--) sum -= *v++ * tmp[*vi++ - 1]; 282 tmp[i] = sum; 283 } 284 285 /* backward solve the upper triangular */ 286 for ( i=n-1; i>=0; i-- ){ 287 v = aa + aij->diag[i]; 288 vi = aj + aij->diag[i]; 289 nz = ai[i+1] - aij->diag[i] - 1; 290 sum = tmp[i]; 291 while (nz--) sum -= *v++ * tmp[*vi++ - 1]; 292 tmp[i] = sum*aa[aij->diag[i]-1]; 293 x[*c--] += tmp[i]; 294 } 295 296 PLogFlops(2*aij->nz); 297 return 0; 298 } 299 /* -------------------------------------------------------------------*/ 300 int MatSolveTrans_AIJ(Mat mat,Vec bb, Vec xx) 301 { 302 Mat_AIJ *aij = (Mat_AIJ *) mat->data; 303 IS iscol = aij->col, isrow = aij->row, invisrow,inviscol; 304 int *r,*c, ierr, i, n = aij->m, *vi, *ai = aij->i, *aj = aij->j; 305 int nz; 306 Scalar *x,*b,*tmp, *aa = aij->a, *v; 307 308 if (mat->factor != FACTOR_LU) 309 SETERRQ(1,"MatSolveTrans_AIJ: Cannot solve with factor."); 310 ierr = VecGetArray(bb,&b); CHKERRQ(ierr); 311 ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 312 tmp = aij->solve_work; 313 314 /* invert the permutations */ 315 ierr = ISInvertPermutation(isrow,&invisrow); CHKERRQ(ierr); 316 ierr = ISInvertPermutation(iscol,&inviscol); CHKERRQ(ierr); 317 318 319 ierr = ISGetIndices(invisrow,&r); CHKERRQ(ierr); 320 ierr = ISGetIndices(inviscol,&c); CHKERRQ(ierr); 321 322 /* copy the b into temp work space according to permutation */ 323 for ( i=0; i<n; i++ ) tmp[c[i]] = b[i]; 324 325 /* forward solve the U^T */ 326 for ( i=0; i<n; i++ ) { 327 v = aa + aij->diag[i] - 1; 328 vi = aj + aij->diag[i]; 329 nz = ai[i+1] - aij->diag[i] - 1; 330 tmp[i] *= *v++; 331 while (nz--) { 332 tmp[*vi++ - 1] -= (*v++)*tmp[i]; 333 } 334 } 335 336 /* backward solve the L^T */ 337 for ( i=n-1; i>=0; i-- ){ 338 v = aa + aij->diag[i] - 2; 339 vi = aj + aij->diag[i] - 2; 340 nz = aij->diag[i] - ai[i]; 341 while (nz--) { 342 tmp[*vi-- - 1] -= (*v--)*tmp[i]; 343 } 344 } 345 346 /* copy tmp into x according to permutation */ 347 for ( i=0; i<n; i++ ) x[r[i]] = tmp[i]; 348 349 ISDestroy(invisrow); ISDestroy(inviscol); 350 351 PLogFlops(2*aij->nz-aij->n); 352 return 0; 353 } 354 355 int MatSolveTransAdd_AIJ(Mat mat,Vec bb, Vec zz,Vec xx) 356 { 357 Mat_AIJ *aij = (Mat_AIJ *) mat->data; 358 IS iscol = aij->col, isrow = aij->row, invisrow,inviscol; 359 int *r,*c, ierr, i, n = aij->m, *vi, *ai = aij->i, *aj = aij->j; 360 int nz; 361 Scalar *x,*b,*tmp, *aa = aij->a, *v; 362 363 if (mat->factor != FACTOR_LU) 364 SETERRQ(1,"MatSolveTransAdd_AIJ: Cannot solve with factor."); 365 if (zz != xx) VecCopy(zz,xx); 366 367 ierr = VecGetArray(bb,&b); CHKERRQ(ierr); 368 ierr = VecGetArray(xx,&x); CHKERRQ(ierr); 369 tmp = aij->solve_work; 370 371 /* invert the permutations */ 372 ierr = ISInvertPermutation(isrow,&invisrow); CHKERRQ(ierr); 373 ierr = ISInvertPermutation(iscol,&inviscol); CHKERRQ(ierr); 374 375 376 ierr = ISGetIndices(invisrow,&r); CHKERRQ(ierr); 377 ierr = ISGetIndices(inviscol,&c); CHKERRQ(ierr); 378 379 /* copy the b into temp work space according to permutation */ 380 for ( i=0; i<n; i++ ) tmp[c[i]] = b[i]; 381 382 /* forward solve the U^T */ 383 for ( i=0; i<n; i++ ) { 384 v = aa + aij->diag[i] - 1; 385 vi = aj + aij->diag[i]; 386 nz = ai[i+1] - aij->diag[i] - 1; 387 tmp[i] *= *v++; 388 while (nz--) { 389 tmp[*vi++ - 1] -= (*v++)*tmp[i]; 390 } 391 } 392 393 /* backward solve the L^T */ 394 for ( i=n-1; i>=0; i-- ){ 395 v = aa + aij->diag[i] - 2; 396 vi = aj + aij->diag[i] - 2; 397 nz = aij->diag[i] - ai[i]; 398 while (nz--) { 399 tmp[*vi-- - 1] -= (*v--)*tmp[i]; 400 } 401 } 402 403 /* copy tmp into x according to permutation */ 404 for ( i=0; i<n; i++ ) x[r[i]] += tmp[i]; 405 406 ISDestroy(invisrow); ISDestroy(inviscol); 407 408 PLogFlops(2*aij->nz); 409 return 0; 410 } 411 /* ----------------------------------------------------------------*/ 412 int MatILUFactorSymbolic_AIJ(Mat mat,IS isrow,IS iscol,int levels,Mat *fact) 413 { 414 Mat_AIJ *aij = (Mat_AIJ *) mat->data, *aijnew; 415 IS isicol; 416 int *r,*ic, ierr, i, n = aij->m, *ai = aij->i, *aj = aij->j; 417 int *ainew,*ajnew, jmax,*fill, *ajtmp, nz, *lfill,*ajfill,*ajtmpf; 418 int *idnew, idx, row,m,fm, nnz, nzi,len; 419 420 if (n != aij->n) 421 SETERRQ(1,"MatILUFactorSymbolic_AIJ: Matrix must be square."); 422 if (!isrow) 423 SETERRQ(1,"MatILUFactorSymbolic_AIJ: Matrix must have row permutation."); 424 if (!iscol) SETERRQ(1, 425 "MatILUFactorSymbolic_AIJ: Matrix must have column permutation."); 426 427 ierr = ISInvertPermutation(iscol,&isicol); CHKERRQ(ierr); 428 ISGetIndices(isrow,&r); ISGetIndices(isicol,&ic); 429 430 /* get new row pointers */ 431 ainew = (int *) PETSCMALLOC( (n+1)*sizeof(int) ); CHKPTRQ(ainew); 432 ainew[0] = 1; 433 /* don't know how many column pointers are needed so estimate */ 434 jmax = 2*ai[n]; 435 ajnew = (int *) PETSCMALLOC( (jmax)*sizeof(int) ); CHKPTRQ(ajnew); 436 /* ajfill is level of fill for each fill entry */ 437 ajfill = (int *) PETSCMALLOC( (jmax)*sizeof(int) ); CHKPTRQ(ajfill); 438 /* fill is a linked list of nonzeros in active row */ 439 fill = (int *) PETSCMALLOC( (n+1)*sizeof(int)); CHKPTRQ(fill); 440 /* lfill is level for each filled value */ 441 lfill = (int *) PETSCMALLOC( (n+1)*sizeof(int)); CHKPTRQ(lfill); 442 /* idnew is location of diagonal in factor */ 443 idnew = (int *) PETSCMALLOC( (n+1)*sizeof(int)); CHKPTRQ(idnew); 444 idnew[0] = 1; 445 446 for ( i=0; i<n; i++ ) { 447 /* first copy previous fill into linked list */ 448 nnz = nz = ai[r[i]+1] - ai[r[i]]; 449 ajtmp = aj + ai[r[i]] - 1; 450 fill[n] = n; 451 while (nz--) { 452 fm = n; 453 idx = ic[*ajtmp++ - 1]; 454 do { 455 m = fm; 456 fm = fill[m]; 457 } while (fm < idx); 458 fill[m] = idx; 459 fill[idx] = fm; 460 lfill[idx] = -1; 461 } 462 row = fill[n]; 463 while ( row < i ) { 464 ajtmp = ajnew + idnew[row] - 1; 465 ajtmpf = ajfill + idnew[row] - 1; 466 nz = ainew[row+1] - idnew[row]; 467 fm = row; 468 while (nz--) { 469 fm = n; 470 idx = *ajtmp++ - 1; 471 do { 472 m = fm; 473 fm = fill[m]; 474 } while (fm < idx); 475 if (fm != idx) { 476 lfill[idx] = *ajtmpf + 1; 477 if (lfill[idx] < levels) { 478 fill[m] = idx; 479 fill[idx] = fm; 480 fm = idx; 481 nnz++; 482 } 483 } 484 ajtmpf++; 485 } 486 row = fill[row]; 487 } 488 /* copy new filled row into permanent storage */ 489 ainew[i+1] = ainew[i] + nnz; 490 if (ainew[i+1] > jmax+1) { 491 /* allocate a longer ajnew */ 492 jmax += nnz*(n-i); 493 ajtmp = (int *) PETSCMALLOC( jmax*sizeof(int) );CHKPTRQ(ajtmp); 494 PETSCMEMCPY(ajtmp,ajnew,(ainew[i]-1)*sizeof(int)); 495 PETSCFREE(ajnew); 496 ajnew = ajtmp; 497 /* allocate a longer ajfill */ 498 ajtmp = (int *) PETSCMALLOC( jmax*sizeof(int) );CHKPTRQ(ajtmp); 499 PETSCMEMCPY(ajtmp,ajfill,(ainew[i]-1)*sizeof(int)); 500 PETSCFREE(ajfill); 501 ajfill = ajtmp; 502 } 503 ajtmp = ajnew + ainew[i] - 1; 504 ajtmpf = ajfill + ainew[i] - 1; 505 fm = fill[n]; 506 nzi = 0; 507 while (nnz--) { 508 if (fm < i) nzi++; 509 *ajtmp++ = fm + 1; 510 *ajtmpf++ = lfill[fm]; 511 fm = fill[fm]; 512 } 513 idnew[i] = ainew[i] + nzi; 514 } 515 PETSCFREE(ajfill); 516 ISDestroy(isicol); PETSCFREE(fill); PETSCFREE(lfill); 517 518 /* put together the new matrix */ 519 ierr = MatCreateSequentialAIJ(mat->comm,n, n, 0, 0, fact); CHKERRQ(ierr); 520 aijnew = (Mat_AIJ *) (*fact)->data; 521 PETSCFREE(aijnew->imax); 522 aijnew->singlemalloc = 0; 523 len = (ainew[n] - 1)*sizeof(Scalar); 524 /* the next line frees the default space generated by the Create() */ 525 PETSCFREE(aijnew->a); PETSCFREE(aijnew->ilen); 526 aijnew->a = (Scalar *) PETSCMALLOC( len ); CHKPTRQ(aijnew->a); 527 aijnew->j = ajnew; 528 aijnew->i = ainew; 529 aijnew->diag = idnew; 530 aijnew->ilen = 0; 531 aijnew->imax = 0; 532 aijnew->row = isrow; 533 aijnew->col = iscol; 534 aijnew->solve_work = (Scalar *) PETSCMALLOC( (n+1)*sizeof(Scalar)); 535 CHKPTRQ(aijnew->solve_work); 536 /* In aijnew structure: Free imax, ilen, old a, old j. 537 Allocate idnew, solve_work, new a, new j */ 538 aijnew->mem += (ainew[n]-1-n)*(sizeof(int) + sizeof(Scalar)) + sizeof(int); 539 aijnew->maxnz = aijnew->nz = ainew[n] - 1; 540 (*fact)->factor = FACTOR_LU; 541 return 0; 542 } 543