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