Actual source code: cholesky.c
2: /*
3: Defines a direct factorization preconditioner for any Mat implementation
4: Note: this need not be consided a preconditioner since it supplies
5: a direct solver.
6: */
7: #include <../src/ksp/pc/impls/factor/factor.h> /*I "petscpc.h" I*/
9: typedef struct {
10: PC_Factor hdr;
11: PetscReal actualfill; /* actual fill in factor */
12: PetscBool inplace; /* flag indicating in-place factorization */
13: IS row,col; /* index sets used for reordering */
14: PetscBool reuseordering; /* reuses previous reordering computed */
15: PetscBool reusefill; /* reuse fill from previous Cholesky */
16: } PC_Cholesky;
21: PetscErrorCode PCFactorSetReuseOrdering_Cholesky(PC pc,PetscBool flag)
22: {
23: PC_Cholesky *lu;
24:
26: lu = (PC_Cholesky*)pc->data;
27: lu->reuseordering = flag;
28: return(0);
29: }
35: PetscErrorCode PCFactorSetReuseFill_Cholesky(PC pc,PetscBool flag)
36: {
37: PC_Cholesky *lu;
38:
40: lu = (PC_Cholesky*)pc->data;
41: lu->reusefill = flag;
42: return(0);
43: }
48: static PetscErrorCode PCSetFromOptions_Cholesky(PC pc)
49: {
51:
53: PetscOptionsHead("Cholesky options");
54: PCSetFromOptions_Factor(pc);
55: PetscOptionsTail();
56: return(0);
57: }
61: static PetscErrorCode PCView_Cholesky(PC pc,PetscViewer viewer)
62: {
63: PC_Cholesky *chol = (PC_Cholesky*)pc->data;
65: PetscBool iascii;
66:
68: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
69: if (iascii) {
70: if (chol->inplace) {
71: PetscViewerASCIIPrintf(viewer," Cholesky: in-place factorization\n");
72: } else {
73: PetscViewerASCIIPrintf(viewer," Cholesky: out-of-place factorization\n");
74: }
75:
76: if (chol->reusefill) {PetscViewerASCIIPrintf(viewer," Reusing fill from past factorization\n");}
77: if (chol->reuseordering) {PetscViewerASCIIPrintf(viewer," Reusing reordering from past factorization\n");}
78: }
79: PCView_Factor(pc,viewer);
80: return(0);
81: }
86: static PetscErrorCode PCSetUp_Cholesky(PC pc)
87: {
89: PetscBool flg;
90: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
93: if (dir->reusefill && pc->setupcalled) ((PC_Factor*)dir)->info.fill = dir->actualfill;
94:
95: if (dir->inplace) {
96: if (dir->row && dir->col && (dir->row != dir->col)) {
97: ISDestroy(&dir->row);
98: }
99: ISDestroy(&dir->col);
100: MatGetOrdering(pc->pmat,((PC_Factor*)dir)->ordering,&dir->row,&dir->col);
101: if (dir->col && (dir->row != dir->col)) { /* only use row ordering for SBAIJ */
102: ISDestroy(&dir->col);
103: }
104: if (dir->row) {PetscLogObjectParent(pc,dir->row);}
105: MatCholeskyFactor(pc->pmat,dir->row,&((PC_Factor*)dir)->info);
106: ((PC_Factor*)dir)->fact = pc->pmat;
107: } else {
108: MatInfo info;
109: if (!pc->setupcalled) {
110: MatGetOrdering(pc->pmat,((PC_Factor*)dir)->ordering,&dir->row,&dir->col);
111: /* check if dir->row == dir->col */
112: ISEqual(dir->row,dir->col,&flg);
113: if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"row and column permutations must equal");
114: ISDestroy(&dir->col); /* only pass one ordering into CholeskyFactor */
116: flg = PETSC_FALSE;
117: PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_factor_nonzeros_along_diagonal",&flg,PETSC_NULL);
118: if (flg) {
119: PetscReal tol = 1.e-10;
120: PetscOptionsGetReal(((PetscObject)pc)->prefix,"-pc_factor_nonzeros_along_diagonal",&tol,PETSC_NULL);
121: MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);
122: }
123: if (dir->row) {PetscLogObjectParent(pc,dir->row);}
124: if (!((PC_Factor*)dir)->fact){
125: MatGetFactor(pc->pmat,((PC_Factor*)dir)->solvertype,MAT_FACTOR_CHOLESKY,&((PC_Factor*)dir)->fact);
126: }
127: MatCholeskyFactorSymbolic(((PC_Factor*)dir)->fact,pc->pmat,dir->row,&((PC_Factor*)dir)->info);
128: MatGetInfo(((PC_Factor*)dir)->fact,MAT_LOCAL,&info);
129: dir->actualfill = info.fill_ratio_needed;
130: PetscLogObjectParent(pc,((PC_Factor*)dir)->fact);
131: } else if (pc->flag != SAME_NONZERO_PATTERN) {
132: if (!dir->reuseordering) {
133: if (dir->row && dir->col && (dir->row != dir->col)) {
134: ISDestroy(&dir->row);
135: }
136: ISDestroy(&dir->col);
137: MatGetOrdering(pc->pmat,((PC_Factor*)dir)->ordering,&dir->row,&dir->col);
138: if (dir->col && (dir->row != dir->col)) { /* only use row ordering for SBAIJ */
139: ISDestroy(&dir->col);
140: }
141: flg = PETSC_FALSE;
142: PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_factor_nonzeros_along_diagonal",&flg,PETSC_NULL);
143: if (flg) {
144: PetscReal tol = 1.e-10;
145: PetscOptionsGetReal(((PetscObject)pc)->prefix,"-pc_factor_nonzeros_along_diagonal",&tol,PETSC_NULL);
146: MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);
147: }
148: if (dir->row) {PetscLogObjectParent(pc,dir->row);}
149: }
150: MatDestroy(&((PC_Factor*)dir)->fact);
151: MatGetFactor(pc->pmat,((PC_Factor*)dir)->solvertype,MAT_FACTOR_CHOLESKY,&((PC_Factor*)dir)->fact);
152: MatCholeskyFactorSymbolic(((PC_Factor*)dir)->fact,pc->pmat,dir->row,&((PC_Factor*)dir)->info);
153: MatGetInfo(((PC_Factor*)dir)->fact,MAT_LOCAL,&info);
154: dir->actualfill = info.fill_ratio_needed;
155: PetscLogObjectParent(pc,((PC_Factor*)dir)->fact);
156: }
157: MatCholeskyFactorNumeric(((PC_Factor*)dir)->fact,pc->pmat,&((PC_Factor*)dir)->info);
158: }
159: return(0);
160: }
164: static PetscErrorCode PCReset_Cholesky(PC pc)
165: {
166: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
170: if (!dir->inplace && ((PC_Factor*)dir)->fact) {MatDestroy(&((PC_Factor*)dir)->fact);}
171: ISDestroy(&dir->row);
172: ISDestroy(&dir->col);
173: return(0);
174: }
178: static PetscErrorCode PCDestroy_Cholesky(PC pc)
179: {
180: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
184: PCReset_Cholesky(pc);
185: PetscFree(((PC_Factor*)dir)->ordering);
186: PetscFree(((PC_Factor*)dir)->solvertype);
187: PetscFree(pc->data);
188: return(0);
189: }
193: static PetscErrorCode PCApply_Cholesky(PC pc,Vec x,Vec y)
194: {
195: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
197:
199: if (dir->inplace) {MatSolve(pc->pmat,x,y);}
200: else {MatSolve(((PC_Factor*)dir)->fact,x,y);}
201: return(0);
202: }
206: static PetscErrorCode PCApplyTranspose_Cholesky(PC pc,Vec x,Vec y)
207: {
208: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
212: if (dir->inplace) {MatSolveTranspose(pc->pmat,x,y);}
213: else {MatSolveTranspose(((PC_Factor*)dir)->fact,x,y);}
214: return(0);
215: }
217: /* -----------------------------------------------------------------------------------*/
222: PetscErrorCode PCFactorSetUseInPlace_Cholesky(PC pc)
223: {
224: PC_Cholesky *dir;
227: dir = (PC_Cholesky*)pc->data;
228: dir->inplace = PETSC_TRUE;
229: return(0);
230: }
233: /* -----------------------------------------------------------------------------------*/
237: /*@
238: PCFactorSetReuseOrdering - When similar matrices are factored, this
239: causes the ordering computed in the first factor to be used for all
240: following factors.
242: Logically Collective on PC
244: Input Parameters:
245: + pc - the preconditioner context
246: - flag - PETSC_TRUE to reuse else PETSC_FALSE
248: Options Database Key:
249: . -pc_factor_reuse_ordering - Activate PCFactorSetReuseOrdering()
251: Level: intermediate
253: .keywords: PC, levels, reordering, factorization, incomplete, LU
255: .seealso: PCFactorSetReuseFill()
256: @*/
257: PetscErrorCode PCFactorSetReuseOrdering(PC pc,PetscBool flag)
258: {
264: PetscTryMethod(pc,"PCFactorSetReuseOrdering_C",(PC,PetscBool),(pc,flag));
265: return(0);
266: }
269: /*MC
270: PCCHOLESKY - Uses a direct solver, based on Cholesky factorization, as a preconditioner
272: Options Database Keys:
273: + -pc_factor_reuse_ordering - Activate PCFactorSetReuseOrdering()
274: . -pc_factor_mat_solver_package - Actives PCFactorSetMatSolverPackage() to choose the direct solver, like spooles
275: . -pc_factor_reuse_fill - Activates PCFactorSetReuseFill()
276: . -pc_factor_fill <fill> - Sets fill amount
277: . -pc_factor_in_place - Activates in-place factorization
278: - -pc_factor_mat_ordering_type <nd,rcm,...> - Sets ordering routine
280: Notes: Not all options work for all matrix formats
282: Level: beginner
284: Concepts: Cholesky factorization, direct solver
286: Notes: Usually this will compute an "exact" solution in one iteration and does
287: not need a Krylov method (i.e. you can use -ksp_type preonly, or
288: KSPSetType(ksp,KSPPREONLY) for the Krylov method
290: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC,
291: PCILU, PCLU, PCICC, PCFactorSetReuseOrdering(), PCFactorSetReuseFill(), PCFactorGetMatrix(),
292: PCFactorSetFill(), PCFactorSetShiftNonzero(), PCFactorSetShiftType(), PCFactorSetShiftAmount()
293: PCFactorSetUseInPlace(), PCFactorSetMatOrderingType()
295: M*/
300: PetscErrorCode PCCreate_Cholesky(PC pc)
301: {
303: PC_Cholesky *dir;
306: PetscNewLog(pc,PC_Cholesky,&dir);
308: ((PC_Factor*)dir)->fact = 0;
309: dir->inplace = PETSC_FALSE;
310: MatFactorInfoInitialize(&((PC_Factor*)dir)->info);
311: ((PC_Factor*)dir)->factortype = MAT_FACTOR_CHOLESKY;
312: ((PC_Factor*)dir)->info.fill = 5.0;
313: ((PC_Factor*)dir)->info.shifttype = (PetscReal) MAT_SHIFT_NONE;
314: ((PC_Factor*)dir)->info.shiftamount = 0.0;
315: ((PC_Factor*)dir)->info.zeropivot = 100.0*PETSC_MACHINE_EPSILON;
316: ((PC_Factor*)dir)->info.pivotinblocks = 1.0;
317: dir->col = 0;
318: dir->row = 0;
319: PetscStrallocpy(MATORDERINGNATURAL,&((PC_Factor*)dir)->ordering);
320: PetscStrallocpy(MATSOLVERPETSC,&((PC_Factor*)dir)->solvertype);
321: dir->reusefill = PETSC_FALSE;
322: dir->reuseordering = PETSC_FALSE;
323: pc->data = (void*)dir;
325: pc->ops->destroy = PCDestroy_Cholesky;
326: pc->ops->reset = PCReset_Cholesky;
327: pc->ops->apply = PCApply_Cholesky;
328: pc->ops->applytranspose = PCApplyTranspose_Cholesky;
329: pc->ops->setup = PCSetUp_Cholesky;
330: pc->ops->setfromoptions = PCSetFromOptions_Cholesky;
331: pc->ops->view = PCView_Cholesky;
332: pc->ops->applyrichardson = 0;
333: pc->ops->getfactoredmatrix = PCFactorGetMatrix_Factor;
335: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetUpMatSolverPackage_C","PCFactorSetUpMatSolverPackage_Factor",
336: PCFactorSetUpMatSolverPackage_Factor);
337: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetMatSolverPackage_C","PCFactorSetMatSolverPackage_Factor",
338: PCFactorSetMatSolverPackage_Factor);
339: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorGetMatSolverPackage_C","PCFactorGetMatSolverPackage_Factor",
340: PCFactorGetMatSolverPackage_Factor);
341: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_Factor",
342: PCFactorSetZeroPivot_Factor);
343: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftType_C","PCFactorSetShiftType_Factor",
344: PCFactorSetShiftType_Factor);
345: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftAmount_C","PCFactorSetShiftAmount_Factor",
346: PCFactorSetShiftAmount_Factor);
347: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetFill_C","PCFactorSetFill_Factor",
348: PCFactorSetFill_Factor);
349: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetUseInPlace_C","PCFactorSetUseInPlace_Cholesky",
350: PCFactorSetUseInPlace_Cholesky);
351: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetMatOrderingType_C","PCFactorSetMatOrderingType_Factor",
352: PCFactorSetMatOrderingType_Factor);
353: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetReuseOrdering_C","PCFactorSetReuseOrdering_Cholesky",
354: PCFactorSetReuseOrdering_Cholesky);
355: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetReuseFill_C","PCFactorSetReuseFill_Cholesky",
356: PCFactorSetReuseFill_Cholesky);
357: return(0);
358: }