xref: /petsc/src/ksp/pc/impls/factor/factimpl.c (revision bef158480efac06de457f7a665168877ab3c2fd7)
1 
2 #include <../src/ksp/pc/impls/factor/factor.h>     /*I "petscpc.h"  I*/
3 
4 /* ------------------------------------------------------------------------------------------*/
5 
6 
7 PetscErrorCode PCFactorSetUpMatSolverType_Factor(PC pc)
8 {
9   PC_Factor      *icc = (PC_Factor*)pc->data;
10   PetscErrorCode ierr;
11 
12   PetscFunctionBegin;
13   if (!pc->pmat) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"You can only call this routine after the matrix object has been provided to the solver, for example with KSPSetOperators() or SNESSetJacobian()");
14   if (!pc->setupcalled && !((PC_Factor*)icc)->fact) {
15     ierr = MatGetFactor(pc->pmat,((PC_Factor*)icc)->solvertype,((PC_Factor*)icc)->factortype,&((PC_Factor*)icc)->fact);CHKERRQ(ierr);
16   }
17   PetscFunctionReturn(0);
18 }
19 
20 PetscErrorCode  PCFactorSetZeroPivot_Factor(PC pc,PetscReal z)
21 {
22   PC_Factor *ilu = (PC_Factor*)pc->data;
23 
24   PetscFunctionBegin;
25   ilu->info.zeropivot = z;
26   PetscFunctionReturn(0);
27 }
28 
29 PetscErrorCode  PCFactorSetShiftType_Factor(PC pc,MatFactorShiftType shifttype)
30 {
31   PC_Factor *dir = (PC_Factor*)pc->data;
32 
33   PetscFunctionBegin;
34   if (shifttype == (MatFactorShiftType)PETSC_DECIDE) dir->info.shifttype = (PetscReal) MAT_SHIFT_NONE;
35   else {
36     dir->info.shifttype = (PetscReal) shifttype;
37     if ((shifttype == MAT_SHIFT_NONZERO || shifttype ==  MAT_SHIFT_INBLOCKS) && dir->info.shiftamount == 0.0) {
38       dir->info.shiftamount = 100.0*PETSC_MACHINE_EPSILON; /* set default amount if user has not called PCFactorSetShiftAmount() yet */
39     }
40   }
41   PetscFunctionReturn(0);
42 }
43 
44 PetscErrorCode  PCFactorSetShiftAmount_Factor(PC pc,PetscReal shiftamount)
45 {
46   PC_Factor *dir = (PC_Factor*)pc->data;
47 
48   PetscFunctionBegin;
49   if (shiftamount == (PetscReal) PETSC_DECIDE) dir->info.shiftamount = 100.0*PETSC_MACHINE_EPSILON;
50   else dir->info.shiftamount = shiftamount;
51   PetscFunctionReturn(0);
52 }
53 
54 PetscErrorCode  PCFactorSetDropTolerance_Factor(PC pc,PetscReal dt,PetscReal dtcol,PetscInt dtcount)
55 {
56   PC_Factor *ilu = (PC_Factor*)pc->data;
57 
58   PetscFunctionBegin;
59   if (pc->setupcalled && (!ilu->info.usedt || ((PC_Factor*)ilu)->info.dt != dt || ((PC_Factor*)ilu)->info.dtcol != dtcol || ((PC_Factor*)ilu)->info.dtcount != dtcount)) {
60     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Cannot change tolerance after use");
61   }
62   ilu->info.usedt   = PETSC_TRUE;
63   ilu->info.dt      = dt;
64   ilu->info.dtcol   = dtcol;
65   ilu->info.dtcount = dtcount;
66   ilu->info.fill    = PETSC_DEFAULT;
67   PetscFunctionReturn(0);
68 }
69 
70 PetscErrorCode  PCFactorSetFill_Factor(PC pc,PetscReal fill)
71 {
72   PC_Factor *dir = (PC_Factor*)pc->data;
73 
74   PetscFunctionBegin;
75   dir->info.fill = fill;
76   PetscFunctionReturn(0);
77 }
78 
79 PetscErrorCode  PCFactorSetMatOrderingType_Factor(PC pc,MatOrderingType ordering)
80 {
81   PC_Factor      *dir = (PC_Factor*)pc->data;
82   PetscErrorCode ierr;
83   PetscBool      flg;
84 
85   PetscFunctionBegin;
86   if (!pc->setupcalled) {
87     ierr = PetscFree(dir->ordering);CHKERRQ(ierr);
88     ierr = PetscStrallocpy(ordering,(char**)&dir->ordering);CHKERRQ(ierr);
89   } else {
90     ierr = PetscStrcmp(dir->ordering,ordering,&flg);CHKERRQ(ierr);
91     if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Cannot change ordering after use");
92   }
93   PetscFunctionReturn(0);
94 }
95 
96 PetscErrorCode  PCFactorGetLevels_Factor(PC pc,PetscInt *levels)
97 {
98   PC_Factor      *ilu = (PC_Factor*)pc->data;
99 
100   PetscFunctionBegin;
101   *levels = ilu->info.levels;
102   PetscFunctionReturn(0);
103 }
104 
105 PetscErrorCode  PCFactorGetZeroPivot_Factor(PC pc,PetscReal *pivot)
106 {
107   PC_Factor      *ilu = (PC_Factor*)pc->data;
108 
109   PetscFunctionBegin;
110   *pivot = ilu->info.zeropivot;
111   PetscFunctionReturn(0);
112 }
113 
114 PetscErrorCode  PCFactorGetShiftAmount_Factor(PC pc,PetscReal *shift)
115 {
116   PC_Factor      *ilu = (PC_Factor*)pc->data;
117 
118   PetscFunctionBegin;
119   *shift = ilu->info.shiftamount;
120   PetscFunctionReturn(0);
121 }
122 
123 PetscErrorCode  PCFactorGetShiftType_Factor(PC pc,MatFactorShiftType *type)
124 {
125   PC_Factor      *ilu = (PC_Factor*)pc->data;
126 
127   PetscFunctionBegin;
128   *type = (MatFactorShiftType) (int) ilu->info.shifttype;
129   PetscFunctionReturn(0);
130 }
131 
132 PetscErrorCode  PCFactorSetLevels_Factor(PC pc,PetscInt levels)
133 {
134   PC_Factor      *ilu = (PC_Factor*)pc->data;
135   PetscErrorCode ierr;
136 
137   PetscFunctionBegin;
138   if (!pc->setupcalled) ilu->info.levels = levels;
139   else if (ilu->info.levels != levels) {
140     ierr             = (*pc->ops->reset)(pc);CHKERRQ(ierr); /* remove previous factored matrices */
141     pc->setupcalled  = 0; /* force a complete rebuild of preconditioner factored matrices */
142     ilu->info.levels = levels;
143   } else if (ilu->info.usedt) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Cannot change levels after use with ILUdt");
144   PetscFunctionReturn(0);
145 }
146 
147 PetscErrorCode  PCFactorSetAllowDiagonalFill_Factor(PC pc,PetscBool flg)
148 {
149   PC_Factor *dir = (PC_Factor*)pc->data;
150 
151   PetscFunctionBegin;
152   dir->info.diagonal_fill = (PetscReal) flg;
153   PetscFunctionReturn(0);
154 }
155 
156 PetscErrorCode  PCFactorGetAllowDiagonalFill_Factor(PC pc,PetscBool *flg)
157 {
158   PC_Factor *dir = (PC_Factor*)pc->data;
159 
160   PetscFunctionBegin;
161   *flg = dir->info.diagonal_fill ? PETSC_TRUE : PETSC_FALSE;
162   PetscFunctionReturn(0);
163 }
164 
165 /* ------------------------------------------------------------------------------------------*/
166 
167 PetscErrorCode  PCFactorSetPivotInBlocks_Factor(PC pc,PetscBool pivot)
168 {
169   PC_Factor *dir = (PC_Factor*)pc->data;
170 
171   PetscFunctionBegin;
172   dir->info.pivotinblocks = pivot ? 1.0 : 0.0;
173   PetscFunctionReturn(0);
174 }
175 
176 PetscErrorCode  PCFactorGetMatrix_Factor(PC pc,Mat *mat)
177 {
178   PC_Factor *ilu = (PC_Factor*)pc->data;
179 
180   PetscFunctionBegin;
181   if (!ilu->fact) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Matrix not yet factored; call after KSPSetUp() or PCSetUp()");
182   *mat = ilu->fact;
183   PetscFunctionReturn(0);
184 }
185 
186 PetscErrorCode  PCFactorSetMatSolverType_Factor(PC pc,MatSolverType stype)
187 {
188   PetscErrorCode ierr;
189   PC_Factor      *lu = (PC_Factor*)pc->data;
190 
191   PetscFunctionBegin;
192   if (lu->fact) {
193     MatSolverType ltype;
194     PetscBool     flg;
195     ierr = MatFactorGetSolverType(lu->fact,&ltype);CHKERRQ(ierr);
196     ierr = PetscStrcmp(stype,ltype,&flg);CHKERRQ(ierr);
197     if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Cannot change solver matrix package after PC has been setup or used");
198   }
199 
200   ierr = PetscFree(lu->solvertype);CHKERRQ(ierr);
201   ierr = PetscStrallocpy(stype,&lu->solvertype);CHKERRQ(ierr);
202   PetscFunctionReturn(0);
203 }
204 
205 PetscErrorCode  PCFactorGetMatSolverType_Factor(PC pc,MatSolverType *stype)
206 {
207   PC_Factor *lu = (PC_Factor*)pc->data;
208 
209   PetscFunctionBegin;
210   *stype = lu->solvertype;
211   PetscFunctionReturn(0);
212 }
213 
214 PetscErrorCode  PCFactorSetColumnPivot_Factor(PC pc,PetscReal dtcol)
215 {
216   PC_Factor *dir = (PC_Factor*)pc->data;
217 
218   PetscFunctionBegin;
219   if (dtcol < 0.0 || dtcol > 1.0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Column pivot tolerance is %g must be between 0 and 1",(double)dtcol);
220   dir->info.dtcol = dtcol;
221   PetscFunctionReturn(0);
222 }
223 
224 PetscErrorCode  PCSetFromOptions_Factor(PetscOptionItems *PetscOptionsObject,PC pc)
225 {
226   PC_Factor         *factor = (PC_Factor*)pc->data;
227   PetscErrorCode    ierr;
228   PetscBool         flg,set;
229   char              tname[256], solvertype[64];
230   PetscFunctionList ordlist;
231   PetscEnum         etmp;
232   PetscBool         inplace;
233 
234   PetscFunctionBegin;
235   ierr = PCFactorGetUseInPlace(pc,&inplace);CHKERRQ(ierr);
236   ierr = PetscOptionsBool("-pc_factor_in_place","Form factored matrix in the same memory as the matrix","PCFactorSetUseInPlace",inplace,&flg,&set);CHKERRQ(ierr);
237   if (set) {
238     ierr = PCFactorSetUseInPlace(pc,flg);CHKERRQ(ierr);
239   }
240   ierr = PetscOptionsReal("-pc_factor_fill","Expected non-zeros in factored matrix","PCFactorSetFill",((PC_Factor*)factor)->info.fill,&((PC_Factor*)factor)->info.fill,NULL);CHKERRQ(ierr);
241 
242   ierr = PetscOptionsEnum("-pc_factor_shift_type","Type of shift to add to diagonal","PCFactorSetShiftType",MatFactorShiftTypes,(PetscEnum)(int)((PC_Factor*)factor)->info.shifttype,&etmp,&flg);CHKERRQ(ierr);
243   if (flg) {
244     ierr = PCFactorSetShiftType(pc,(MatFactorShiftType)etmp);CHKERRQ(ierr);
245   }
246   ierr = PetscOptionsReal("-pc_factor_shift_amount","Shift added to diagonal","PCFactorSetShiftAmount",((PC_Factor*)factor)->info.shiftamount,&((PC_Factor*)factor)->info.shiftamount,NULL);CHKERRQ(ierr);
247 
248   ierr = PetscOptionsReal("-pc_factor_zeropivot","Pivot is considered zero if less than","PCFactorSetZeroPivot",((PC_Factor*)factor)->info.zeropivot,&((PC_Factor*)factor)->info.zeropivot,NULL);CHKERRQ(ierr);
249   ierr = PetscOptionsReal("-pc_factor_column_pivot","Column pivot tolerance (used only for some factorization)","PCFactorSetColumnPivot",((PC_Factor*)factor)->info.dtcol,&((PC_Factor*)factor)->info.dtcol,&flg);CHKERRQ(ierr);
250 
251   ierr = PetscOptionsBool("-pc_factor_pivot_in_blocks","Pivot inside matrix dense blocks for BAIJ and SBAIJ","PCFactorSetPivotInBlocks",((PC_Factor*)factor)->info.pivotinblocks ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
252   if (set) {
253     ierr = PCFactorSetPivotInBlocks(pc,flg);CHKERRQ(ierr);
254   }
255 
256   ierr = PetscOptionsBool("-pc_factor_reuse_fill","Use fill from previous factorization","PCFactorSetReuseFill",PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
257   if (set) {
258     ierr = PCFactorSetReuseFill(pc,flg);CHKERRQ(ierr);
259   }
260   ierr = PetscOptionsBool("-pc_factor_reuse_ordering","Reuse ordering from previous factorization","PCFactorSetReuseOrdering",PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
261   if (set) {
262     ierr = PCFactorSetReuseOrdering(pc,flg);CHKERRQ(ierr);
263   }
264 
265   ierr = MatGetOrderingList(&ordlist);CHKERRQ(ierr);
266   ierr = PetscOptionsFList("-pc_factor_mat_ordering_type","Reordering to reduce nonzeros in factored matrix","PCFactorSetMatOrderingType",ordlist,((PC_Factor*)factor)->ordering,tname,sizeof(tname),&flg);CHKERRQ(ierr);
267   if (flg) {
268     ierr = PCFactorSetMatOrderingType(pc,tname);CHKERRQ(ierr);
269   }
270 
271   /* maybe should have MatGetSolverTypes(Mat,&list) like the ordering list */
272   ierr = PetscOptionsDeprecated("-pc_factor_mat_solver_package","-pc_factor_mat_solver_type","3.9",NULL);CHKERRQ(ierr);
273   ierr = PetscOptionsString("-pc_factor_mat_solver_type","Specific direct solver to use","MatGetFactor",((PC_Factor*)factor)->solvertype,solvertype,sizeof(solvertype),&flg);CHKERRQ(ierr);
274   if (flg) {
275     ierr = PCFactorSetMatSolverType(pc,solvertype);CHKERRQ(ierr);
276   }
277   PetscFunctionReturn(0);
278 }
279 
280 PetscErrorCode PCView_Factor(PC pc,PetscViewer viewer)
281 {
282   PC_Factor       *factor = (PC_Factor*)pc->data;
283   PetscErrorCode  ierr;
284   PetscBool       isstring,iascii,flg;
285   MatOrderingType ordering;
286 
287   PetscFunctionBegin;
288   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
289   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
290   if (iascii) {
291     if (factor->inplace) {
292       ierr = PetscViewerASCIIPrintf(viewer,"  in-place factorization\n");CHKERRQ(ierr);
293     } else {
294       ierr = PetscViewerASCIIPrintf(viewer,"  out-of-place factorization\n");CHKERRQ(ierr);
295     }
296 
297     if (factor->reusefill)     {ierr = PetscViewerASCIIPrintf(viewer,"  Reusing fill from past factorization\n");CHKERRQ(ierr);}
298     if (factor->reuseordering) {ierr = PetscViewerASCIIPrintf(viewer,"  Reusing reordering from past factorization\n");CHKERRQ(ierr);}
299     if (factor->factortype == MAT_FACTOR_ILU || factor->factortype == MAT_FACTOR_ICC) {
300       if (factor->info.dt > 0) {
301         ierr = PetscViewerASCIIPrintf(viewer,"  drop tolerance %g\n",(double)factor->info.dt);CHKERRQ(ierr);
302         ierr = PetscViewerASCIIPrintf(viewer,"  max nonzeros per row %D\n",factor->info.dtcount);CHKERRQ(ierr);
303         ierr = PetscViewerASCIIPrintf(viewer,"  column permutation tolerance %g\n",(double)factor->info.dtcol);CHKERRQ(ierr);
304       } else if (factor->info.levels == 1) {
305         ierr = PetscViewerASCIIPrintf(viewer,"  %D level of fill\n",(PetscInt)factor->info.levels);CHKERRQ(ierr);
306       } else {
307         ierr = PetscViewerASCIIPrintf(viewer,"  %D levels of fill\n",(PetscInt)factor->info.levels);CHKERRQ(ierr);
308       }
309     }
310 
311     ierr = PetscViewerASCIIPrintf(viewer,"  tolerance for zero pivot %g\n",(double)factor->info.zeropivot);CHKERRQ(ierr);
312     if (MatFactorShiftTypesDetail[(int)factor->info.shifttype]) { /* Only print when using a nontrivial shift */
313       ierr = PetscViewerASCIIPrintf(viewer,"  using %s [%s]\n",MatFactorShiftTypesDetail[(int)factor->info.shifttype],MatFactorShiftTypes[(int)factor->info.shifttype]);CHKERRQ(ierr);
314     }
315 
316     ierr = PetscStrcmp(factor->ordering,MATORDERINGNATURAL_OR_ND,&flg);CHKERRQ(ierr);
317     if (flg) {
318       PetscBool isseqsbaij;
319       ierr = PetscObjectTypeCompareAny((PetscObject)pc->pmat,&isseqsbaij,MATSEQSBAIJ,MATSEQBAIJ,NULL);CHKERRQ(ierr);
320       if (isseqsbaij) {
321         ordering = MATORDERINGNATURAL;
322       } else {
323         ordering = MATORDERINGND;
324       }
325     } else {
326       ordering = factor->ordering;
327     }
328     if (!factor->fact) {
329       ierr = PetscViewerASCIIPrintf(viewer,"  matrix ordering: %s (may be overridden during setup)\n",ordering);CHKERRQ(ierr);
330     } else {
331       PetscBool useordering;
332       MatInfo   info;
333       ierr = MatFactorGetUseOrdering(factor->fact,&useordering);CHKERRQ(ierr);
334       if (!useordering) ordering = "external";
335       ierr = PetscViewerASCIIPrintf(viewer,"  matrix ordering: %s\n",ordering);CHKERRQ(ierr);
336       ierr = MatGetInfo(factor->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
337       ierr = PetscViewerASCIIPrintf(viewer,"  factor fill ratio given %g, needed %g\n",(double)info.fill_ratio_given,(double)info.fill_ratio_needed);CHKERRQ(ierr);
338       ierr = PetscViewerASCIIPrintf(viewer,"    Factored matrix follows:\n");CHKERRQ(ierr);
339       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
340       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
341       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
342       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
343       ierr = MatView(factor->fact,viewer);CHKERRQ(ierr);
344       ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
345       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
346       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
347       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
348     }
349 
350   } else if (isstring) {
351     MatFactorType t;
352     ierr = MatGetFactorType(factor->fact,&t);CHKERRQ(ierr);
353     if (t == MAT_FACTOR_ILU || t == MAT_FACTOR_ICC) {
354       ierr = PetscViewerStringSPrintf(viewer," lvls=%D,order=%s",(PetscInt)factor->info.levels,factor->ordering);CHKERRQ(ierr);
355     }
356   }
357   PetscFunctionReturn(0);
358 }
359