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: }