Actual source code: icc.c

  1: #define PETSCKSP_DLL

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

 8:  #include src/ksp/pc/impls/factor/icc/icc.h

 13: PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetZeroPivot_ICC(PC pc,PetscReal z)
 14: {
 15:   PC_ICC *icc;

 18:   icc                 = (PC_ICC*)pc->data;
 19:   icc->info.zeropivot = z;
 20:   return(0);
 21: }

 27: PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftNonzero_ICC(PC pc,PetscReal shift)
 28: {
 29:   PC_ICC *dir;

 32:   dir = (PC_ICC*)pc->data;
 33:   if (shift == (PetscReal) PETSC_DECIDE) {
 34:     dir->info.shiftnz = 1.e-12;
 35:   } else {
 36:     dir->info.shiftnz = shift;
 37:   }
 38:   return(0);
 39: }

 45: PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftPd_ICC(PC pc,PetscTruth shift)
 46: {
 47:   PC_ICC *dir;
 48: 
 50:   dir = (PC_ICC*)pc->data;
 51:   dir->info.shiftpd = shift;
 52:   if (shift) dir->info.shift_fraction = 0.0;
 53:   return(0);
 54: }

 60: PetscErrorCode PETSCKSP_DLLEXPORT PCICCSetMatOrdering_ICC(PC pc,MatOrderingType ordering)
 61: {
 62:   PC_ICC         *dir = (PC_ICC*)pc->data;
 64: 
 66:   PetscStrfree(dir->ordering);
 67:   PetscStrallocpy(ordering,&dir->ordering);
 68:   return(0);
 69: }

 75: PetscErrorCode PETSCKSP_DLLEXPORT PCICCSetFill_ICC(PC pc,PetscReal fill)
 76: {
 77:   PC_ICC *dir;

 80:   dir            = (PC_ICC*)pc->data;
 81:   dir->info.fill = fill;
 82:   return(0);
 83: }

 89: PetscErrorCode PETSCKSP_DLLEXPORT PCICCSetLevels_ICC(PC pc,PetscInt levels)
 90: {
 91:   PC_ICC *icc;

 94:   icc = (PC_ICC*)pc->data;
 95:   icc->info.levels = levels;
 96:   return(0);
 97: }

102: /*@
103:     PCICCSetMatOrdering - Sets the ordering routine (to reduce fill) to 
104:     be used it the ICC factorization.

106:     Collective on PC

108:     Input Parameters:
109: +   pc - the preconditioner context
110: -   ordering - the matrix ordering name, for example, MATORDERING_ND or MATORDERING_RCM

112:     Options Database Key:
113: .   -pc_icc_mat_ordering_type <nd,rcm,...> - Sets ordering routine

115:     Level: intermediate

117: .seealso: PCLUSetMatOrdering()

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

121: @*/
122: PetscErrorCode PETSCKSP_DLLEXPORT PCICCSetMatOrdering(PC pc,MatOrderingType ordering)
123: {
124:   PetscErrorCode ierr,(*f)(PC,MatOrderingType);

128:   PetscObjectQueryFunction((PetscObject)pc,"PCICCSetMatOrdering_C",(void (**)(void))&f);
129:   if (f) {
130:     (*f)(pc,ordering);
131:   }
132:   return(0);
133: }

137: /*@
138:    PCICCSetLevels - Sets the number of levels of fill to use.

140:    Collective on PC

142:    Input Parameters:
143: +  pc - the preconditioner context
144: -  levels - number of levels of fill

146:    Options Database Key:
147: .  -pc_icc_levels <levels> - Sets fill level

149:    Level: intermediate

151:    Concepts: ICC^setting levels of fill

153: @*/
154: PetscErrorCode PETSCKSP_DLLEXPORT PCICCSetLevels(PC pc,PetscInt levels)
155: {
156:   PetscErrorCode ierr,(*f)(PC,PetscInt);

160:   if (levels < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"negative levels");
161:   PetscObjectQueryFunction((PetscObject)pc,"PCICCSetLevels_C",(void (**)(void))&f);
162:   if (f) {
163:     (*f)(pc,levels);
164:   }
165:   return(0);
166: }

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

174:    Collective on PC

176:    Input Parameters:
177: +  pc - the preconditioner context
178: -  fill - amount of expected fill

180:    Options Database Key:
181: $  -pc_icc_fill <fill>

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

189:    Level: intermediate

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

193: .seealso: PCLUSetFill()
194: @*/
195: PetscErrorCode PETSCKSP_DLLEXPORT PCICCSetFill(PC pc,PetscReal fill)
196: {
197:   PetscErrorCode ierr,(*f)(PC,PetscReal);

201:   if (fill < 1.0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Fill factor cannot be less than 1.0");
202:   PetscObjectQueryFunction((PetscObject)pc,"PCICCSetFill_C",(void (**)(void))&f);
203:   if (f) {
204:     (*f)(pc,fill);
205:   }
206:   return(0);
207: }

211: static PetscErrorCode PCSetup_ICC(PC pc)
212: {
213:   PC_ICC         *icc = (PC_ICC*)pc->data;
214:   IS             perm,cperm;

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

220:   if (!pc->setupcalled) {
221:     MatICCFactorSymbolic(pc->pmat,perm,&icc->info,&icc->fact);
222:   } else if (pc->flag != SAME_NONZERO_PATTERN) {
223:     MatDestroy(icc->fact);
224:     MatICCFactorSymbolic(pc->pmat,perm,&icc->info,&icc->fact);
225:   }
226:   ISDestroy(cperm);
227:   ISDestroy(perm);
228:   MatCholeskyFactorNumeric(pc->pmat,&icc->info,&icc->fact);
229:   return(0);
230: }

234: static PetscErrorCode PCDestroy_ICC(PC pc)
235: {
236:   PC_ICC         *icc = (PC_ICC*)pc->data;

240:   if (icc->fact) {MatDestroy(icc->fact);}
241:   PetscStrfree(icc->ordering);
242:   PetscFree(icc);
243:   return(0);
244: }

248: static PetscErrorCode PCApply_ICC(PC pc,Vec x,Vec y)
249: {
250:   PC_ICC         *icc = (PC_ICC*)pc->data;

254:   MatSolve(icc->fact,x,y);
255:   return(0);
256: }

260: static PetscErrorCode PCApplySymmetricLeft_ICC(PC pc,Vec x,Vec y)
261: {
263:   PC_ICC         *icc = (PC_ICC*)pc->data;

266:   MatForwardSolve(icc->fact,x,y);
267:   return(0);
268: }

272: static PetscErrorCode PCApplySymmetricRight_ICC(PC pc,Vec x,Vec y)
273: {
275:   PC_ICC         *icc = (PC_ICC*)pc->data;

278:   MatBackwardSolve(icc->fact,x,y);
279:   return(0);
280: }

284: static PetscErrorCode PCGetFactoredMatrix_ICC(PC pc,Mat *mat)
285: {
286:   PC_ICC *icc = (PC_ICC*)pc->data;

289:   *mat = icc->fact;
290:   return(0);
291: }

295: static PetscErrorCode PCSetFromOptions_ICC(PC pc)
296: {
297:   PC_ICC         *icc = (PC_ICC*)pc->data;
298:   char           tname[256];
299:   PetscTruth     flg;
301:   PetscFList     ordlist;

304:   MatOrderingRegisterAll(PETSC_NULL);
305:   PetscOptionsHead("ICC Options");
306:     PetscOptionsReal("-pc_icc_levels","levels of fill","PCICCSetLevels",icc->info.levels,&icc->info.levels,&flg);
307:     PetscOptionsReal("-pc_icc_fill","Expected fill in factorization","PCICCSetFill",icc->info.fill,&icc->info.fill,&flg);
308:     MatGetOrderingList(&ordlist);
309:     PetscOptionsList("-pc_icc_mat_ordering_type","Reorder to reduce nonzeros in ICC","PCICCSetMatOrdering",ordlist,icc->ordering,tname,256,&flg);
310:     if (flg) {
311:       PCICCSetMatOrdering(pc,tname);
312:     }
313:     PetscOptionsName("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",&flg);
314:     if (flg) {
315:       PCFactorSetShiftNonzero(pc,(PetscReal)PETSC_DECIDE);
316:     }
317:     PetscOptionsReal("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",icc->info.shiftnz,&icc->info.shiftnz,0);
318:     PetscOptionsName("-pc_factor_shift_positive_definite","Manteuffel shift applied to diagonal","PCICCSetShift",&flg);
319:     if (flg) {
320:       PCFactorSetShiftPd(pc,PETSC_TRUE);
321:     } else {
322:       PCFactorSetShiftPd(pc,PETSC_FALSE);
323:     }
324:     PetscOptionsReal("-pc_factor_zeropivot","Pivot is considered zero if less than","PCFactorSetZeroPivot",icc->info.zeropivot,&icc->info.zeropivot,0);
325: 
326:   PetscOptionsTail();
327:   return(0);
328: }

332: static PetscErrorCode PCView_ICC(PC pc,PetscViewer viewer)
333: {
334:   PC_ICC         *icc = (PC_ICC*)pc->data;
336:   PetscTruth     isstring,iascii;

339:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
340:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
341:   if (iascii) {
342:     if (icc->info.levels == 1) {
343:         PetscViewerASCIIPrintf(viewer,"  ICC: %D level of fill\n",(PetscInt)icc->info.levels);
344:     } else {
345:         PetscViewerASCIIPrintf(viewer,"  ICC: %D levels of fill\n",(PetscInt)icc->info.levels);
346:     }
347:     PetscViewerASCIIPrintf(viewer,"  ICC: max fill ratio allocated %g\n",icc->info.fill);
348:     if (icc->info.shiftpd) {PetscViewerASCIIPrintf(viewer,"  ICC: using Manteuffel shift\n");}
349:   } else if (isstring) {
350:     PetscViewerStringSPrintf(viewer," lvls=%D",(PetscInt)icc->info.levels);
351:   } else {
352:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCICC",((PetscObject)viewer)->type_name);
353:   }
354:   return(0);
355: }

357: /*MC
358:      PCICC - Incomplete Cholesky factorization preconditioners.

360:    Options Database Keys:
361: +  -pc_icc_levels <k> - number of levels of fill for ICC(k)
362: .  -pc_icc_in_place - only for ICC(0) with natural ordering, reuses the space of the matrix for
363:                       its factorization (overwrites original matrix)
364: .  -pc_icc_fill <nfill> - expected amount of fill in factored matrix compared to original matrix, nfill > 1
365: .  -pc_icc_mat_ordering_type <natural,nd,1wd,rcm,qmd> - set the row/column ordering of the factored matrix
366: .  -pc_factor_shift_nonzero <shift> - Sets shift amount or PETSC_DECIDE for the default
367: -  -pc_factor_shift_positive_definite [PETSC_TRUE/PETSC_FALSE] - Activate/Deactivate PCFactorSetShiftPd(); the value
368:    is optional with PETSC_TRUE being the default

370:    Level: beginner

372:   Concepts: incomplete Cholesky factorization

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

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

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

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


384: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCSOR, MatOrderingType,
385:            PCFactorSetZeroPivot(), PCFactorSetShiftNonzero(), PCFactorSetShiftPd(), 
386:            PCICCSetFill(), PCICCSetMatOrdering(), PCICCSetReuseOrdering(), 
387:            PCICCSetLevels(),PCFactorSetShiftNonzero(),PCFactorSetShiftPd(),

389: M*/

394: PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_ICC(PC pc)
395: {
397:   PC_ICC         *icc;

400:   PetscNew(PC_ICC,&icc);
401:   PetscLogObjectMemory(pc,sizeof(PC_ICC));

403:   icc->fact                  = 0;
404:   PetscStrallocpy(MATORDERING_NATURAL,&icc->ordering);
405:   MatFactorInfoInitialize(&icc->info);
406:   icc->info.levels          = 0;
407:   icc->info.fill          = 1.0;
408:   icc->implctx            = 0;

410:   icc->info.dtcol              = PETSC_DEFAULT;
411:   icc->info.shiftnz            = 0.0;
412:   icc->info.shiftpd            = PETSC_TRUE;
413:   icc->info.shift_fraction     = 0.0;
414:   icc->info.zeropivot          = 1.e-12;
415:   pc->data                       = (void*)icc;

417:   pc->ops->apply               = PCApply_ICC;
418:   pc->ops->setup               = PCSetup_ICC;
419:   pc->ops->destroy               = PCDestroy_ICC;
420:   pc->ops->setfromoptions      = PCSetFromOptions_ICC;
421:   pc->ops->view                = PCView_ICC;
422:   pc->ops->getfactoredmatrix   = PCGetFactoredMatrix_ICC;
423:   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_ICC;
424:   pc->ops->applysymmetricright = PCApplySymmetricRight_ICC;

426:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_ICC",
427:                     PCFactorSetZeroPivot_ICC);
428:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftNonzero_C","PCFactorSetShiftNonzero_ICC",
429:                     PCFactorSetShiftNonzero_ICC);
430:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftPd_C","PCFactorSetShiftPd_ICC",
431:                     PCFactorSetShiftPd_ICC);

433:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetLevels_C","PCICCSetLevels_ICC",
434:                     PCICCSetLevels_ICC);
435:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetFill_C","PCICCSetFill_ICC",
436:                     PCICCSetFill_ICC);
437:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetMatOrdering_C","PCICCSetMatOrdering_ICC",
438:                     PCICCSetMatOrdering_ICC);
439:   return(0);
440: }