xref: /petsc/src/ksp/pc/impls/factor/ilu/ilu.c (revision aed5ffcbc31e41b96407a92d0c19d6464f10f960)
1 
2 /*
3    Defines a ILU factorization preconditioner for any Mat implementation
4 */
5 #include <../src/ksp/pc/impls/factor/ilu/ilu.h>     /*I "petscpc.h"  I*/
6 
7 /* ------------------------------------------------------------------------------------------*/
8 #undef __FUNCT__
9 #define __FUNCT__ "PCFactorSetReuseFill_ILU"
10 PetscErrorCode  PCFactorSetReuseFill_ILU(PC pc,PetscBool flag)
11 {
12   PC_ILU *lu = (PC_ILU*)pc->data;
13 
14   PetscFunctionBegin;
15   lu->reusefill = flag;
16   PetscFunctionReturn(0);
17 }
18 
19 #undef __FUNCT__
20 #define __FUNCT__ "PCFactorReorderForNonzeroDiagonal_ILU"
21 PetscErrorCode  PCFactorReorderForNonzeroDiagonal_ILU(PC pc,PetscReal z)
22 {
23   PC_ILU *ilu = (PC_ILU*)pc->data;
24 
25   PetscFunctionBegin;
26   ilu->nonzerosalongdiagonal = PETSC_TRUE;
27   if (z == PETSC_DECIDE) ilu->nonzerosalongdiagonaltol = 1.e-10;
28   else ilu->nonzerosalongdiagonaltol = z;
29   PetscFunctionReturn(0);
30 }
31 
32 #undef __FUNCT__
33 #define __FUNCT__ "PCReset_ILU"
34 PetscErrorCode PCReset_ILU(PC pc)
35 {
36   PC_ILU         *ilu = (PC_ILU*)pc->data;
37   PetscErrorCode ierr;
38 
39   PetscFunctionBegin;
40   if (!ilu->inplace) {ierr = MatDestroy(&((PC_Factor*)ilu)->fact);CHKERRQ(ierr);}
41   if (ilu->row && ilu->col && ilu->row != ilu->col) {ierr = ISDestroy(&ilu->row);CHKERRQ(ierr);}
42   ierr = ISDestroy(&ilu->col);CHKERRQ(ierr);
43   PetscFunctionReturn(0);
44 }
45 
46 #undef __FUNCT__
47 #define __FUNCT__ "PCFactorSetDropTolerance_ILU"
48 PetscErrorCode  PCFactorSetDropTolerance_ILU(PC pc,PetscReal dt,PetscReal dtcol,PetscInt dtcount)
49 {
50   PC_ILU *ilu = (PC_ILU*)pc->data;
51 
52   PetscFunctionBegin;
53   if (pc->setupcalled && (((PC_Factor*)ilu)->info.dt != dt || ((PC_Factor*)ilu)->info.dtcol != dtcol || ((PC_Factor*)ilu)->info.dtcount != dtcount)) {
54     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot change drop tolerance after using PC");
55   }
56   ((PC_Factor*)ilu)->info.dt      = dt;
57   ((PC_Factor*)ilu)->info.dtcol   = dtcol;
58   ((PC_Factor*)ilu)->info.dtcount = dtcount;
59   ((PC_Factor*)ilu)->info.usedt   = 1.0;
60   PetscFunctionReturn(0);
61 }
62 
63 #undef __FUNCT__
64 #define __FUNCT__ "PCFactorSetReuseOrdering_ILU"
65 PetscErrorCode  PCFactorSetReuseOrdering_ILU(PC pc,PetscBool flag)
66 {
67   PC_ILU *ilu = (PC_ILU*)pc->data;
68 
69   PetscFunctionBegin;
70   ilu->reuseordering = flag;
71   PetscFunctionReturn(0);
72 }
73 
74 #undef __FUNCT__
75 #define __FUNCT__ "PCFactorSetUseInPlace_ILU"
76 PetscErrorCode  PCFactorSetUseInPlace_ILU(PC pc)
77 {
78   PC_ILU *dir = (PC_ILU*)pc->data;
79 
80   PetscFunctionBegin;
81   dir->inplace = PETSC_TRUE;
82   PetscFunctionReturn(0);
83 }
84 
85 #undef __FUNCT__
86 #define __FUNCT__ "PCSetFromOptions_ILU"
87 static PetscErrorCode PCSetFromOptions_ILU(PC pc)
88 {
89   PetscErrorCode ierr;
90   PetscInt       itmp;
91   PetscBool      flg;
92   PC_ILU         *ilu = (PC_ILU*)pc->data;
93   PetscReal      tol;
94   /* PetscReal      dt[3]; */
95 
96   PetscFunctionBegin;
97   ierr = PetscOptionsHead("ILU Options");CHKERRQ(ierr);
98   ierr = PCSetFromOptions_Factor(pc);CHKERRQ(ierr);
99 
100   ierr = PetscOptionsInt("-pc_factor_levels","levels of fill","PCFactorSetLevels",(PetscInt)((PC_Factor*)ilu)->info.levels,&itmp,&flg);CHKERRQ(ierr);
101   if (flg) ((PC_Factor*)ilu)->info.levels = itmp;
102 
103   flg  = PETSC_FALSE;
104   ierr = PetscOptionsBool("-pc_factor_diagonal_fill","Allow fill into empty diagonal entry","PCFactorSetAllowDiagonalFill",flg,&flg,NULL);CHKERRQ(ierr);
105   ((PC_Factor*)ilu)->info.diagonal_fill = (double) flg;
106   /*
107   dt[0] = ((PC_Factor*)ilu)->info.dt;
108   dt[1] = ((PC_Factor*)ilu)->info.dtcol;
109   dt[2] = ((PC_Factor*)ilu)->info.dtcount;
110 
111   PetscInt       dtmax = 3;
112   ierr = PetscOptionsRealArray("-pc_factor_drop_tolerance,","<dt,dtcol,maxrowcount>","PCFactorSetDropTolerance",dt,&dtmax,&flg);CHKERRQ(ierr);
113   if (flg) {
114     ierr = PCFactorSetDropTolerance(pc,dt[0],dt[1],(PetscInt)dt[2]);CHKERRQ(ierr);
115   }
116   */
117   ierr = PetscOptionsName("-pc_factor_nonzeros_along_diagonal","Reorder to remove zeros from diagonal","PCFactorReorderForNonzeroDiagonal",&flg);CHKERRQ(ierr);
118   if (flg) {
119     tol  = PETSC_DECIDE;
120     ierr = PetscOptionsReal("-pc_factor_nonzeros_along_diagonal","Reorder to remove zeros from diagonal","PCFactorReorderForNonzeroDiagonal",ilu->nonzerosalongdiagonaltol,&tol,0);CHKERRQ(ierr);
121     ierr = PCFactorReorderForNonzeroDiagonal(pc,tol);CHKERRQ(ierr);
122   }
123 
124   ierr = PetscOptionsTail();CHKERRQ(ierr);
125   PetscFunctionReturn(0);
126 }
127 
128 #undef __FUNCT__
129 #define __FUNCT__ "PCView_ILU"
130 static PetscErrorCode PCView_ILU(PC pc,PetscViewer viewer)
131 {
132   PC_ILU         *ilu = (PC_ILU*)pc->data;
133   PetscErrorCode ierr;
134   PetscBool      iascii;
135 
136   PetscFunctionBegin;
137   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
138   if (iascii) {
139     if (ilu->inplace) {
140       ierr = PetscViewerASCIIPrintf(viewer,"  ILU: in-place factorization\n");CHKERRQ(ierr);
141     } else {
142       ierr = PetscViewerASCIIPrintf(viewer,"  ILU: out-of-place factorization\n");CHKERRQ(ierr);
143     }
144 
145     if (ilu->reusefill)     {ierr = PetscViewerASCIIPrintf(viewer,"  ILU: Reusing fill from past factorization\n");CHKERRQ(ierr);}
146     if (ilu->reuseordering) {ierr = PetscViewerASCIIPrintf(viewer,"  ILU: Reusing reordering from past factorization\n");CHKERRQ(ierr);}
147   }
148   ierr = PCView_Factor(pc,viewer);CHKERRQ(ierr);
149   PetscFunctionReturn(0);
150 }
151 
152 #undef __FUNCT__
153 #define __FUNCT__ "PCSetUp_ILU"
154 static PetscErrorCode PCSetUp_ILU(PC pc)
155 {
156   PetscErrorCode ierr;
157   PC_ILU         *ilu = (PC_ILU*)pc->data;
158   MatInfo        info;
159   PetscBool      flg;
160 
161   PetscFunctionBegin;
162   /* ugly hack to change default, since it is not support by some matrix types */
163   if (((PC_Factor*)ilu)->info.shifttype == (PetscReal)MAT_SHIFT_NONZERO) {
164     ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATSEQAIJ,&flg);CHKERRQ(ierr);
165     if (!flg) {
166       ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATMPIAIJ,&flg);CHKERRQ(ierr);
167       if (!flg) {
168         ((PC_Factor*)ilu)->info.shifttype = (PetscReal)MAT_SHIFT_INBLOCKS;
169         PetscInfo(pc,"Changing shift type from NONZERO to INBLOCKS because block matrices do not support NONZERO");CHKERRQ(ierr);
170       }
171     }
172   }
173 
174   if (ilu->inplace) {
175     if (!pc->setupcalled) {
176 
177       /* In-place factorization only makes sense with the natural ordering,
178          so we only need to get the ordering once, even if nonzero structure changes */
179       ierr = MatGetOrdering(pc->pmat,((PC_Factor*)ilu)->ordering,&ilu->row,&ilu->col);CHKERRQ(ierr);
180       if (ilu->row) {ierr = PetscLogObjectParent(pc,ilu->row);CHKERRQ(ierr);}
181       if (ilu->col) {ierr = PetscLogObjectParent(pc,ilu->col);CHKERRQ(ierr);}
182     }
183 
184     /* In place ILU only makes sense with fill factor of 1.0 because
185        cannot have levels of fill */
186     ((PC_Factor*)ilu)->info.fill          = 1.0;
187     ((PC_Factor*)ilu)->info.diagonal_fill = 0.0;
188 
189     ierr = MatILUFactor(pc->pmat,ilu->row,ilu->col,&((PC_Factor*)ilu)->info);CHKERRQ(ierr);CHKERRQ(ierr);
190     ((PC_Factor*)ilu)->fact = pc->pmat;
191   } else {
192     if (!pc->setupcalled) {
193       /* first time in so compute reordering and symbolic factorization */
194       ierr = MatGetOrdering(pc->pmat,((PC_Factor*)ilu)->ordering,&ilu->row,&ilu->col);CHKERRQ(ierr);
195       if (ilu->row) {ierr = PetscLogObjectParent(pc,ilu->row);CHKERRQ(ierr);}
196       if (ilu->col) {ierr = PetscLogObjectParent(pc,ilu->col);CHKERRQ(ierr);}
197       /*  Remove zeros along diagonal?     */
198       if (ilu->nonzerosalongdiagonal) {
199         ierr = MatReorderForNonzeroDiagonal(pc->pmat,ilu->nonzerosalongdiagonaltol,ilu->row,ilu->col);CHKERRQ(ierr);
200       }
201       if (!((PC_Factor*)ilu)->fact) {
202         ierr = MatGetFactor(pc->pmat,((PC_Factor*)ilu)->solvertype,MAT_FACTOR_ILU,&((PC_Factor*)ilu)->fact);CHKERRQ(ierr);
203       }
204       ierr = MatILUFactorSymbolic(((PC_Factor*)ilu)->fact,pc->pmat,ilu->row,ilu->col,&((PC_Factor*)ilu)->info);CHKERRQ(ierr);
205       ierr = MatGetInfo(((PC_Factor*)ilu)->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
206 
207       ilu->actualfill = info.fill_ratio_needed;
208 
209       ierr = PetscLogObjectParent(pc,((PC_Factor*)ilu)->fact);CHKERRQ(ierr);
210     } else if (pc->flag != SAME_NONZERO_PATTERN) {
211       if (!ilu->reuseordering) {
212         /* compute a new ordering for the ILU */
213         ierr = ISDestroy(&ilu->row);CHKERRQ(ierr);
214         ierr = ISDestroy(&ilu->col);CHKERRQ(ierr);
215         ierr = MatGetOrdering(pc->pmat,((PC_Factor*)ilu)->ordering,&ilu->row,&ilu->col);CHKERRQ(ierr);
216         if (ilu->row) {ierr = PetscLogObjectParent(pc,ilu->row);CHKERRQ(ierr);}
217         if (ilu->col) {ierr = PetscLogObjectParent(pc,ilu->col);CHKERRQ(ierr);}
218         /*  Remove zeros along diagonal?     */
219         if (ilu->nonzerosalongdiagonal) {
220           ierr = MatReorderForNonzeroDiagonal(pc->pmat,ilu->nonzerosalongdiagonaltol,ilu->row,ilu->col);CHKERRQ(ierr);
221         }
222       }
223       ierr = MatDestroy(&((PC_Factor*)ilu)->fact);CHKERRQ(ierr);
224       ierr = MatGetFactor(pc->pmat,((PC_Factor*)ilu)->solvertype,MAT_FACTOR_ILU,&((PC_Factor*)ilu)->fact);CHKERRQ(ierr);
225       ierr = MatILUFactorSymbolic(((PC_Factor*)ilu)->fact,pc->pmat,ilu->row,ilu->col,&((PC_Factor*)ilu)->info);CHKERRQ(ierr);
226       ierr = MatGetInfo(((PC_Factor*)ilu)->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
227 
228       ilu->actualfill = info.fill_ratio_needed;
229 
230       ierr = PetscLogObjectParent(pc,((PC_Factor*)ilu)->fact);CHKERRQ(ierr);
231     }
232     ierr = MatLUFactorNumeric(((PC_Factor*)ilu)->fact,pc->pmat,&((PC_Factor*)ilu)->info);CHKERRQ(ierr);
233   }
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "PCDestroy_ILU"
239 static PetscErrorCode PCDestroy_ILU(PC pc)
240 {
241   PC_ILU         *ilu = (PC_ILU*)pc->data;
242   PetscErrorCode ierr;
243 
244   PetscFunctionBegin;
245   ierr = PCReset_ILU(pc);CHKERRQ(ierr);
246   ierr = PetscFree(((PC_Factor*)ilu)->solvertype);CHKERRQ(ierr);
247   ierr = PetscFree(((PC_Factor*)ilu)->ordering);CHKERRQ(ierr);
248   ierr = PetscFree(pc->data);CHKERRQ(ierr);
249   PetscFunctionReturn(0);
250 }
251 
252 #undef __FUNCT__
253 #define __FUNCT__ "PCApply_ILU"
254 static PetscErrorCode PCApply_ILU(PC pc,Vec x,Vec y)
255 {
256   PC_ILU         *ilu = (PC_ILU*)pc->data;
257   PetscErrorCode ierr;
258 
259   PetscFunctionBegin;
260   ierr = MatSolve(((PC_Factor*)ilu)->fact,x,y);CHKERRQ(ierr);
261   PetscFunctionReturn(0);
262 }
263 
264 #undef __FUNCT__
265 #define __FUNCT__ "PCApplyTranspose_ILU"
266 static PetscErrorCode PCApplyTranspose_ILU(PC pc,Vec x,Vec y)
267 {
268   PC_ILU         *ilu = (PC_ILU*)pc->data;
269   PetscErrorCode ierr;
270 
271   PetscFunctionBegin;
272   ierr = MatSolveTranspose(((PC_Factor*)ilu)->fact,x,y);CHKERRQ(ierr);
273   PetscFunctionReturn(0);
274 }
275 
276 #undef __FUNCT__
277 #define __FUNCT__ "PCApplySymmetricLeft_ILU"
278 static PetscErrorCode PCApplySymmetricLeft_ILU(PC pc,Vec x,Vec y)
279 {
280   PetscErrorCode ierr;
281   PC_ILU         *icc = (PC_ILU*)pc->data;
282 
283   PetscFunctionBegin;
284   ierr = MatForwardSolve(((PC_Factor*)icc)->fact,x,y);CHKERRQ(ierr);
285   PetscFunctionReturn(0);
286 }
287 
288 #undef __FUNCT__
289 #define __FUNCT__ "PCApplySymmetricRight_ILU"
290 static PetscErrorCode PCApplySymmetricRight_ILU(PC pc,Vec x,Vec y)
291 {
292   PetscErrorCode ierr;
293   PC_ILU         *icc = (PC_ILU*)pc->data;
294 
295   PetscFunctionBegin;
296   ierr = MatBackwardSolve(((PC_Factor*)icc)->fact,x,y);CHKERRQ(ierr);
297   PetscFunctionReturn(0);
298 }
299 
300 /*MC
301      PCILU - Incomplete factorization preconditioners.
302 
303    Options Database Keys:
304 +  -pc_factor_levels <k> - number of levels of fill for ILU(k)
305 .  -pc_factor_in_place - only for ILU(0) with natural ordering, reuses the space of the matrix for
306                       its factorization (overwrites original matrix)
307 .  -pc_factor_diagonal_fill - fill in a zero diagonal even if levels of fill indicate it wouldn't be fill
308 .  -pc_factor_reuse_ordering - reuse ordering of factorized matrix from previous factorization
309 .  -pc_factor_fill <nfill> - expected amount of fill in factored matrix compared to original matrix, nfill > 1
310 .  -pc_factor_nonzeros_along_diagonal - reorder the matrix before factorization to remove zeros from the diagonal,
311                                    this decreases the chance of getting a zero pivot
312 .  -pc_factor_mat_ordering_type <natural,nd,1wd,rcm,qmd> - set the row/column ordering of the factored matrix
313 .  -pc_factor_pivot_in_blocks - for block ILU(k) factorization, i.e. with BAIJ matrices with block size larger
314                              than 1 the diagonal blocks are factored with partial pivoting (this increases the
315                              stability of the ILU factorization
316 
317    Level: beginner
318 
319   Concepts: incomplete factorization
320 
321    Notes: Only implemented for some matrix formats. (for parallel see PCHYPRE for hypre's ILU)
322 
323           For BAIJ matrices this implements a point block ILU
324 
325           The "symmetric" application of this preconditioner is not actually symmetric since L is not transpose(U)
326           even when the matrix is not symmetric since the U stores the diagonals of the factorization.
327 
328           If you are using MATSEQAIJCUSPARSE matrices (or MATMPIAIJCUSPARESE matrices with block Jacobi), factorization
329           is never done on the GPU).
330 
331    References:
332    T. Dupont, R. Kendall, and H. Rachford. An approximate factorization procedure for solving
333    self-adjoint elliptic difference equations. SIAM J. Numer. Anal., 5:559--573, 1968.
334 
335    T.A. Oliphant. An implicit numerical method for solving two-dimensional time-dependent dif-
336    fusion problems. Quart. Appl. Math., 19:221--229, 1961.
337 
338    Review article: APPROXIMATE AND INCOMPLETE FACTORIZATIONS, TONY F. CHAN AND HENK A. VAN DER VORST
339       http://igitur-archive.library.uu.nl/math/2001-0621-115821/proc.pdf chapter in Parallel Numerical
340       Algorithms, edited by D. Keyes, A. Semah, V. Venkatakrishnan, ICASE/LaRC Interdisciplinary Series in
341       Science and Engineering, Kluwer, pp. 167--202.
342 
343 
344 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCSOR, MatOrderingType,
345            PCFactorSetZeroPivot(), PCFactorSetShiftSetType(), PCFactorSetAmount(),
346            PCFactorSetDropTolerance(),PCFactorSetFill(), PCFactorSetMatOrderingType(), PCFactorSetReuseOrdering(),
347            PCFactorSetLevels(), PCFactorSetUseInPlace(), PCFactorSetAllowDiagonalFill(), PCFactorSetPivotInBlocks()
348 
349 M*/
350 
351 #undef __FUNCT__
352 #define __FUNCT__ "PCCreate_ILU"
353 PETSC_EXTERN PetscErrorCode PCCreate_ILU(PC pc)
354 {
355   PetscErrorCode ierr;
356   PC_ILU         *ilu;
357 
358   PetscFunctionBegin;
359   ierr = PetscNewLog(pc,PC_ILU,&ilu);CHKERRQ(ierr);
360 
361   ((PC_Factor*)ilu)->fact               = 0;
362   ierr                                  = MatFactorInfoInitialize(&((PC_Factor*)ilu)->info);CHKERRQ(ierr);
363   ((PC_Factor*)ilu)->factortype         = MAT_FACTOR_ILU;
364   ((PC_Factor*)ilu)->info.levels        = 0.;
365   ((PC_Factor*)ilu)->info.fill          = 1.0;
366   ilu->col                              = 0;
367   ilu->row                              = 0;
368   ilu->inplace                          = PETSC_FALSE;
369   ierr                                  = PetscStrallocpy(MATSOLVERPETSC,&((PC_Factor*)ilu)->solvertype);CHKERRQ(ierr);
370   ierr                                  = PetscStrallocpy(MATORDERINGNATURAL,(char**)&((PC_Factor*)ilu)->ordering);CHKERRQ(ierr);
371   ilu->reuseordering                    = PETSC_FALSE;
372   ((PC_Factor*)ilu)->info.dt            = PETSC_DEFAULT;
373   ((PC_Factor*)ilu)->info.dtcount       = PETSC_DEFAULT;
374   ((PC_Factor*)ilu)->info.dtcol         = PETSC_DEFAULT;
375   ((PC_Factor*)ilu)->info.shifttype     = (PetscReal)MAT_SHIFT_INBLOCKS;
376   ((PC_Factor*)ilu)->info.shiftamount   = 100.0*PETSC_MACHINE_EPSILON;
377   ((PC_Factor*)ilu)->info.zeropivot     = 100.0*PETSC_MACHINE_EPSILON;
378   ((PC_Factor*)ilu)->info.pivotinblocks = 1.0;
379   ilu->reusefill                        = PETSC_FALSE;
380   ((PC_Factor*)ilu)->info.diagonal_fill = 0.0;
381   pc->data                              = (void*)ilu;
382 
383   pc->ops->reset               = PCReset_ILU;
384   pc->ops->destroy             = PCDestroy_ILU;
385   pc->ops->apply               = PCApply_ILU;
386   pc->ops->applytranspose      = PCApplyTranspose_ILU;
387   pc->ops->setup               = PCSetUp_ILU;
388   pc->ops->setfromoptions      = PCSetFromOptions_ILU;
389   pc->ops->getfactoredmatrix   = PCFactorGetMatrix_Factor;
390   pc->ops->view                = PCView_ILU;
391   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_ILU;
392   pc->ops->applysymmetricright = PCApplySymmetricRight_ILU;
393   pc->ops->applyrichardson     = 0;
394 
395   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetZeroPivot_C",PCFactorSetZeroPivot_Factor);CHKERRQ(ierr);
396   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetShiftType_C",PCFactorSetShiftType_Factor);CHKERRQ(ierr);
397   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetShiftAmount_C",PCFactorSetShiftAmount_Factor);CHKERRQ(ierr);
398   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorGetMatSolverPackage_C",PCFactorGetMatSolverPackage_Factor);CHKERRQ(ierr);
399   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetMatSolverPackage_C",PCFactorSetMatSolverPackage_Factor);CHKERRQ(ierr);
400   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetUpMatSolverPackage_C",PCFactorSetUpMatSolverPackage_Factor);CHKERRQ(ierr);
401   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetDropTolerance_C",PCFactorSetDropTolerance_ILU);CHKERRQ(ierr);
402   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetFill_C",PCFactorSetFill_Factor);CHKERRQ(ierr);
403   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetMatOrderingType_C",PCFactorSetMatOrderingType_Factor);CHKERRQ(ierr);
404   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetReuseOrdering_C",PCFactorSetReuseOrdering_ILU);CHKERRQ(ierr);
405   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetReuseFill_C",PCFactorSetReuseFill_ILU);CHKERRQ(ierr);
406   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetLevels_C",PCFactorSetLevels_Factor);CHKERRQ(ierr);
407   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorGetLevels_C",PCFactorGetLevels_Factor);CHKERRQ(ierr);
408   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetUseInPlace_C",PCFactorSetUseInPlace_ILU);CHKERRQ(ierr);
409   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetAllowDiagonalFill_C",PCFactorSetAllowDiagonalFill_Factor);CHKERRQ(ierr);
410   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorSetPivotInBlocks_C",PCFactorSetPivotInBlocks_Factor);CHKERRQ(ierr);
411   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCFactorReorderForNonzeroDiagonal_C",PCFactorReorderForNonzeroDiagonal_ILU);CHKERRQ(ierr);
412   PetscFunctionReturn(0);
413 }
414