Actual source code: icc.c

  1: /*$Id: icc.c,v 1.82 2001/08/06 21:16:31 bsmith Exp $*/
  2: /*
  3:    Defines a Cholesky factorization preconditioner for any Mat implementation.
  4:   Presently only provided for MPIRowbs format (i.e. BlockSolve).
  5: */

 7:  #include src/ksp/pc/impls/icc/icc.h

  9: EXTERN_C_BEGIN
 12: int PCICCSetMatOrdering_ICC(PC pc,MatOrderingType ordering)
 13: {
 14:   PC_ICC *dir = (PC_ICC*)pc->data;
 15:   int    ierr;
 16: 
 18:   PetscStrfree(dir->ordering);
 19:   PetscStrallocpy(ordering,&dir->ordering);
 20:   return(0);
 21: }
 22: EXTERN_C_END

 24: EXTERN_C_BEGIN
 27: int PCICCSetDamping_ICC(PC pc,PetscReal damping)
 28: {
 29:   PC_ICC *dir;

 32:   dir = (PC_ICC*)pc->data;
 33:   dir->info.damping = damping;
 34:   return(0);
 35: }
 36: EXTERN_C_END

 38: EXTERN_C_BEGIN
 41: int PCICCSetShift_ICC(PC pc,PetscTruth shift)
 42: {
 43:   PC_ICC *dir;

 46:   dir = (PC_ICC*)pc->data;
 47:   dir->info.shift = shift;
 48:   if (shift) dir->info.shift_fraction = 0.0;
 49:   return(0);
 50: }
 51: EXTERN_C_END

 53: EXTERN_C_BEGIN
 56: int PCICCSetZeroPivot_ICC(PC pc,PetscReal z)
 57: {
 58:   PC_ICC *lu;

 61:   lu                 = (PC_ICC*)pc->data;
 62:   lu->info.zeropivot = z;
 63:   return(0);
 64: }
 65: EXTERN_C_END

 67: EXTERN_C_BEGIN
 70: int PCICCSetFill_ICC(PC pc,PetscReal fill)
 71: {
 72:   PC_ICC *dir;

 75:   dir            = (PC_ICC*)pc->data;
 76:   dir->info.fill = fill;
 77:   return(0);
 78: }
 79: EXTERN_C_END

 81: EXTERN_C_BEGIN
 84: int PCICCSetLevels_ICC(PC pc,int levels)
 85: {
 86:   PC_ICC *icc;

 89:   icc = (PC_ICC*)pc->data;
 90:   icc->info.levels = levels;
 91:   return(0);
 92: }
 93: EXTERN_C_END

 97: /*@
 98:     PCICCSetMatOrdering - Sets the ordering routine (to reduce fill) to 
 99:     be used it the ICC factorization.

101:     Collective on PC

103:     Input Parameters:
104: +   pc - the preconditioner context
105: -   ordering - the matrix ordering name, for example, MATORDERING_ND or MATORDERING_RCM

107:     Options Database Key:
108: .   -pc_icc_mat_ordering_type <nd,rcm,...> - Sets ordering routine

110:     Level: intermediate

112: .seealso: PCLUSetMatOrdering()

114: .keywords: PC, ICC, set, matrix, reordering

116: @*/
117: int PCICCSetMatOrdering(PC pc,MatOrderingType ordering)
118: {
119:   int ierr,(*f)(PC,MatOrderingType);

123:   PetscObjectQueryFunction((PetscObject)pc,"PCICCSetMatOrdering_C",(void (**)(void))&f);
124:   if (f) {
125:     (*f)(pc,ordering);
126:   }
127:   return(0);
128: }

132: /*@
133:    PCICCSetLevels - Sets the number of levels of fill to use.

135:    Collective on PC

137:    Input Parameters:
138: +  pc - the preconditioner context
139: -  levels - number of levels of fill

141:    Options Database Key:
142: .  -pc_icc_levels <levels> - Sets fill level

144:    Level: intermediate

146:    Concepts: ICC^setting levels of fill

148: @*/
149: int PCICCSetLevels(PC pc,int levels)
150: {
151:   int ierr,(*f)(PC,int);

155:   if (levels < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"negative levels");
156:   PetscObjectQueryFunction((PetscObject)pc,"PCICCSetLevels_C",(void (**)(void))&f);
157:   if (f) {
158:     (*f)(pc,levels);
159:   }
160:   return(0);
161: }

165: /*@
166:    PCICCSetFill - Indicate the amount of fill you expect in the factored matrix,
167:    where fill = number nonzeros in factor/number nonzeros in original matrix.

169:    Collective on PC

171:    Input Parameters:
172: +  pc - the preconditioner context
173: -  fill - amount of expected fill

175:    Options Database Key:
176: $  -pc_icc_fill <fill>

178:    Note:
179:    For sparse matrix factorizations it is difficult to predict how much 
180:    fill to expect. By running with the option -log_info PETSc will print the 
181:    actual amount of fill used; allowing you to set the value accurately for
182:    future runs. But default PETSc uses a value of 1.0

184:    Level: intermediate

186: .keywords: PC, set, factorization, direct, fill

188: .seealso: PCLUSetFill()
189: @*/
190: int PCICCSetFill(PC pc,PetscReal fill)
191: {
192:   int ierr,(*f)(PC,PetscReal);

196:   if (fill < 1.0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Fill factor cannot be less than 1.0");
197:   PetscObjectQueryFunction((PetscObject)pc,"PCICCSetFill_C",(void (**)(void))&f);
198:   if (f) {
199:     (*f)(pc,fill);
200:   }
201:   return(0);
202: }

206: /*@
207:    PCICCSetDamping - adds this quantity to the diagonal of the matrix during the 
208:      ICC numerical factorization

210:    Collective on PC
211:    
212:    Input Parameters:
213: +  pc - the preconditioner context
214: -  damping - amount of damping

216:    Options Database Key:
217: .  -pc_icc_damping <damping> - Sets damping amount or PETSC_DECIDE for the default

219:    Note: If 0.0 is given, then no damping is used. If a diagonal element is classified as a zero
220:          pivot, then the damping is doubled until this is alleviated.

222:    Level: intermediate

224: .keywords: PC, set, factorization, direct, fill

226: .seealso: PCICCSetFill(), PCLUSetDamping()
227: @*/
228: int PCICCSetDamping(PC pc,PetscReal damping)
229: {
230:   int ierr,(*f)(PC,PetscReal);

234:   PetscObjectQueryFunction((PetscObject)pc,"PCICCSetDamping_C",(void (**)(void))&f);
235:   if (f) {
236:     (*f)(pc,damping);
237:   }
238:   return(0);
239: }

243: /*@
244:    PCICCSetShift - specify whether to use Manteuffel shifting of ICC.
245:    If an ICC factorisation breaks down because of nonpositive pivots,
246:    adding sufficient identity to the diagonal will remedy this.
247:    
248:    Manteuffel shifting for ICC uses a different algorithm than the ILU case.
249:    Here we base the shift on the lack of diagonal dominance when a negative
250:    pivot occurs.

252:    Input parameters:
253: +  pc - the preconditioner context
254: -  shifting - PETSC_TRUE to set shift else PETSC_FALSE

256:    Options Database Key:
257: .  -pc_icc_shift - Activate PCICCSetShift()

259:    Level: intermediate

261: .keywords: PC, indefinite, factorization, incomplete, ICC

263: .seealso: PCILUSetShift()
264: @*/
265: int PCICCSetShift(PC pc,PetscTruth shift)
266: {
267:   int ierr,(*f)(PC,PetscTruth);

271:   PetscObjectQueryFunction((PetscObject)pc,"PCICCSetShift_C",(void (**)(void))&f);
272:   if (f) {
273:     (*f)(pc,shift);
274:   }
275:   return(0);
276: }

280: /*@
281:    PCICCSetZeroPivot - Sets the size at which smaller pivots are declared to be zero

283:    Collective on PC
284:    
285:    Input Parameters:
286: +  pc - the preconditioner context
287: -  zero - all pivots smaller than this will be considered zero

289:    Options Database Key:
290: .  -pc_ilu_zeropivot <zero> - Sets the zero pivot size

292:    Level: intermediate

294: .keywords: PC, set, factorization, direct, fill

296: .seealso: PCICCSetFill(), PCLUSetDamp(), PCLUSetZeroPivot()
297: @*/
298: int PCICCSetZeroPivot(PC pc,PetscReal zero)
299: {
300:   int ierr,(*f)(PC,PetscReal);

304:   PetscObjectQueryFunction((PetscObject)pc,"PCICCSetZeroPivot_C",(void (**)(void))&f);
305:   if (f) {
306:     (*f)(pc,zero);
307:   }
308:   return(0);
309: }

313: static int PCSetup_ICC(PC pc)
314: {
315:   PC_ICC *icc = (PC_ICC*)pc->data;
316:   IS     perm,cperm;
317:   int    ierr;

320:   MatGetOrdering(pc->pmat,icc->ordering,&perm,&cperm);

322:   if (!pc->setupcalled) {
323:     MatICCFactorSymbolic(pc->pmat,perm,&icc->info,&icc->fact);
324:   } else if (pc->flag != SAME_NONZERO_PATTERN) {
325:     MatDestroy(icc->fact);
326:     MatICCFactorSymbolic(pc->pmat,perm,&icc->info,&icc->fact);
327:   }
328:   ISDestroy(cperm);
329:   ISDestroy(perm);
330:   MatCholeskyFactorNumeric(pc->pmat,&icc->fact);
331:   return(0);
332: }

336: static int PCDestroy_ICC(PC pc)
337: {
338:   PC_ICC *icc = (PC_ICC*)pc->data;
339:   int    ierr;

342:   if (icc->fact) {MatDestroy(icc->fact);}
343:   PetscStrfree(icc->ordering);
344:   PetscFree(icc);
345:   return(0);
346: }

350: static int PCApply_ICC(PC pc,Vec x,Vec y)
351: {
352:   PC_ICC *icc = (PC_ICC*)pc->data;
353:   int    ierr;

356:   MatSolve(icc->fact,x,y);
357:   return(0);
358: }

362: static int PCApplySymmetricLeft_ICC(PC pc,Vec x,Vec y)
363: {
364:   int    ierr;
365:   PC_ICC *icc = (PC_ICC*)pc->data;

368:   MatForwardSolve(icc->fact,x,y);
369:   return(0);
370: }

374: static int PCApplySymmetricRight_ICC(PC pc,Vec x,Vec y)
375: {
376:   int    ierr;
377:   PC_ICC *icc = (PC_ICC*)pc->data;

380:   MatBackwardSolve(icc->fact,x,y);
381:   return(0);
382: }

386: static int PCGetFactoredMatrix_ICC(PC pc,Mat *mat)
387: {
388:   PC_ICC *icc = (PC_ICC*)pc->data;

391:   *mat = icc->fact;
392:   return(0);
393: }

397: static int PCSetFromOptions_ICC(PC pc)
398: {
399:   PC_ICC     *icc = (PC_ICC*)pc->data;
400:   char       tname[256];
401:   PetscTruth flg;
402:   int        ierr;
403:   PetscFList ordlist;

406:   MatOrderingRegisterAll(PETSC_NULL);
407:   PetscOptionsHead("ICC Options");
408:     PetscOptionsReal("-pc_icc_levels","levels of fill","PCICCSetLevels",icc->info.levels,&icc->info.levels,&flg);
409:     PetscOptionsReal("-pc_icc_fill","Expected fill in factorization","PCICCSetFill",icc->info.fill,&icc->info.fill,&flg);
410:     MatGetOrderingList(&ordlist);
411:     PetscOptionsList("-pc_icc_mat_ordering_type","Reorder to reduce nonzeros in ICC","PCICCSetMatOrdering",ordlist,icc->ordering,tname,256,&flg);
412:     if (flg) {
413:       PCICCSetMatOrdering(pc,tname);
414:     }
415:     PetscOptionsName("-pc_icc_damping","Damping added to diagonal","PCICCSetDamping",&flg);
416:     if (flg) {
417:       PCICCSetDamping(pc,(PetscReal) PETSC_DECIDE);
418:     }
419:     PetscOptionsReal("-pc_icc_damping","Damping added to diagonal","PCICCSetDamping",icc->info.damping,&icc->info.damping,0);
420:     PetscOptionsName("-pc_icc_shift","Manteuffel shift applied to diagonal","PCICCSetShift",&flg);
421:     if (flg) {
422:       PCICCSetShift(pc,PETSC_TRUE);
423:     }
424:     PetscOptionsReal("-pc_icc_zeropivot","Pivot is considered zero if less than","PCICCSetSetZeroPivot",icc->info.zeropivot,&icc->info.zeropivot,0);
425:   PetscOptionsTail();
426:   return(0);
427: }

431: static int PCView_ICC(PC pc,PetscViewer viewer)
432: {
433:   PC_ICC     *icc = (PC_ICC*)pc->data;
434:   int        ierr;
435:   PetscTruth isstring,isascii;

438:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
439:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
440:   if (isascii) {
441:     if (icc->info.levels == 1) {
442:         PetscViewerASCIIPrintf(viewer,"  ICC: %d level of fill\n",(int)icc->info.levels);
443:     } else {
444:         PetscViewerASCIIPrintf(viewer,"  ICC: %d levels of fill\n",(int)icc->info.levels);
445:     }
446:     PetscViewerASCIIPrintf(viewer,"  ICC: max fill ratio allocated %g\n",icc->info.fill);
447:     if (icc->info.shift) {PetscViewerASCIIPrintf(viewer,"  ICC: using Manteuffel shift\n");}
448:   } else if (isstring) {
449:     PetscViewerStringSPrintf(viewer," lvls=%d",(int)icc->info.levels);
450:   } else {
451:     SETERRQ1(1,"Viewer type %s not supported for PCICC",((PetscObject)viewer)->type_name);
452:   }
453:   return(0);
454: }

456: /*MC
457:      PCICC - Incomplete Cholesky factorization preconditioners.

459:    Options Database Keys:
460: +  -pc_icc_levels <k> - number of levels of fill for ICC(k)
461: .  -pc_icc_in_place - only for ICC(0) with natural ordering, reuses the space of the matrix for
462:                       its factorization (overwrites original matrix)
463: .  -pc_icc_damping - add damping to diagonal to prevent zero (or very small) pivots
464: .  -pc_icc_shift - apply Manteuffel shift to diagonal to force positive definite preconditioner
465: .  -pc_icc_zeropivot <tol> - set tolerance for what is considered a zero pivot
466: .  -pc_icc_fill <nfill> - expected amount of fill in factored matrix compared to original matrix, nfill > 1
467: -  -pc_icc_mat_ordering_type <natural,nd,1wd,rcm,qmd> - set the row/column ordering of the factored matrix

469:    Level: beginner

471:   Concepts: incomplete Cholesky factorization

473:    Notes: Only implemented for some matrix formats. Not implemented in parallel

475:           For BAIJ matrices this implements a point block ICC.

477: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCSOR, MatOrderingType,
478:            PCICCSetSetZeroPivot(), PCICCSetDamping(), PCICCSetShift(), 
479:            PCICCSetFill(), PCICCSetMatOrdering(), PCICCSetReuseOrdering(), 
480:            PCICCSetLevels()

482: M*/

484: EXTERN_C_BEGIN
487: int PCCreate_ICC(PC pc)
488: {
489:   int    ierr;
490:   PC_ICC *icc;

493:   PetscNew(PC_ICC,&icc);
494:   PetscLogObjectMemory(pc,sizeof(PC_ICC));

496:   icc->fact                  = 0;
497:   PetscStrallocpy(MATORDERING_NATURAL,&icc->ordering);
498:   icc->info.levels          = 0;
499:   icc->info.fill          = 1.0;
500:   icc->implctx            = 0;

502:   icc->info.dtcol              = PETSC_DEFAULT;
503:   icc->info.damping            = 0.0;
504:   icc->info.shift              = PETSC_FALSE;
505:   icc->info.shift_fraction     = 0.0;
506:   icc->info.zeropivot          = 1.e-12;
507:   pc->data                       = (void*)icc;

509:   pc->ops->apply               = PCApply_ICC;
510:   pc->ops->setup               = PCSetup_ICC;
511:   pc->ops->destroy               = PCDestroy_ICC;
512:   pc->ops->setfromoptions      = PCSetFromOptions_ICC;
513:   pc->ops->view                = PCView_ICC;
514:   pc->ops->getfactoredmatrix   = PCGetFactoredMatrix_ICC;
515:   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_ICC;
516:   pc->ops->applysymmetricright = PCApplySymmetricRight_ICC;

518:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetLevels_C","PCICCSetLevels_ICC",
519:                     PCICCSetLevels_ICC);
520:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetFill_C","PCICCSetFill_ICC",
521:                     PCICCSetFill_ICC);
522:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetDamping_C","PCICCSetDamping_ICC",
523:                     PCICCSetDamping_ICC);
524:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetShift_C","PCICCSetShift_ICC",
525:                     PCICCSetShift_ICC);
526:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetMatOrdering_C","PCICCSetMatOrdering_ICC",
527:                     PCICCSetMatOrdering_ICC);
528:   return(0);
529: }
530: EXTERN_C_END