Actual source code: icc.c

  1: /*
  2:    Defines a Cholesky factorization preconditioner for any Mat implementation.
  3:   Presently only provided for MPIRowbs format (i.e. BlockSolve).
  4: */

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

 11: PetscErrorCode PCICCSetMatOrdering_ICC(PC pc,MatOrderingType ordering)
 12: {
 13:   PC_ICC         *dir = (PC_ICC*)pc->data;
 15: 
 17:   PetscStrfree(dir->ordering);
 18:   PetscStrallocpy(ordering,&dir->ordering);
 19:   return(0);
 20: }

 26: PetscErrorCode PCICCSetDamping_ICC(PC pc,PetscReal damping)
 27: {
 28:   PC_ICC *dir;

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

 40: PetscErrorCode PCICCSetShift_ICC(PC pc,PetscTruth shift)
 41: {
 42:   PC_ICC *dir;

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

 55: PetscErrorCode PCICCSetZeroPivot_ICC(PC pc,PetscReal z)
 56: {
 57:   PC_ICC *lu;

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

 69: PetscErrorCode PCICCSetFill_ICC(PC pc,PetscReal fill)
 70: {
 71:   PC_ICC *dir;

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

 83: PetscErrorCode PCICCSetLevels_ICC(PC pc,PetscInt levels)
 84: {
 85:   PC_ICC *icc;

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

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

100:     Collective on PC

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

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

109:     Level: intermediate

111: .seealso: PCLUSetMatOrdering()

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

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

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

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

134:    Collective on PC

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

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

143:    Level: intermediate

145:    Concepts: ICC^setting levels of fill

147: @*/
148: PetscErrorCode PCICCSetLevels(PC pc,PetscInt levels)
149: {
150:   PetscErrorCode ierr,(*f)(PC,PetscInt);

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

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

168:    Collective on PC

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

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

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

183:    Level: intermediate

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

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

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

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

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

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

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

221:    Level: intermediate

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

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

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

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

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

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

258:    Level: intermediate

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

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

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

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

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

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

291:    Level: intermediate

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

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

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

312: static PetscErrorCode PCSetup_ICC(PC pc)
313: {
314:   PC_ICC         *icc = (PC_ICC*)pc->data;
315:   IS             perm,cperm;

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

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

335: static PetscErrorCode PCDestroy_ICC(PC pc)
336: {
337:   PC_ICC         *icc = (PC_ICC*)pc->data;

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

349: static PetscErrorCode PCApply_ICC(PC pc,Vec x,Vec y)
350: {
351:   PC_ICC         *icc = (PC_ICC*)pc->data;

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

361: static PetscErrorCode PCApplySymmetricLeft_ICC(PC pc,Vec x,Vec y)
362: {
364:   PC_ICC         *icc = (PC_ICC*)pc->data;

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

373: static PetscErrorCode PCApplySymmetricRight_ICC(PC pc,Vec x,Vec y)
374: {
376:   PC_ICC         *icc = (PC_ICC*)pc->data;

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

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

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

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

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

430: static PetscErrorCode PCView_ICC(PC pc,PetscViewer viewer)
431: {
432:   PC_ICC         *icc = (PC_ICC*)pc->data;
434:   PetscTruth     isstring,iascii;

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

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

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

468:    Level: beginner

470:   Concepts: incomplete Cholesky factorization

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

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

476:           The Manteuffel shift is only implemented for matrices with block size 1

478:           By default, the Manteuffel is applied (for matrices with block size 1). Call PCICCSetShift(pc,PETSC_FALSE);
479:           to turn off the shift.


482: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCSOR, MatOrderingType,
483:            PCICCSetSetZeroPivot(), PCICCSetDamping(), PCICCSetShift(), 
484:            PCICCSetFill(), PCICCSetMatOrdering(), PCICCSetReuseOrdering(), 
485:            PCICCSetLevels()

487: M*/

492: PetscErrorCode PCCreate_ICC(PC pc)
493: {
495:   PC_ICC         *icc;

498:   PetscNew(PC_ICC,&icc);
499:   PetscLogObjectMemory(pc,sizeof(PC_ICC));

501:   icc->fact                  = 0;
502:   PetscStrallocpy(MATORDERING_NATURAL,&icc->ordering);
503:   MatFactorInfoInitialize(&icc->info);
504:   icc->info.levels          = 0;
505:   icc->info.fill          = 1.0;
506:   icc->implctx            = 0;

508:   icc->info.dtcol              = PETSC_DEFAULT;
509:   icc->info.damping            = 0.0;
510:   icc->info.shift              = PETSC_TRUE;
511:   icc->info.shift_fraction     = 0.0;
512:   icc->info.zeropivot          = 1.e-12;
513:   pc->data                       = (void*)icc;

515:   pc->ops->apply               = PCApply_ICC;
516:   pc->ops->setup               = PCSetup_ICC;
517:   pc->ops->destroy               = PCDestroy_ICC;
518:   pc->ops->setfromoptions      = PCSetFromOptions_ICC;
519:   pc->ops->view                = PCView_ICC;
520:   pc->ops->getfactoredmatrix   = PCGetFactoredMatrix_ICC;
521:   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_ICC;
522:   pc->ops->applysymmetricright = PCApplySymmetricRight_ICC;

524:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetLevels_C","PCICCSetLevels_ICC",
525:                     PCICCSetLevels_ICC);
526:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetFill_C","PCICCSetFill_ICC",
527:                     PCICCSetFill_ICC);
528:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetDamping_C","PCICCSetDamping_ICC",
529:                     PCICCSetDamping_ICC);
530:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetShift_C","PCICCSetShift_ICC",
531:                     PCICCSetShift_ICC);
532:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetMatOrdering_C","PCICCSetMatOrdering_ICC",
533:                     PCICCSetMatOrdering_ICC);
534:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetZeroPivot_C","PCICCSetZeroPivot_ICC",
535:                     PCICCSetZeroPivot_ICC);
536:   return(0);
537: }