xref: /petsc/src/ksp/pc/impls/factor/icc/icc.c (revision 3f32ffd6a1a2c74a8ac459f93ac54c5d1eec7f6c)
1 #define PETSCKSP_DLL
2 
3 #include "src/ksp/pc/impls/factor/icc/icc.h"   /*I "petscpc.h" I*/
4 
5 EXTERN_C_BEGIN
6 #undef __FUNCT__
7 #define __FUNCT__ "PCFactorSetZeroPivot_ICC"
8 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetZeroPivot_ICC(PC pc,PetscReal z)
9 {
10   PC_ICC *icc  = (PC_ICC*)pc->data;
11 
12   PetscFunctionBegin;
13   ((PC_Factor*)icc)->info.zeropivot = z;
14   PetscFunctionReturn(0);
15 }
16 EXTERN_C_END
17 
18 EXTERN_C_BEGIN
19 #undef __FUNCT__
20 #define __FUNCT__ "PCFactorSetShiftNonzero_ICC"
21 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftNonzero_ICC(PC pc,PetscReal shift)
22 {
23   PC_ICC *dir  = (PC_ICC*)pc->data;
24 
25   PetscFunctionBegin;
26   if (shift == (PetscReal) PETSC_DECIDE) {
27      ((PC_Factor*)dir)->info.shiftnz = 1.e-12;
28   } else {
29      ((PC_Factor*)dir)->info.shiftnz = shift;
30   }
31   PetscFunctionReturn(0);
32 }
33 EXTERN_C_END
34 
35 EXTERN_C_BEGIN
36 #undef __FUNCT__
37 #define __FUNCT__ "PCFactorSetShiftPd_ICC"
38 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftPd_ICC(PC pc,PetscTruth shift)
39 {
40   PC_ICC *dir = (PC_ICC*)pc->data;
41 
42   PetscFunctionBegin;
43   if (shift) {
44      ((PC_Factor*)dir)->info.shiftpd = 1.0;
45   } else {
46      ((PC_Factor*)dir)->info.shiftpd = 0.0;
47   }
48   PetscFunctionReturn(0);
49 }
50 EXTERN_C_END
51 
52 EXTERN_C_BEGIN
53 #undef __FUNCT__
54 #define __FUNCT__ "PCFactorSetMatOrderingType_ICC"
55 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetMatOrderingType_ICC(PC pc,const MatOrderingType ordering)
56 {
57   PC_ICC         *dir = (PC_ICC*)pc->data;
58   PetscErrorCode ierr;
59 
60   PetscFunctionBegin;
61   ierr = PetscStrfree(((PC_Factor*)dir)->ordering);CHKERRQ(ierr);
62   ierr = PetscStrallocpy(ordering,& ((PC_Factor*)dir)->ordering);CHKERRQ(ierr);
63   PetscFunctionReturn(0);
64 }
65 EXTERN_C_END
66 
67 EXTERN_C_BEGIN
68 #undef __FUNCT__
69 #define __FUNCT__ "PCFactorSetFill_ICC"
70 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetFill_ICC(PC pc,PetscReal fill)
71 {
72   PC_ICC *dir = (PC_ICC*)pc->data;
73 
74   PetscFunctionBegin;
75   ((PC_Factor*)dir)->info.fill = fill;
76   PetscFunctionReturn(0);
77 }
78 EXTERN_C_END
79 
80 EXTERN_C_BEGIN
81 #undef __FUNCT__
82 #define __FUNCT__ "PCFactorSetLevels_ICC"
83 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetLevels_ICC(PC pc,PetscInt levels)
84 {
85   PC_ICC *icc = (PC_ICC*)pc->data;
86 
87   PetscFunctionBegin;
88    ((PC_Factor*)icc)->info.levels = levels;
89   PetscFunctionReturn(0);
90 }
91 EXTERN_C_END
92 
93 #undef __FUNCT__
94 #define __FUNCT__ "PCSetup_ICC"
95 static PetscErrorCode PCSetup_ICC(PC pc)
96 {
97   PC_ICC         *icc = (PC_ICC*)pc->data;
98   IS             perm,cperm;
99   PetscErrorCode ierr;
100   MatInfo        info;
101 
102   PetscFunctionBegin;
103   ierr = MatGetOrdering(pc->pmat, ((PC_Factor*)icc)->ordering,&perm,&cperm);CHKERRQ(ierr);
104 
105   if (!pc->setupcalled) {
106     ierr = MatGetFactor(pc->pmat,MAT_SOLVER_PETSC,MAT_FACTOR_ICC,& ((PC_Factor*)icc)->fact);CHKERRQ(ierr);
107     ierr = MatICCFactorSymbolic(((PC_Factor*)icc)->fact,pc->pmat,perm,&((PC_Factor*)icc)->info);CHKERRQ(ierr);
108   } else if (pc->flag != SAME_NONZERO_PATTERN) {
109     ierr = MatDestroy(((PC_Factor*)icc)->fact);CHKERRQ(ierr);
110     ierr = MatGetFactor(pc->pmat,MAT_SOLVER_PETSC,MAT_FACTOR_ICC,&((PC_Factor*)icc)->fact);CHKERRQ(ierr);
111     ierr = MatICCFactorSymbolic(((PC_Factor*)icc)->fact,pc->pmat,perm,&((PC_Factor*)icc)->info);CHKERRQ(ierr);
112   }
113   ierr = MatGetInfo(((PC_Factor*)icc)->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
114   icc->actualfill = info.fill_ratio_needed;
115 
116   ierr = ISDestroy(cperm);CHKERRQ(ierr);
117   ierr = ISDestroy(perm);CHKERRQ(ierr);
118   ierr = MatCholeskyFactorNumeric(((PC_Factor*)icc)->fact,pc->pmat,&((PC_Factor*)icc)->info);CHKERRQ(ierr);
119   PetscFunctionReturn(0);
120 }
121 
122 #undef __FUNCT__
123 #define __FUNCT__ "PCDestroy_ICC"
124 static PetscErrorCode PCDestroy_ICC(PC pc)
125 {
126   PC_ICC         *icc = (PC_ICC*)pc->data;
127   PetscErrorCode ierr;
128 
129   PetscFunctionBegin;
130   if (((PC_Factor*)icc)->fact) {ierr = MatDestroy(((PC_Factor*)icc)->fact);CHKERRQ(ierr);}
131   ierr = PetscStrfree(((PC_Factor*)icc)->ordering);CHKERRQ(ierr);
132   ierr = PetscFree(icc);CHKERRQ(ierr);
133   PetscFunctionReturn(0);
134 }
135 
136 #undef __FUNCT__
137 #define __FUNCT__ "PCApply_ICC"
138 static PetscErrorCode PCApply_ICC(PC pc,Vec x,Vec y)
139 {
140   PC_ICC         *icc = (PC_ICC*)pc->data;
141   PetscErrorCode ierr;
142 
143   PetscFunctionBegin;
144   ierr = MatSolve(((PC_Factor*)icc)->fact,x,y);CHKERRQ(ierr);
145   PetscFunctionReturn(0);
146 }
147 
148 #undef __FUNCT__
149 #define __FUNCT__ "PCApplySymmetricLeft_ICC"
150 static PetscErrorCode PCApplySymmetricLeft_ICC(PC pc,Vec x,Vec y)
151 {
152   PetscErrorCode ierr;
153   PC_ICC         *icc = (PC_ICC*)pc->data;
154 
155   PetscFunctionBegin;
156   ierr = MatForwardSolve(((PC_Factor*)icc)->fact,x,y);CHKERRQ(ierr);
157   PetscFunctionReturn(0);
158 }
159 
160 #undef __FUNCT__
161 #define __FUNCT__ "PCApplySymmetricRight_ICC"
162 static PetscErrorCode PCApplySymmetricRight_ICC(PC pc,Vec x,Vec y)
163 {
164   PetscErrorCode ierr;
165   PC_ICC         *icc = (PC_ICC*)pc->data;
166 
167   PetscFunctionBegin;
168   ierr = MatBackwardSolve(((PC_Factor*)icc)->fact,x,y);CHKERRQ(ierr);
169   PetscFunctionReturn(0);
170 }
171 
172 #undef __FUNCT__
173 #define __FUNCT__ "PCFactorGetMatrix_ICC"
174 static PetscErrorCode PCFactorGetMatrix_ICC(PC pc,Mat *mat)
175 {
176   PC_ICC *icc = (PC_ICC*)pc->data;
177 
178   PetscFunctionBegin;
179   *mat = ((PC_Factor*)icc)->fact;
180   PetscFunctionReturn(0);
181 }
182 
183 #undef __FUNCT__
184 #define __FUNCT__ "PCSetFromOptions_ICC"
185 static PetscErrorCode PCSetFromOptions_ICC(PC pc)
186 {
187   PC_ICC         *icc = (PC_ICC*)pc->data;
188   char           tname[256];
189   PetscTruth     flg;
190   PetscErrorCode ierr;
191   PetscFList     ordlist;
192 
193   PetscFunctionBegin;
194   ierr = MatOrderingRegisterAll(PETSC_NULL);CHKERRQ(ierr);
195   ierr = PetscOptionsHead("ICC Options");CHKERRQ(ierr);
196     ierr = PetscOptionsReal("-pc_factor_levels","levels of fill","PCFactorSetLevels",((PC_Factor*)icc)->info.levels,&((PC_Factor*)icc)->info.levels,&flg);CHKERRQ(ierr);
197     ierr = PetscOptionsReal("-pc_factor_fill","Expected fill in factorization","PCFactorSetFill",((PC_Factor*)icc)->info.fill,&((PC_Factor*)icc)->info.fill,&flg);CHKERRQ(ierr);
198     ierr = MatGetOrderingList(&ordlist);CHKERRQ(ierr);
199     ierr = PetscOptionsList("-pc_factor_mat_ordering_type","Reorder to reduce nonzeros in ICC","PCFactorSetMatOrderingType",ordlist,((PC_Factor*)icc)->ordering,tname,256,&flg);CHKERRQ(ierr);
200     if (flg) {
201       ierr = PCFactorSetMatOrderingType(pc,tname);CHKERRQ(ierr);
202     }
203     ierr = PetscOptionsName("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",&flg);CHKERRQ(ierr);
204     if (flg) {
205       ierr = PCFactorSetShiftNonzero(pc,(PetscReal)PETSC_DECIDE);CHKERRQ(ierr);
206     }
207     ierr = PetscOptionsReal("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",((PC_Factor*)icc)->info.shiftnz,&((PC_Factor*)icc)->info.shiftnz,0);CHKERRQ(ierr);
208     flg = (((PC_Factor*)icc)->info.shiftpd > 0.0) ? PETSC_TRUE : PETSC_FALSE;
209     ierr = PetscOptionsTruth("-pc_factor_shift_positive_definite","Manteuffel shift applied to diagonal","PCFactorSetShiftPd",flg,&flg,PETSC_NULL);CHKERRQ(ierr);
210     ierr = PCFactorSetShiftPd(pc,flg);CHKERRQ(ierr);
211     ierr = PetscOptionsReal("-pc_factor_zeropivot","Pivot is considered zero if less than","PCFactorSetZeroPivot",((PC_Factor*)icc)->info.zeropivot,&((PC_Factor*)icc)->info.zeropivot,0);CHKERRQ(ierr);
212 
213   ierr = PetscOptionsTail();CHKERRQ(ierr);
214   PetscFunctionReturn(0);
215 }
216 
217 #undef __FUNCT__
218 #define __FUNCT__ "PCView_ICC"
219 static PetscErrorCode PCView_ICC(PC pc,PetscViewer viewer)
220 {
221   PC_ICC         *icc = (PC_ICC*)pc->data;
222   PetscErrorCode ierr;
223   PetscTruth     isstring,iascii;
224 
225   PetscFunctionBegin;
226   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr);
227   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
228   if (iascii) {
229     if (((PC_Factor*)icc)->info.levels == 1) {
230         ierr = PetscViewerASCIIPrintf(viewer,"  ICC: %D level of fill\n",(PetscInt)((PC_Factor*)icc)->info.levels);CHKERRQ(ierr);
231     } else {
232         ierr = PetscViewerASCIIPrintf(viewer,"  ICC: %D levels of fill\n",(PetscInt)((PC_Factor*)icc)->info.levels);CHKERRQ(ierr);
233     }
234     ierr = PetscViewerASCIIPrintf(viewer,"  ICC: factor fill ratio allocated %G, ordering used %s\n",((PC_Factor*)icc)->info.fill,((PC_Factor*)icc)->ordering);CHKERRQ(ierr);
235     if (((PC_Factor*)icc)->info.shiftpd) {ierr = PetscViewerASCIIPrintf(viewer,"  ICC: using Manteuffel shift\n");CHKERRQ(ierr);}
236     if (((PC_Factor*)icc)->info.shiftnz) {ierr = PetscViewerASCIIPrintf(viewer,"  ICC: using diagonal shift to prevent zero pivot\n");CHKERRQ(ierr);}
237     if (((PC_Factor*)icc)->fact) {
238       ierr = PetscViewerASCIIPrintf(viewer,"  ICC: factor fill ratio needed %G\n",icc->actualfill);CHKERRQ(ierr);
239       ierr = PetscViewerASCIIPrintf(viewer,"       Factored matrix follows\n");CHKERRQ(ierr);
240       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
241       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
242       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
243       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
244       ierr = MatView(((PC_Factor*)icc)->fact,viewer);CHKERRQ(ierr);
245       ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
246       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
247       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
248       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
249     }
250   } else if (isstring) {
251     ierr = PetscViewerStringSPrintf(viewer," lvls=%D",(PetscInt)((PC_Factor*)icc)->info.levels);CHKERRQ(ierr);CHKERRQ(ierr);
252   } else {
253     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCICC",((PetscObject)viewer)->type_name);
254   }
255   PetscFunctionReturn(0);
256 }
257 
258 /*MC
259      PCICC - Incomplete Cholesky factorization preconditioners.
260 
261    Options Database Keys:
262 +  -pc_factor_levels <k> - number of levels of fill for ICC(k)
263 .  -pc_factor_in_place - only for ICC(0) with natural ordering, reuses the space of the matrix for
264                       its factorization (overwrites original matrix)
265 .  -pc_factor_fill <nfill> - expected amount of fill in factored matrix compared to original matrix, nfill > 1
266 .  -pc_factor_mat_ordering_type <natural,nd,1wd,rcm,qmd> - set the row/column ordering of the factored matrix
267 .  -pc_factor_shift_nonzero <shift> - Sets shift amount or PETSC_DECIDE for the default
268 -  -pc_factor_shift_positive_definite [PETSC_TRUE/PETSC_FALSE] - Activate/Deactivate PCFactorSetShiftPd(); the value
269    is optional with PETSC_TRUE being the default
270 
271    Level: beginner
272 
273   Concepts: incomplete Cholesky factorization
274 
275    Notes: Only implemented for some matrix formats. Not implemented in parallel (for parallel use you
276              must use MATMPIROWBS, see MatCreateMPIRowbs(), this supports only ICC(0) and this is not recommended
277              unless you really want a parallel ICC).
278 
279           For BAIJ matrices this implements a point block ICC.
280 
281           The Manteuffel shift is only implemented for matrices with block size 1
282 
283           By default, the Manteuffel is applied (for matrices with block size 1). Call PCFactorSetShiftPd(pc,PETSC_FALSE);
284           to turn off the shift.
285 
286    References:
287    Review article: APPROXIMATE AND INCOMPLETE FACTORIZATIONS, TONY F. CHAN AND HENK A. VAN DER VORST
288       http://igitur-archive.library.uu.nl/math/2001-0621-115821/proc.pdf chapter in Parallel Numerical
289       Algorithms, edited by D. Keyes, A. Semah, V. Venkatakrishnan, ICASE/LaRC Interdisciplinary Series in
290       Science and Engineering, Kluwer, pp. 167--202.
291 
292 
293 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCSOR, MatOrderingType,
294            PCFactorSetZeroPivot(), PCFactorSetShiftNonzero(), PCFactorSetShiftPd(),
295            PCFactorSetFill(), PCFactorSetMatOrderingType(), PCFactorSetReuseOrdering(),
296            PCFactorSetLevels(),PCFactorSetShiftNonzero(),PCFactorSetShiftPd(),
297 
298 M*/
299 
300 EXTERN_C_BEGIN
301 #undef __FUNCT__
302 #define __FUNCT__ "PCCreate_ICC"
303 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_ICC(PC pc)
304 {
305   PetscErrorCode ierr;
306   PC_ICC         *icc;
307 
308   PetscFunctionBegin;
309   ierr = PetscNewLog(pc,PC_ICC,&icc);CHKERRQ(ierr);
310 
311   ((PC_Factor*)icc)->fact	          = 0;
312   ierr = PetscStrallocpy(MATORDERING_NATURAL,&((PC_Factor*)icc)->ordering);CHKERRQ(ierr);
313   ierr = MatFactorInfoInitialize(&((PC_Factor*)icc)->info);CHKERRQ(ierr);
314   ((PC_Factor*)icc)->info.levels	  = 0;
315   ((PC_Factor*)icc)->info.fill          = 1.0;
316   icc->implctx            = 0;
317 
318   ((PC_Factor*)icc)->info.dtcol              = PETSC_DEFAULT;
319   ((PC_Factor*)icc)->info.shiftnz            = 0.0;
320   ((PC_Factor*)icc)->info.shiftpd            = 1.0; /* true */
321   ((PC_Factor*)icc)->info.zeropivot          = 1.e-12;
322   pc->data	               = (void*)icc;
323 
324   pc->ops->apply	       = PCApply_ICC;
325   pc->ops->setup               = PCSetup_ICC;
326   pc->ops->destroy	       = PCDestroy_ICC;
327   pc->ops->setfromoptions      = PCSetFromOptions_ICC;
328   pc->ops->view                = PCView_ICC;
329   pc->ops->getfactoredmatrix   = PCFactorGetMatrix_ICC;
330   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_ICC;
331   pc->ops->applysymmetricright = PCApplySymmetricRight_ICC;
332 
333   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_ICC",
334                     PCFactorSetZeroPivot_ICC);CHKERRQ(ierr);
335   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftNonzero_C","PCFactorSetShiftNonzero_ICC",
336                     PCFactorSetShiftNonzero_ICC);CHKERRQ(ierr);
337   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftPd_C","PCFactorSetShiftPd_ICC",
338                     PCFactorSetShiftPd_ICC);CHKERRQ(ierr);
339 
340   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetLevels_C","PCFactorSetLevels_ICC",
341                     PCFactorSetLevels_ICC);CHKERRQ(ierr);
342   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetFill_C","PCFactorSetFill_ICC",
343                     PCFactorSetFill_ICC);CHKERRQ(ierr);
344   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetMatOrderingType_C","PCFactorSetMatOrderingType_ICC",
345                     PCFactorSetMatOrderingType_ICC);CHKERRQ(ierr);
346   PetscFunctionReturn(0);
347 }
348 EXTERN_C_END
349 
350 
351