xref: /petsc/src/ksp/pc/impls/factor/icc/icc.c (revision ee45ca4afdde1af4d1deda7cd4dc1a4a63a3ea97)
1 /*
2    Defines a Cholesky factorization preconditioner for any Mat implementation.
3   Presently only provided for MPIRowbs format (i.e. BlockSolve).
4 */
5 
6 #include "src/ksp/pc/impls/factor/icc/icc.h"   /*I "petscpc.h" I*/
7 
8 EXTERN_C_BEGIN
9 #undef __FUNCT__
10 #define __FUNCT__ "PCICCSetMatOrdering_ICC"
11 PetscErrorCode PCICCSetMatOrdering_ICC(PC pc,MatOrderingType ordering)
12 {
13   PC_ICC         *dir = (PC_ICC*)pc->data;
14   PetscErrorCode ierr;
15 
16   PetscFunctionBegin;
17   ierr = PetscStrfree(dir->ordering);CHKERRQ(ierr);
18   ierr = PetscStrallocpy(ordering,&dir->ordering);CHKERRQ(ierr);
19   PetscFunctionReturn(0);
20 }
21 EXTERN_C_END
22 
23 EXTERN_C_BEGIN
24 #undef __FUNCT__
25 #define __FUNCT__ "PCICCSetFill_ICC"
26 PetscErrorCode PCICCSetFill_ICC(PC pc,PetscReal fill)
27 {
28   PC_ICC *dir;
29 
30   PetscFunctionBegin;
31   dir            = (PC_ICC*)pc->data;
32   dir->info.fill = fill;
33   PetscFunctionReturn(0);
34 }
35 EXTERN_C_END
36 
37 EXTERN_C_BEGIN
38 #undef __FUNCT__
39 #define __FUNCT__ "PCICCSetLevels_ICC"
40 PetscErrorCode PCICCSetLevels_ICC(PC pc,PetscInt levels)
41 {
42   PC_ICC *icc;
43 
44   PetscFunctionBegin;
45   icc = (PC_ICC*)pc->data;
46   icc->info.levels = levels;
47   PetscFunctionReturn(0);
48 }
49 EXTERN_C_END
50 
51 #undef __FUNCT__
52 #define __FUNCT__ "PCICCSetMatOrdering"
53 /*@
54     PCICCSetMatOrdering - Sets the ordering routine (to reduce fill) to
55     be used it the ICC factorization.
56 
57     Collective on PC
58 
59     Input Parameters:
60 +   pc - the preconditioner context
61 -   ordering - the matrix ordering name, for example, MATORDERING_ND or MATORDERING_RCM
62 
63     Options Database Key:
64 .   -pc_icc_mat_ordering_type <nd,rcm,...> - Sets ordering routine
65 
66     Level: intermediate
67 
68 .seealso: PCLUSetMatOrdering()
69 
70 .keywords: PC, ICC, set, matrix, reordering
71 
72 @*/
73 PetscErrorCode PCICCSetMatOrdering(PC pc,MatOrderingType ordering)
74 {
75   PetscErrorCode ierr,(*f)(PC,MatOrderingType);
76 
77   PetscFunctionBegin;
78   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
79   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCICCSetMatOrdering_C",(void (**)(void))&f);CHKERRQ(ierr);
80   if (f) {
81     ierr = (*f)(pc,ordering);CHKERRQ(ierr);
82   }
83   PetscFunctionReturn(0);
84 }
85 
86 #undef __FUNCT__
87 #define __FUNCT__ "PCICCSetLevels"
88 /*@
89    PCICCSetLevels - Sets the number of levels of fill to use.
90 
91    Collective on PC
92 
93    Input Parameters:
94 +  pc - the preconditioner context
95 -  levels - number of levels of fill
96 
97    Options Database Key:
98 .  -pc_icc_levels <levels> - Sets fill level
99 
100    Level: intermediate
101 
102    Concepts: ICC^setting levels of fill
103 
104 @*/
105 PetscErrorCode PCICCSetLevels(PC pc,PetscInt levels)
106 {
107   PetscErrorCode ierr,(*f)(PC,PetscInt);
108 
109   PetscFunctionBegin;
110   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
111   if (levels < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"negative levels");
112   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCICCSetLevels_C",(void (**)(void))&f);CHKERRQ(ierr);
113   if (f) {
114     ierr = (*f)(pc,levels);CHKERRQ(ierr);
115   }
116   PetscFunctionReturn(0);
117 }
118 
119 #undef __FUNCT__
120 #define __FUNCT__ "PCICCSetFill"
121 /*@
122    PCICCSetFill - Indicate the amount of fill you expect in the factored matrix,
123    where fill = number nonzeros in factor/number nonzeros in original matrix.
124 
125    Collective on PC
126 
127    Input Parameters:
128 +  pc - the preconditioner context
129 -  fill - amount of expected fill
130 
131    Options Database Key:
132 $  -pc_icc_fill <fill>
133 
134    Note:
135    For sparse matrix factorizations it is difficult to predict how much
136    fill to expect. By running with the option -log_info PETSc will print the
137    actual amount of fill used; allowing you to set the value accurately for
138    future runs. But default PETSc uses a value of 1.0
139 
140    Level: intermediate
141 
142 .keywords: PC, set, factorization, direct, fill
143 
144 .seealso: PCLUSetFill()
145 @*/
146 PetscErrorCode PCICCSetFill(PC pc,PetscReal fill)
147 {
148   PetscErrorCode ierr,(*f)(PC,PetscReal);
149 
150   PetscFunctionBegin;
151   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
152   if (fill < 1.0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Fill factor cannot be less than 1.0");
153   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCICCSetFill_C",(void (**)(void))&f);CHKERRQ(ierr);
154   if (f) {
155     ierr = (*f)(pc,fill);CHKERRQ(ierr);
156   }
157   PetscFunctionReturn(0);
158 }
159 
160 #undef __FUNCT__
161 #define __FUNCT__ "PCSetup_ICC"
162 static PetscErrorCode PCSetup_ICC(PC pc)
163 {
164   PC_ICC         *icc = (PC_ICC*)pc->data;
165   IS             perm,cperm;
166   PetscErrorCode ierr;
167 
168   PetscFunctionBegin;
169   ierr = MatGetOrdering(pc->pmat,icc->ordering,&perm,&cperm);CHKERRQ(ierr);
170 
171   if (!pc->setupcalled) {
172     ierr = MatICCFactorSymbolic(pc->pmat,perm,&icc->info,&icc->fact);CHKERRQ(ierr);
173   } else if (pc->flag != SAME_NONZERO_PATTERN) {
174     ierr = MatDestroy(icc->fact);CHKERRQ(ierr);
175     ierr = MatICCFactorSymbolic(pc->pmat,perm,&icc->info,&icc->fact);CHKERRQ(ierr);
176   }
177   ierr = ISDestroy(cperm);CHKERRQ(ierr);
178   ierr = ISDestroy(perm);CHKERRQ(ierr);
179   ierr = MatCholeskyFactorNumeric(pc->pmat,&icc->info,&icc->fact);CHKERRQ(ierr);
180   PetscFunctionReturn(0);
181 }
182 
183 #undef __FUNCT__
184 #define __FUNCT__ "PCDestroy_ICC"
185 static PetscErrorCode PCDestroy_ICC(PC pc)
186 {
187   PC_ICC         *icc = (PC_ICC*)pc->data;
188   PetscErrorCode ierr;
189 
190   PetscFunctionBegin;
191   if (icc->fact) {ierr = MatDestroy(icc->fact);CHKERRQ(ierr);}
192   ierr = PetscStrfree(icc->ordering);CHKERRQ(ierr);
193   ierr = PetscFree(icc);CHKERRQ(ierr);
194   PetscFunctionReturn(0);
195 }
196 
197 #undef __FUNCT__
198 #define __FUNCT__ "PCApply_ICC"
199 static PetscErrorCode PCApply_ICC(PC pc,Vec x,Vec y)
200 {
201   PC_ICC         *icc = (PC_ICC*)pc->data;
202   PetscErrorCode ierr;
203 
204   PetscFunctionBegin;
205   ierr = MatSolve(icc->fact,x,y);CHKERRQ(ierr);
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "PCApplySymmetricLeft_ICC"
211 static PetscErrorCode PCApplySymmetricLeft_ICC(PC pc,Vec x,Vec y)
212 {
213   PetscErrorCode ierr;
214   PC_ICC         *icc = (PC_ICC*)pc->data;
215 
216   PetscFunctionBegin;
217   ierr = MatForwardSolve(icc->fact,x,y);CHKERRQ(ierr);
218   PetscFunctionReturn(0);
219 }
220 
221 #undef __FUNCT__
222 #define __FUNCT__ "PCApplySymmetricRight_ICC"
223 static PetscErrorCode PCApplySymmetricRight_ICC(PC pc,Vec x,Vec y)
224 {
225   PetscErrorCode ierr;
226   PC_ICC         *icc = (PC_ICC*)pc->data;
227 
228   PetscFunctionBegin;
229   ierr = MatBackwardSolve(icc->fact,x,y);CHKERRQ(ierr);
230   PetscFunctionReturn(0);
231 }
232 
233 #undef __FUNCT__
234 #define __FUNCT__ "PCGetFactoredMatrix_ICC"
235 static PetscErrorCode PCGetFactoredMatrix_ICC(PC pc,Mat *mat)
236 {
237   PC_ICC *icc = (PC_ICC*)pc->data;
238 
239   PetscFunctionBegin;
240   *mat = icc->fact;
241   PetscFunctionReturn(0);
242 }
243 
244 #undef __FUNCT__
245 #define __FUNCT__ "PCSetFromOptions_ICC"
246 static PetscErrorCode PCSetFromOptions_ICC(PC pc)
247 {
248   PC_ICC         *icc = (PC_ICC*)pc->data;
249   char           tname[256];
250   PetscTruth     flg;
251   PetscErrorCode ierr;
252   PetscFList     ordlist;
253 
254   PetscFunctionBegin;
255   ierr = MatOrderingRegisterAll(PETSC_NULL);CHKERRQ(ierr);
256   ierr = PetscOptionsHead("ICC Options");CHKERRQ(ierr);
257     ierr = PetscOptionsReal("-pc_icc_levels","levels of fill","PCICCSetLevels",icc->info.levels,&icc->info.levels,&flg);CHKERRQ(ierr);
258     ierr = PetscOptionsReal("-pc_icc_fill","Expected fill in factorization","PCICCSetFill",icc->info.fill,&icc->info.fill,&flg);CHKERRQ(ierr);
259     ierr = MatGetOrderingList(&ordlist);CHKERRQ(ierr);
260     ierr = PetscOptionsList("-pc_icc_mat_ordering_type","Reorder to reduce nonzeros in ICC","PCICCSetMatOrdering",ordlist,icc->ordering,tname,256,&flg);CHKERRQ(ierr);
261     if (flg) {
262       ierr = PCICCSetMatOrdering(pc,tname);CHKERRQ(ierr);
263     }
264     ierr = PetscOptionsName("-pc_factor_shiftnonzero","Shift added to diagonal","PCFactorSetShiftNonzero",&flg);CHKERRQ(ierr);
265     if (flg) {
266       ierr = PCFactorSetShiftNonzero((PetscReal) PETSC_DECIDE,&icc->info);CHKERRQ(ierr);
267     }
268     ierr = PetscOptionsReal("-pc_factor_shiftnonzero","Shift added to diagonal","PCFactorSetShiftNonzero",icc->info.shiftnz,&icc->info.shiftnz,0);CHKERRQ(ierr);
269     ierr = PetscOptionsName("-pc_factor_shiftpd","Manteuffel shift applied to diagonal","PCICCSetShift",&flg);CHKERRQ(ierr);
270     if (flg) {
271       ierr = PCFactorSetShiftPd(PETSC_TRUE,&icc->info);CHKERRQ(ierr);
272     } else {
273       ierr = PCFactorSetShiftPd(PETSC_FALSE,&icc->info);CHKERRQ(ierr);
274     }
275     ierr = PetscOptionsReal("-pc_factor_zeropivot","Pivot is considered zero if less than","PCFactorSetZeroPivot",icc->info.zeropivot,&icc->info.zeropivot,0);CHKERRQ(ierr);
276 
277   ierr = PetscOptionsTail();CHKERRQ(ierr);
278   PetscFunctionReturn(0);
279 }
280 
281 #undef __FUNCT__
282 #define __FUNCT__ "PCView_ICC"
283 static PetscErrorCode PCView_ICC(PC pc,PetscViewer viewer)
284 {
285   PC_ICC         *icc = (PC_ICC*)pc->data;
286   PetscErrorCode ierr;
287   PetscTruth     isstring,iascii;
288 
289   PetscFunctionBegin;
290   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr);
291   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
292   if (iascii) {
293     if (icc->info.levels == 1) {
294         ierr = PetscViewerASCIIPrintf(viewer,"  ICC: %D level of fill\n",(PetscInt)icc->info.levels);CHKERRQ(ierr);
295     } else {
296         ierr = PetscViewerASCIIPrintf(viewer,"  ICC: %D levels of fill\n",(PetscInt)icc->info.levels);CHKERRQ(ierr);
297     }
298     ierr = PetscViewerASCIIPrintf(viewer,"  ICC: max fill ratio allocated %g\n",icc->info.fill);CHKERRQ(ierr);
299     if (icc->info.shiftpd) {ierr = PetscViewerASCIIPrintf(viewer,"  ICC: using Manteuffel shift\n");CHKERRQ(ierr);}
300   } else if (isstring) {
301     ierr = PetscViewerStringSPrintf(viewer," lvls=%D",(PetscInt)icc->info.levels);CHKERRQ(ierr);CHKERRQ(ierr);
302   } else {
303     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCICC",((PetscObject)viewer)->type_name);
304   }
305   PetscFunctionReturn(0);
306 }
307 
308 /*MC
309      PCICC - Incomplete Cholesky factorization preconditioners.
310 
311    Options Database Keys:
312 +  -pc_icc_levels <k> - number of levels of fill for ICC(k)
313 .  -pc_icc_in_place - only for ICC(0) with natural ordering, reuses the space of the matrix for
314                       its factorization (overwrites original matrix)
315 .  -pc_icc_fill <nfill> - expected amount of fill in factored matrix compared to original matrix, nfill > 1
316 -  -pc_icc_mat_ordering_type <natural,nd,1wd,rcm,qmd> - set the row/column ordering of the factored matrix
317 
318    Level: beginner
319 
320   Concepts: incomplete Cholesky factorization
321 
322    Notes: Only implemented for some matrix formats. Not implemented in parallel
323 
324           For BAIJ matrices this implements a point block ICC.
325 
326           The Manteuffel shift is only implemented for matrices with block size 1
327 
328           By default, the Manteuffel is applied (for matrices with block size 1). Call PCICCSetShift(pc,PETSC_FALSE);
329           to turn off the shift.
330 
331 
332 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCSOR, MatOrderingType,
333            PCFactorSetZeroPivot(), PCFactorSetShiftNonzero(), PCFactorSetShiftPd(),
334            PCICCSetFill(), PCICCSetMatOrdering(), PCICCSetReuseOrdering(),
335            PCICCSetLevels()
336 
337 M*/
338 
339 EXTERN_C_BEGIN
340 #undef __FUNCT__
341 #define __FUNCT__ "PCCreate_ICC"
342 PetscErrorCode PCCreate_ICC(PC pc)
343 {
344   PetscErrorCode ierr;
345   PC_ICC         *icc;
346 
347   PetscFunctionBegin;
348   ierr = PetscNew(PC_ICC,&icc);CHKERRQ(ierr);
349   PetscLogObjectMemory(pc,sizeof(PC_ICC));
350 
351   icc->fact	          = 0;
352   ierr = PetscStrallocpy(MATORDERING_NATURAL,&icc->ordering);CHKERRQ(ierr);
353   ierr = MatFactorInfoInitialize(&icc->info);CHKERRQ(ierr);
354   icc->info.levels	  = 0;
355   icc->info.fill          = 1.0;
356   icc->implctx            = 0;
357 
358   icc->info.dtcol              = PETSC_DEFAULT;
359   icc->info.shiftnz            = 0.0;
360   icc->info.shiftpd            = PETSC_TRUE;
361   icc->info.shift_fraction     = 0.0;
362   icc->info.zeropivot          = 1.e-12;
363   pc->data	               = (void*)icc;
364 
365   pc->ops->apply	       = PCApply_ICC;
366   pc->ops->setup               = PCSetup_ICC;
367   pc->ops->destroy	       = PCDestroy_ICC;
368   pc->ops->setfromoptions      = PCSetFromOptions_ICC;
369   pc->ops->view                = PCView_ICC;
370   pc->ops->getfactoredmatrix   = PCGetFactoredMatrix_ICC;
371   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_ICC;
372   pc->ops->applysymmetricright = PCApplySymmetricRight_ICC;
373 
374   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetLevels_C","PCICCSetLevels_ICC",
375                     PCICCSetLevels_ICC);CHKERRQ(ierr);
376   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetFill_C","PCICCSetFill_ICC",
377                     PCICCSetFill_ICC);CHKERRQ(ierr);
378   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCICCSetMatOrdering_C","PCICCSetMatOrdering_ICC",
379                     PCICCSetMatOrdering_ICC);CHKERRQ(ierr);
380   PetscFunctionReturn(0);
381 }
382 EXTERN_C_END
383 
384 
385