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:   if (shift) {
 52:     dir->info.shift_fraction = 0.0;
 53:     dir->info.shiftpd = 1.0;
 54:   } else {
 55:     dir->info.shiftpd = 0.0;
 56:   }
 57:   return(0);
 58: }

 64: PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetMatOrdering_ICC(PC pc,MatOrderingType ordering)
 65: {
 66:   PC_ICC         *dir = (PC_ICC*)pc->data;
 68: 
 70:   PetscStrfree(dir->ordering);
 71:   PetscStrallocpy(ordering,&dir->ordering);
 72:   return(0);
 73: }

 79: PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetFill_ICC(PC pc,PetscReal fill)
 80: {
 81:   PC_ICC *dir;

 84:   dir            = (PC_ICC*)pc->data;
 85:   dir->info.fill = fill;
 86:   return(0);
 87: }

 93: PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetLevels_ICC(PC pc,PetscInt levels)
 94: {
 95:   PC_ICC *icc;

 98:   icc = (PC_ICC*)pc->data;
 99:   icc->info.levels = levels;
100:   return(0);
101: }

106: static PetscErrorCode PCSetup_ICC(PC pc)
107: {
108:   PC_ICC         *icc = (PC_ICC*)pc->data;
109:   IS             perm,cperm;

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

115:   if (!pc->setupcalled) {
116:     MatICCFactorSymbolic(pc->pmat,perm,&icc->info,&icc->fact);
117:   } else if (pc->flag != SAME_NONZERO_PATTERN) {
118:     MatDestroy(icc->fact);
119:     MatICCFactorSymbolic(pc->pmat,perm,&icc->info,&icc->fact);
120:   }
121:   ISDestroy(cperm);
122:   ISDestroy(perm);
123:   MatCholeskyFactorNumeric(pc->pmat,&icc->info,&icc->fact);
124:   return(0);
125: }

129: static PetscErrorCode PCDestroy_ICC(PC pc)
130: {
131:   PC_ICC         *icc = (PC_ICC*)pc->data;

135:   if (icc->fact) {MatDestroy(icc->fact);}
136:   PetscStrfree(icc->ordering);
137:   PetscFree(icc);
138:   return(0);
139: }

143: static PetscErrorCode PCApply_ICC(PC pc,Vec x,Vec y)
144: {
145:   PC_ICC         *icc = (PC_ICC*)pc->data;

149:   MatSolve(icc->fact,x,y);
150:   return(0);
151: }

155: static PetscErrorCode PCApplySymmetricLeft_ICC(PC pc,Vec x,Vec y)
156: {
158:   PC_ICC         *icc = (PC_ICC*)pc->data;

161:   MatForwardSolve(icc->fact,x,y);
162:   return(0);
163: }

167: static PetscErrorCode PCApplySymmetricRight_ICC(PC pc,Vec x,Vec y)
168: {
170:   PC_ICC         *icc = (PC_ICC*)pc->data;

173:   MatBackwardSolve(icc->fact,x,y);
174:   return(0);
175: }

179: static PetscErrorCode PCGetFactoredMatrix_ICC(PC pc,Mat *mat)
180: {
181:   PC_ICC *icc = (PC_ICC*)pc->data;

184:   *mat = icc->fact;
185:   return(0);
186: }

190: static PetscErrorCode PCSetFromOptions_ICC(PC pc)
191: {
192:   PC_ICC         *icc = (PC_ICC*)pc->data;
193:   char           tname[256];
194:   PetscTruth     flg;
196:   PetscFList     ordlist;

199:   MatOrderingRegisterAll(PETSC_NULL);
200:   PetscOptionsHead("ICC Options");
201:     PetscOptionsReal("-pc_factor_levels","levels of fill","PCFactorSetLevels",icc->info.levels,&icc->info.levels,&flg);
202:     PetscOptionsReal("-pc_factor_fill","Expected fill in factorization","PCFactorSetFill",icc->info.fill,&icc->info.fill,&flg);
203:     MatGetOrderingList(&ordlist);
204:     PetscOptionsList("-pc_factor_mat_ordering_type","Reorder to reduce nonzeros in ICC","PCFactorSetMatOrdering",ordlist,icc->ordering,tname,256,&flg);
205:     if (flg) {
206:       PCFactorSetMatOrdering(pc,tname);
207:     }
208:     PetscOptionsName("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",&flg);
209:     if (flg) {
210:       PCFactorSetShiftNonzero(pc,(PetscReal)PETSC_DECIDE);
211:     }
212:     PetscOptionsReal("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",icc->info.shiftnz,&icc->info.shiftnz,0);
213:     PetscOptionsName("-pc_factor_shift_positive_definite","Manteuffel shift applied to diagonal","PCFactorSetShift",&flg);
214:     if (flg) {
215:       PCFactorSetShiftPd(pc,PETSC_TRUE);
216:     } else {
217:       PCFactorSetShiftPd(pc,PETSC_FALSE);
218:     }
219:     PetscOptionsReal("-pc_factor_zeropivot","Pivot is considered zero if less than","PCFactorSetZeroPivot",icc->info.zeropivot,&icc->info.zeropivot,0);
220: 
221:   PetscOptionsTail();
222:   return(0);
223: }

227: static PetscErrorCode PCView_ICC(PC pc,PetscViewer viewer)
228: {
229:   PC_ICC         *icc = (PC_ICC*)pc->data;
231:   PetscTruth     isstring,iascii;

234:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
235:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
236:   if (iascii) {
237:     if (icc->info.levels == 1) {
238:         PetscViewerASCIIPrintf(viewer,"  ICC: %D level of fill\n",(PetscInt)icc->info.levels);
239:     } else {
240:         PetscViewerASCIIPrintf(viewer,"  ICC: %D levels of fill\n",(PetscInt)icc->info.levels);
241:     }
242:     PetscViewerASCIIPrintf(viewer,"  ICC: max fill ratio allocated %G\n",icc->info.fill);
243:     if (icc->info.shiftpd) {PetscViewerASCIIPrintf(viewer,"  ICC: using Manteuffel shift\n");}
244:   } else if (isstring) {
245:     PetscViewerStringSPrintf(viewer," lvls=%D",(PetscInt)icc->info.levels);
246:   } else {
247:     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCICC",((PetscObject)viewer)->type_name);
248:   }
249:   return(0);
250: }

252: /*MC
253:      PCICC - Incomplete Cholesky factorization preconditioners.

255:    Options Database Keys:
256: +  -pc_factor_levels <k> - number of levels of fill for ICC(k)
257: .  -pc_factor_in_place - only for ICC(0) with natural ordering, reuses the space of the matrix for
258:                       its factorization (overwrites original matrix)
259: .  -pc_factor_fill <nfill> - expected amount of fill in factored matrix compared to original matrix, nfill > 1
260: .  -pc_factor_mat_ordering_type <natural,nd,1wd,rcm,qmd> - set the row/column ordering of the factored matrix
261: .  -pc_factor_shift_nonzero <shift> - Sets shift amount or PETSC_DECIDE for the default
262: -  -pc_factor_shift_positive_definite [PETSC_TRUE/PETSC_FALSE] - Activate/Deactivate PCFactorSetShiftPd(); the value
263:    is optional with PETSC_TRUE being the default

265:    Level: beginner

267:   Concepts: incomplete Cholesky factorization

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

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

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

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


279: .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCSOR, MatOrderingType,
280:            PCFactorSetZeroPivot(), PCFactorSetShiftNonzero(), PCFactorSetShiftPd(), 
281:            PCFactorSetFill(), PCFactorSetMatOrdering(), PCFactorSetReuseOrdering(), 
282:            PCFactorSetLevels(),PCFactorSetShiftNonzero(),PCFactorSetShiftPd(),

284: M*/

289: PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_ICC(PC pc)
290: {
292:   PC_ICC         *icc;

295:   PetscNew(PC_ICC,&icc);
296:   PetscLogObjectMemory(pc,sizeof(PC_ICC));

298:   icc->fact                  = 0;
299:   PetscStrallocpy(MATORDERING_NATURAL,&icc->ordering);
300:   MatFactorInfoInitialize(&icc->info);
301:   icc->info.levels          = 0;
302:   icc->info.fill          = 1.0;
303:   icc->implctx            = 0;

305:   icc->info.dtcol              = PETSC_DEFAULT;
306:   icc->info.shiftnz            = 0.0;
307:   icc->info.shiftpd            = 1.0; /* true */
308:   icc->info.shift_fraction     = 0.0;
309:   icc->info.zeropivot          = 1.e-12;
310:   pc->data                       = (void*)icc;

312:   pc->ops->apply               = PCApply_ICC;
313:   pc->ops->setup               = PCSetup_ICC;
314:   pc->ops->destroy               = PCDestroy_ICC;
315:   pc->ops->setfromoptions      = PCSetFromOptions_ICC;
316:   pc->ops->view                = PCView_ICC;
317:   pc->ops->getfactoredmatrix   = PCGetFactoredMatrix_ICC;
318:   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_ICC;
319:   pc->ops->applysymmetricright = PCApplySymmetricRight_ICC;

321:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_ICC",
322:                     PCFactorSetZeroPivot_ICC);
323:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftNonzero_C","PCFactorSetShiftNonzero_ICC",
324:                     PCFactorSetShiftNonzero_ICC);
325:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftPd_C","PCFactorSetShiftPd_ICC",
326:                     PCFactorSetShiftPd_ICC);

328:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetLevels_C","PCFactorSetLevels_ICC",
329:                     PCFactorSetLevels_ICC);
330:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetFill_C","PCFactorSetFill_ICC",
331:                     PCFactorSetFill_ICC);
332:   PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetMatOrdering_C","PCFactorSetMatOrdering_ICC",
333:                     PCFactorSetMatOrdering_ICC);
334:   return(0);
335: }