xref: /petsc/src/ksp/pc/impls/factor/lu/lu.c (revision fd705b320d8d44969be9ca25a36dbdd35fbe8e12)
1 #define PETSCKSP_DLL
2 
3 /*
4    Defines a direct factorization preconditioner for any Mat implementation
5    Note: this need not be consided a preconditioner since it supplies
6          a direct solver.
7 */
8 
9 #include "private/pcimpl.h"                /*I "petscpc.h" I*/
10 #include "src/ksp/pc/impls/factor/lu/lu.h"
11 
12 EXTERN_C_BEGIN
13 #undef __FUNCT__
14 #define __FUNCT__ "PCFactorSetZeroPivot_LU"
15 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetZeroPivot_LU(PC pc,PetscReal z)
16 {
17   PC_LU *lu;
18 
19   PetscFunctionBegin;
20   lu                 = (PC_LU*)pc->data;
21   lu->info.zeropivot = z;
22   PetscFunctionReturn(0);
23 }
24 EXTERN_C_END
25 
26 EXTERN_C_BEGIN
27 #undef __FUNCT__
28 #define __FUNCT__ "PCFactorSetShiftNonzero_LU"
29 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftNonzero_LU(PC pc,PetscReal shift)
30 {
31   PC_LU *dir;
32 
33   PetscFunctionBegin;
34   dir = (PC_LU*)pc->data;
35   if (shift == (PetscReal) PETSC_DECIDE) {
36     dir->info.shiftnz = 1.e-12;
37   } else {
38     dir->info.shiftnz = shift;
39   }
40   PetscFunctionReturn(0);
41 }
42 EXTERN_C_END
43 
44 EXTERN_C_BEGIN
45 #undef __FUNCT__
46 #define __FUNCT__ "PCFactorSetShiftPd_LU"
47 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftPd_LU(PC pc,PetscTruth shift)
48 {
49   PC_LU *dir;
50 
51   PetscFunctionBegin;
52   dir = (PC_LU*)pc->data;
53   if (shift) {
54     dir->info.shift_fraction = 0.0;
55     dir->info.shiftpd = 1.0;
56   } else {
57     dir->info.shiftpd = 0.0;
58   }
59   PetscFunctionReturn(0);
60 }
61 EXTERN_C_END
62 
63 EXTERN_C_BEGIN
64 #undef __FUNCT__
65 #define __FUNCT__ "PCFactorReorderForNonzeroDiagonal_LU"
66 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorReorderForNonzeroDiagonal_LU(PC pc,PetscReal z)
67 {
68   PC_LU *lu = (PC_LU*)pc->data;
69 
70   PetscFunctionBegin;
71   lu->nonzerosalongdiagonal = PETSC_TRUE;
72   if (z == PETSC_DECIDE) {
73     lu->nonzerosalongdiagonaltol = 1.e-10;
74   } else {
75     lu->nonzerosalongdiagonaltol = z;
76   }
77   PetscFunctionReturn(0);
78 }
79 EXTERN_C_END
80 
81 EXTERN_C_BEGIN
82 #undef __FUNCT__
83 #define __FUNCT__ "PCFactorSetReuseOrdering_LU"
84 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetReuseOrdering_LU(PC pc,PetscTruth flag)
85 {
86   PC_LU *lu;
87 
88   PetscFunctionBegin;
89   lu                = (PC_LU*)pc->data;
90   lu->reuseordering = flag;
91   PetscFunctionReturn(0);
92 }
93 EXTERN_C_END
94 
95 EXTERN_C_BEGIN
96 #undef __FUNCT__
97 #define __FUNCT__ "PCFactorSetReuseFill_LU"
98 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetReuseFill_LU(PC pc,PetscTruth flag)
99 {
100   PC_LU *lu;
101 
102   PetscFunctionBegin;
103   lu = (PC_LU*)pc->data;
104   lu->reusefill = flag;
105   PetscFunctionReturn(0);
106 }
107 EXTERN_C_END
108 
109 #undef __FUNCT__
110 #define __FUNCT__ "PCSetFromOptions_LU"
111 static PetscErrorCode PCSetFromOptions_LU(PC pc)
112 {
113   PC_LU          *lu = (PC_LU*)pc->data;
114   PetscErrorCode ierr;
115   PetscTruth     flg,set;
116   char           tname[256];
117   PetscFList     ordlist;
118   PetscReal      tol;
119 
120   PetscFunctionBegin;
121   ierr = MatOrderingRegisterAll(PETSC_NULL);CHKERRQ(ierr);
122   ierr = PetscOptionsHead("LU options");CHKERRQ(ierr);
123     ierr = PetscOptionsName("-pc_factor_in_place","Form LU in the same memory as the matrix","PCFactorSetUseInPlace",&flg);CHKERRQ(ierr);
124     if (flg) {
125       ierr = PCFactorSetUseInPlace(pc);CHKERRQ(ierr);
126     }
127     ierr = PetscOptionsReal("-pc_factor_fill","Expected non-zeros in LU/non-zeros in matrix","PCFactorSetFill",lu->info.fill,&lu->info.fill,0);CHKERRQ(ierr);
128 
129     ierr = PetscOptionsName("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",&flg);CHKERRQ(ierr);
130     if (flg) {
131         ierr = PCFactorSetShiftNonzero(pc,(PetscReal) PETSC_DECIDE);CHKERRQ(ierr);
132     }
133     ierr = PetscOptionsReal("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",lu->info.shiftnz,&lu->info.shiftnz,0);CHKERRQ(ierr);
134     ierr = PetscOptionsName("-pc_factor_shift_positive_definite","Manteuffel shift applied to diagonal","PCFactorSetShiftPd",&flg);CHKERRQ(ierr);
135     if (flg) {
136       ierr = PCFactorSetShiftPd(pc,PETSC_TRUE);CHKERRQ(ierr);
137     }
138     ierr = PetscOptionsReal("-pc_factor_zeropivot","Pivot is considered zero if less than","PCFactorSetZeroPivot",lu->info.zeropivot,&lu->info.zeropivot,0);CHKERRQ(ierr);
139 
140     ierr = PetscOptionsName("-pc_factor_reuse_fill","Use fill from previous factorization","PCFactorSetReuseFill",&flg);CHKERRQ(ierr);
141     if (flg) {
142       ierr = PCFactorSetReuseFill(pc,PETSC_TRUE);CHKERRQ(ierr);
143     }
144     ierr = PetscOptionsName("-pc_factor_reuse_ordering","Reuse ordering from previous factorization","PCFactorSetReuseOrdering",&flg);CHKERRQ(ierr);
145     if (flg) {
146       ierr = PCFactorSetReuseOrdering(pc,PETSC_TRUE);CHKERRQ(ierr);
147     }
148 
149     ierr = MatGetOrderingList(&ordlist);CHKERRQ(ierr);
150     ierr = PetscOptionsList("-pc_factor_mat_ordering_type","Reordering to reduce nonzeros in LU","PCFactorSetMatOrderingType",ordlist,lu->ordering,tname,256,&flg);CHKERRQ(ierr);
151     if (flg) {
152       ierr = PCFactorSetMatOrderingType(pc,tname);CHKERRQ(ierr);
153     }
154 
155     ierr = PetscOptionsName("-pc_factor_nonzeros_along_diagonal","Reorder to remove zeros from diagonal","PCFactorReorderForNonzeroDiagonal",&flg);CHKERRQ(ierr);
156     if (flg) {
157       tol = PETSC_DECIDE;
158       ierr = PetscOptionsReal("-pc_factor_nonzeros_along_diagonal","Reorder to remove zeros from diagonal","PCFactorReorderForNonzeroDiagonal",lu->nonzerosalongdiagonaltol,&tol,0);CHKERRQ(ierr);
159       ierr = PCFactorReorderForNonzeroDiagonal(pc,tol);CHKERRQ(ierr);
160     }
161 
162     ierr = PetscOptionsReal("-pc_factor_pivoting","Pivoting tolerance (used only for some factorization)","PCFactorSetPivoting",lu->info.dtcol,&lu->info.dtcol,&flg);CHKERRQ(ierr);
163 
164     flg = lu->info.pivotinblocks ? PETSC_TRUE : PETSC_FALSE;
165     ierr = PetscOptionsTruth("-pc_factor_pivot_in_blocks","Pivot inside matrix blocks for BAIJ and SBAIJ","PCFactorSetPivotInBlocks",flg,&flg,&set);CHKERRQ(ierr);
166     if (set) {
167       ierr = PCFactorSetPivotInBlocks(pc,flg);CHKERRQ(ierr);
168     }
169   ierr = PetscOptionsTail();CHKERRQ(ierr);
170   PetscFunctionReturn(0);
171 }
172 
173 #undef __FUNCT__
174 #define __FUNCT__ "PCView_LU"
175 static PetscErrorCode PCView_LU(PC pc,PetscViewer viewer)
176 {
177   PC_LU          *lu = (PC_LU*)pc->data;
178   PetscErrorCode ierr;
179   PetscTruth     iascii,isstring;
180 
181   PetscFunctionBegin;
182   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
183   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr);
184   if (iascii) {
185 
186     if (lu->inplace) {ierr = PetscViewerASCIIPrintf(viewer,"  LU: in-place factorization\n");CHKERRQ(ierr);}
187     else             {ierr = PetscViewerASCIIPrintf(viewer,"  LU: out-of-place factorization\n");CHKERRQ(ierr);}
188     ierr = PetscViewerASCIIPrintf(viewer,"    matrix ordering: %s\n",lu->ordering);CHKERRQ(ierr);
189     ierr = PetscViewerASCIIPrintf(viewer,"  LU: tolerance for zero pivot %G\n",lu->info.zeropivot);CHKERRQ(ierr);
190     if (lu->info.shiftpd) {ierr = PetscViewerASCIIPrintf(viewer,"  LU: using Manteuffel shift\n");CHKERRQ(ierr);}
191     if (lu->fact) {
192       ierr = PetscViewerASCIIPrintf(viewer,"  LU: factor fill ratio needed %G\n",lu->actualfill);CHKERRQ(ierr);
193       ierr = PetscViewerASCIIPrintf(viewer,"       Factored matrix follows\n");CHKERRQ(ierr);
194       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
195       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
196       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
197       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
198       ierr = MatView(lu->fact,viewer);CHKERRQ(ierr);
199       ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
200       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
201       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
202       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
203     }
204     if (lu->reusefill)    {ierr = PetscViewerASCIIPrintf(viewer,"       Reusing fill from past factorization\n");CHKERRQ(ierr);}
205     if (lu->reuseordering) {ierr = PetscViewerASCIIPrintf(viewer,"       Reusing reordering from past factorization\n");CHKERRQ(ierr);}
206   } else if (isstring) {
207     ierr = PetscViewerStringSPrintf(viewer," order=%s",lu->ordering);CHKERRQ(ierr);CHKERRQ(ierr);
208   } else {
209     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCLU",((PetscObject)viewer)->type_name);
210   }
211   PetscFunctionReturn(0);
212 }
213 
214 #undef __FUNCT__
215 #define __FUNCT__ "PCFactorGetMatrix_LU"
216 static PetscErrorCode PCFactorGetMatrix_LU(PC pc,Mat *mat)
217 {
218   PC_LU *dir = (PC_LU*)pc->data;
219 
220   PetscFunctionBegin;
221   if (!dir->fact) SETERRQ(PETSC_ERR_ORDER,"Matrix not yet factored; call after KSPSetUp() or PCSetUp()");
222   *mat = dir->fact;
223   PetscFunctionReturn(0);
224 }
225 
226 #undef __FUNCT__
227 #define __FUNCT__ "PCSetUp_LU"
228 static PetscErrorCode PCSetUp_LU(PC pc)
229 {
230   PetscErrorCode ierr;
231   PC_LU          *dir = (PC_LU*)pc->data;
232 
233   PetscFunctionBegin;
234   if (dir->reusefill && pc->setupcalled) dir->info.fill = dir->actualfill;
235 
236   if (dir->inplace) {
237     if (dir->row && dir->col && dir->row != dir->col) {ierr = ISDestroy(dir->row);CHKERRQ(ierr);}
238     if (dir->col) {ierr = ISDestroy(dir->col);CHKERRQ(ierr);}
239     ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
240     if (dir->row) {
241       ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);
242       ierr = PetscLogObjectParent(pc,dir->col);CHKERRQ(ierr);
243     }
244     ierr = MatLUFactor(pc->pmat,dir->row,dir->col,&dir->info);CHKERRQ(ierr);
245     dir->fact = pc->pmat;
246   } else {
247     MatInfo info;
248     if (!pc->setupcalled) {
249       ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
250       if (dir->nonzerosalongdiagonal) {
251         ierr = MatReorderForNonzeroDiagonal(pc->pmat,dir->nonzerosalongdiagonaltol,dir->row,dir->col);CHKERRQ(ierr);
252       }
253       if (dir->row) {
254         ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);
255         ierr = PetscLogObjectParent(pc,dir->col);CHKERRQ(ierr);
256       }
257       ierr = MatLUFactorSymbolic(pc->pmat,dir->row,dir->col,&dir->info,&dir->fact);CHKERRQ(ierr);
258       ierr = MatGetInfo(dir->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
259       dir->actualfill = info.fill_ratio_needed;
260       ierr = PetscLogObjectParent(pc,dir->fact);CHKERRQ(ierr);
261     } else if (pc->flag != SAME_NONZERO_PATTERN) {
262       if (!dir->reuseordering) {
263         if (dir->row && dir->col && dir->row != dir->col) {ierr = ISDestroy(dir->row);CHKERRQ(ierr);}
264         if (dir->col) {ierr = ISDestroy(dir->col);CHKERRQ(ierr);}
265         ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
266         if (dir->nonzerosalongdiagonal) {
267           ierr = MatReorderForNonzeroDiagonal(pc->pmat,dir->nonzerosalongdiagonaltol,dir->row,dir->col);CHKERRQ(ierr);
268         }
269         if (dir->row) {
270           ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);
271           ierr = PetscLogObjectParent(pc,dir->col);CHKERRQ(ierr);
272         }
273       }
274       ierr = MatDestroy(dir->fact);CHKERRQ(ierr);
275       ierr = MatLUFactorSymbolic(pc->pmat,dir->row,dir->col,&dir->info,&dir->fact);CHKERRQ(ierr);
276       ierr = MatGetInfo(dir->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
277       dir->actualfill = info.fill_ratio_needed;
278       ierr = PetscLogObjectParent(pc,dir->fact);CHKERRQ(ierr);
279     }
280     ierr = MatLUFactorNumeric(pc->pmat,&dir->info,&dir->fact);CHKERRQ(ierr);
281   }
282   PetscFunctionReturn(0);
283 }
284 
285 #undef __FUNCT__
286 #define __FUNCT__ "PCDestroy_LU"
287 static PetscErrorCode PCDestroy_LU(PC pc)
288 {
289   PC_LU          *dir = (PC_LU*)pc->data;
290   PetscErrorCode ierr;
291 
292   PetscFunctionBegin;
293   if (!dir->inplace && dir->fact) {ierr = MatDestroy(dir->fact);CHKERRQ(ierr);}
294   if (dir->row && dir->col && dir->row != dir->col) {ierr = ISDestroy(dir->row);CHKERRQ(ierr);}
295   if (dir->col) {ierr = ISDestroy(dir->col);CHKERRQ(ierr);}
296   ierr = PetscStrfree(dir->ordering);CHKERRQ(ierr);
297   ierr = PetscFree(dir);CHKERRQ(ierr);
298   PetscFunctionReturn(0);
299 }
300 
301 #undef __FUNCT__
302 #define __FUNCT__ "PCApply_LU"
303 static PetscErrorCode PCApply_LU(PC pc,Vec x,Vec y)
304 {
305   PC_LU          *dir = (PC_LU*)pc->data;
306   PetscErrorCode ierr;
307 
308   PetscFunctionBegin;
309   if (dir->inplace) {ierr = MatSolve(pc->pmat,x,y);CHKERRQ(ierr);}
310   else              {ierr = MatSolve(dir->fact,x,y);CHKERRQ(ierr);}
311   PetscFunctionReturn(0);
312 }
313 
314 #undef __FUNCT__
315 #define __FUNCT__ "PCApplyTranspose_LU"
316 static PetscErrorCode PCApplyTranspose_LU(PC pc,Vec x,Vec y)
317 {
318   PC_LU          *dir = (PC_LU*)pc->data;
319   PetscErrorCode ierr;
320 
321   PetscFunctionBegin;
322   if (dir->inplace) {ierr = MatSolveTranspose(pc->pmat,x,y);CHKERRQ(ierr);}
323   else              {ierr = MatSolveTranspose(dir->fact,x,y);CHKERRQ(ierr);}
324   PetscFunctionReturn(0);
325 }
326 
327 /* -----------------------------------------------------------------------------------*/
328 
329 EXTERN_C_BEGIN
330 #undef __FUNCT__
331 #define __FUNCT__ "PCFactorSetFill_LU"
332 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetFill_LU(PC pc,PetscReal fill)
333 {
334   PC_LU *dir;
335 
336   PetscFunctionBegin;
337   dir = (PC_LU*)pc->data;
338   dir->info.fill = fill;
339   PetscFunctionReturn(0);
340 }
341 EXTERN_C_END
342 
343 EXTERN_C_BEGIN
344 #undef __FUNCT__
345 #define __FUNCT__ "PCFactorSetUseInPlace_LU"
346 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetUseInPlace_LU(PC pc)
347 {
348   PC_LU *dir;
349 
350   PetscFunctionBegin;
351   dir = (PC_LU*)pc->data;
352   dir->inplace = PETSC_TRUE;
353   PetscFunctionReturn(0);
354 }
355 EXTERN_C_END
356 
357 EXTERN_C_BEGIN
358 #undef __FUNCT__
359 #define __FUNCT__ "PCFactorSetMatOrderingType_LU"
360 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetMatOrderingType_LU(PC pc,MatOrderingType ordering)
361 {
362   PC_LU          *dir = (PC_LU*)pc->data;
363   PetscErrorCode ierr;
364 
365   PetscFunctionBegin;
366   ierr = PetscStrfree(dir->ordering);CHKERRQ(ierr);
367   ierr = PetscStrallocpy(ordering,&dir->ordering);CHKERRQ(ierr);
368   PetscFunctionReturn(0);
369 }
370 EXTERN_C_END
371 
372 EXTERN_C_BEGIN
373 #undef __FUNCT__
374 #define __FUNCT__ "PCFactorSetPivoting_LU"
375 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetPivoting_LU(PC pc,PetscReal dtcol)
376 {
377   PC_LU *dir = (PC_LU*)pc->data;
378 
379   PetscFunctionBegin;
380   if (dtcol < 0.0 || dtcol > 1.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Column pivot tolerance is %G must be between 0 and 1",dtcol);
381   dir->info.dtcol = dtcol;
382   PetscFunctionReturn(0);
383 }
384 EXTERN_C_END
385 
386 EXTERN_C_BEGIN
387 #undef __FUNCT__
388 #define __FUNCT__ "PCFactorSetPivotInBlocks_LU"
389 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetPivotInBlocks_LU(PC pc,PetscTruth pivot)
390 {
391   PC_LU *dir = (PC_LU*)pc->data;
392 
393   PetscFunctionBegin;
394   dir->info.pivotinblocks = pivot ? 1.0 : 0.0;
395   PetscFunctionReturn(0);
396 }
397 EXTERN_C_END
398 
399 /* -----------------------------------------------------------------------------------*/
400 
401 #undef __FUNCT__
402 #define __FUNCT__ "PCFactorReorderForNonzeroDiagonal"
403 /*@
404    PCFactorReorderForNonzeroDiagonal - reorders rows/columns of matrix to remove zeros from diagonal
405 
406    Collective on PC
407 
408    Input Parameters:
409 +  pc - the preconditioner context
410 -  tol - diagonal entries smaller than this in absolute value are considered zero
411 
412    Options Database Key:
413 .  -pc_factor_nonzeros_along_diagonal
414 
415    Level: intermediate
416 
417 .keywords: PC, set, factorization, direct, fill
418 
419 .seealso: PCFactorSetFill(), PCFactorSetShiftNonzero(), PCFactorSetZeroPivot(), MatReorderForNonzeroDiagonal()
420 @*/
421 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorReorderForNonzeroDiagonal(PC pc,PetscReal rtol)
422 {
423   PetscErrorCode ierr,(*f)(PC,PetscReal);
424 
425   PetscFunctionBegin;
426   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
427   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFactorReorderForNonzeroDiagonal_C",(void (**)(void))&f);CHKERRQ(ierr);
428   if (f) {
429     ierr = (*f)(pc,rtol);CHKERRQ(ierr);
430   }
431   PetscFunctionReturn(0);
432 }
433 
434 #undef __FUNCT__
435 #define __FUNCT__ "PCFactorSetFill"
436 /*@
437    PCFactorSetFill - Indicate the amount of fill you expect in the factored matrix,
438    fill = number nonzeros in factor/number nonzeros in original matrix.
439 
440    Collective on PC
441 
442    Input Parameters:
443 +  pc - the preconditioner context
444 -  fill - amount of expected fill
445 
446    Options Database Key:
447 .  -pc_factor_fill <fill> - Sets fill amount
448 
449    Level: intermediate
450 
451    Note:
452    For sparse matrix factorizations it is difficult to predict how much
453    fill to expect. By running with the option -info PETSc will print the
454    actual amount of fill used; allowing you to set the value accurately for
455    future runs. Default PETSc uses a value of 5.0
456 
457 .keywords: PC, set, factorization, direct, fill
458 
459 @*/
460 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetFill(PC pc,PetscReal fill)
461 {
462   PetscErrorCode ierr,(*f)(PC,PetscReal);
463 
464   PetscFunctionBegin;
465   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
466   if (fill < 1.0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Fill factor cannot be less then 1.0");
467   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFactorSetFill_C",(void (**)(void))&f);CHKERRQ(ierr);
468   if (f) {
469     ierr = (*f)(pc,fill);CHKERRQ(ierr);
470   }
471   PetscFunctionReturn(0);
472 }
473 
474 #undef __FUNCT__
475 #define __FUNCT__ "PCFactorSetUseInPlace"
476 /*@
477    PCFactorSetUseInPlace - Tells the system to do an in-place factorization.
478    For dense matrices, this enables the solution of much larger problems.
479    For sparse matrices the factorization cannot be done truly in-place
480    so this does not save memory during the factorization, but after the matrix
481    is factored, the original unfactored matrix is freed, thus recovering that
482    space.
483 
484    Collective on PC
485 
486    Input Parameters:
487 .  pc - the preconditioner context
488 
489    Options Database Key:
490 .  -pc_factor_in_place - Activates in-place factorization
491 
492    Notes:
493    PCFactorSetUseInplace() can only be used with the KSP method KSPPREONLY or when
494    a different matrix is provided for the multiply and the preconditioner in
495    a call to KSPSetOperators().
496    This is because the Krylov space methods require an application of the
497    matrix multiplication, which is not possible here because the matrix has
498    been factored in-place, replacing the original matrix.
499 
500    Level: intermediate
501 
502 .keywords: PC, set, factorization, direct, inplace, in-place, LU
503 
504 .seealso: PCILUSetUseInPlace()
505 @*/
506 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetUseInPlace(PC pc)
507 {
508   PetscErrorCode ierr,(*f)(PC);
509 
510   PetscFunctionBegin;
511   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
512   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFactorSetUseInPlace_C",(void (**)(void))&f);CHKERRQ(ierr);
513   if (f) {
514     ierr = (*f)(pc);CHKERRQ(ierr);
515   }
516   PetscFunctionReturn(0);
517 }
518 
519 #undef __FUNCT__
520 #define __FUNCT__ "PCFactorSetMatOrderingType"
521 /*@C
522     PCFactorSetMatOrderingType - Sets the ordering routine (to reduce fill) to
523     be used in the LU factorization.
524 
525     Collective on PC
526 
527     Input Parameters:
528 +   pc - the preconditioner context
529 -   ordering - the matrix ordering name, for example, MATORDERING_ND or MATORDERING_RCM
530 
531     Options Database Key:
532 .   -pc_factor_mat_ordering_type <nd,rcm,...> - Sets ordering routine
533 
534     Level: intermediate
535 
536     Notes: nested dissection is used by default
537 
538     For Cholesky and ICC and the SBAIJ format reorderings are not available,
539     since only the upper triangular part of the matrix is stored. You can use the
540     SeqAIJ format in this case to get reorderings.
541 
542 @*/
543 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetMatOrderingType(PC pc,MatOrderingType ordering)
544 {
545   PetscErrorCode ierr,(*f)(PC,MatOrderingType);
546 
547   PetscFunctionBegin;
548   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFactorSetMatOrderingType_C",(void (**)(void))&f);CHKERRQ(ierr);
549   if (f) {
550     ierr = (*f)(pc,ordering);CHKERRQ(ierr);
551   }
552   PetscFunctionReturn(0);
553 }
554 
555 #undef __FUNCT__
556 #define __FUNCT__ "PCFactorSetPivoting"
557 /*@
558     PCFactorSetPivoting - Determines when pivoting is done during LU.
559       For PETSc dense matrices column pivoting is always done, for PETSc sparse matrices
560       it is never done. For the Matlab and SuperLU factorization this is used.
561 
562     Collective on PC
563 
564     Input Parameters:
565 +   pc - the preconditioner context
566 -   dtcol - 0.0 implies no pivoting, 1.0 complete pivoting (slower, requires more memory but more stable)
567 
568     Options Database Key:
569 .   -pc_factor_pivoting <dtcol>
570 
571     Level: intermediate
572 
573 .seealso: PCILUSetMatOrdering(), PCFactorSetPivotInBlocks()
574 @*/
575 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetPivoting(PC pc,PetscReal dtcol)
576 {
577   PetscErrorCode ierr,(*f)(PC,PetscReal);
578 
579   PetscFunctionBegin;
580   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFactorSetPivoting_C",(void (**)(void))&f);CHKERRQ(ierr);
581   if (f) {
582     ierr = (*f)(pc,dtcol);CHKERRQ(ierr);
583   }
584   PetscFunctionReturn(0);
585 }
586 
587 #undef __FUNCT__
588 #define __FUNCT__ "PCFactorSetPivotInBlocks"
589 /*@
590     PCFactorSetPivotInBlocks - Determines if pivoting is done while factoring each block
591       with BAIJ or SBAIJ matrices
592 
593     Collective on PC
594 
595     Input Parameters:
596 +   pc - the preconditioner context
597 -   pivot - PETSC_TRUE or PETSC_FALSE
598 
599     Options Database Key:
600 .   -pc_factor_pivot_in_blocks <true,false>
601 
602     Level: intermediate
603 
604 .seealso: PCILUSetMatOrdering(), PCFactorSetPivoting()
605 @*/
606 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetPivotInBlocks(PC pc,PetscTruth pivot)
607 {
608   PetscErrorCode ierr,(*f)(PC,PetscTruth);
609 
610   PetscFunctionBegin;
611   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCFactorSetPivotInBlocks_C",(void (**)(void))&f);CHKERRQ(ierr);
612   if (f) {
613     ierr = (*f)(pc,pivot);CHKERRQ(ierr);
614   }
615   PetscFunctionReturn(0);
616 }
617 
618 /* ------------------------------------------------------------------------ */
619 
620 /*MC
621    PCLU - Uses a direct solver, based on LU factorization, as a preconditioner
622 
623    Options Database Keys:
624 +  -pc_factor_reuse_ordering - Activate PCFactorSetReuseOrdering()
625 .  -pc_factor_reuse_fill - Activates PCFactorSetReuseFill()
626 .  -pc_factor_fill <fill> - Sets fill amount
627 .  -pc_factor_in_place - Activates in-place factorization
628 .  -pc_factor_mat_ordering_type <nd,rcm,...> - Sets ordering routine
629 .  -pc_factor_pivot_in_blocks <true,false> - allow pivoting within the small blocks during factorization (may increase
630                                          stability of factorization.
631 .  -pc_factor_shift_nonzero <shift> - Sets shift amount or PETSC_DECIDE for the default
632 .  -pc_factor_shift_positive_definite [PETSC_TRUE/PETSC_FALSE] - Activate/Deactivate PCFactorSetShiftPd(); the value
633         is optional with PETSC_TRUE being the default
634 -   -pc_factor_nonzeros_along_diagonal - permutes the rows and columns to try to put nonzero value along the
635         diagonal.
636 
637    Notes: Not all options work for all matrix formats
638           Run with -help to see additional options for particular matrix formats or factorization
639           algorithms
640 
641    Level: beginner
642 
643    Concepts: LU factorization, direct solver
644 
645    Notes: Usually this will compute an "exact" solution in one iteration and does
646           not need a Krylov method (i.e. you can use -ksp_type preonly, or
647           KSPSetType(ksp,KSPPREONLY) for the Krylov method
648 
649 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
650            PCILU, PCCHOLESKY, PCICC, PCFactorSetReuseOrdering(), PCFactorSetReuseFill(), PCFactorGetMatrix(),
651            PCFactorSetFill(), PCFactorSetUseInPlace(), PCFactorSetMatOrderingType(), PCFactorSetPivoting(),
652            PCFactorSetPivotingInBlocks(),PCFactorSetShiftNonzero(),PCFactorSetShiftPd(), PCFactorReorderForNonzeroDiagonal()
653 M*/
654 
655 EXTERN_C_BEGIN
656 #undef __FUNCT__
657 #define __FUNCT__ "PCCreate_LU"
658 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_LU(PC pc)
659 {
660   PetscErrorCode ierr;
661   PetscMPIInt    size;
662   PC_LU          *dir;
663 
664   PetscFunctionBegin;
665   ierr = PetscNewLog(pc,PC_LU,&dir);CHKERRQ(ierr);
666 
667   ierr = MatFactorInfoInitialize(&dir->info);CHKERRQ(ierr);
668   dir->fact                  = 0;
669   dir->inplace               = PETSC_FALSE;
670   dir->nonzerosalongdiagonal = PETSC_FALSE;
671 
672   dir->info.fill           = 5.0;
673   dir->info.dtcol          = 1.e-6; /* default to pivoting; this is only thing PETSc LU supports */
674   dir->info.shiftnz        = 0.0;
675   dir->info.zeropivot      = 1.e-12;
676   dir->info.pivotinblocks  = 1.0;
677   dir->info.shiftpd        = 0.0; /* false */
678   dir->info.shift_fraction = 0.0;
679   dir->col                 = 0;
680   dir->row                 = 0;
681   ierr = MPI_Comm_size(((PetscObject)pc)->comm,&size);CHKERRQ(ierr);
682   if (size == 1) {
683     ierr = PetscStrallocpy(MATORDERING_ND,&dir->ordering);CHKERRQ(ierr);
684   } else {
685     ierr = PetscStrallocpy(MATORDERING_NATURAL,&dir->ordering);CHKERRQ(ierr);
686   }
687   dir->reusefill        = PETSC_FALSE;
688   dir->reuseordering    = PETSC_FALSE;
689   pc->data              = (void*)dir;
690 
691   pc->ops->destroy           = PCDestroy_LU;
692   pc->ops->apply             = PCApply_LU;
693   pc->ops->applytranspose    = PCApplyTranspose_LU;
694   pc->ops->setup             = PCSetUp_LU;
695   pc->ops->setfromoptions    = PCSetFromOptions_LU;
696   pc->ops->view              = PCView_LU;
697   pc->ops->applyrichardson   = 0;
698   pc->ops->getfactoredmatrix = PCFactorGetMatrix_LU;
699 
700   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_LU",
701                     PCFactorSetZeroPivot_LU);CHKERRQ(ierr);
702   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftNonzero_C","PCFactorSetShiftNonzero_LU",
703                     PCFactorSetShiftNonzero_LU);CHKERRQ(ierr);
704   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftPd_C","PCFactorSetShiftPd_LU",
705                     PCFactorSetShiftPd_LU);CHKERRQ(ierr);
706 
707   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetFill_C","PCFactorSetFill_LU",
708                     PCFactorSetFill_LU);CHKERRQ(ierr);
709   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetUseInPlace_C","PCFactorSetUseInPlace_LU",
710                     PCFactorSetUseInPlace_LU);CHKERRQ(ierr);
711   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetMatOrderingType_C","PCFactorSetMatOrderingType_LU",
712                     PCFactorSetMatOrderingType_LU);CHKERRQ(ierr);
713   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetReuseOrdering_C","PCFactorSetReuseOrdering_LU",
714                     PCFactorSetReuseOrdering_LU);CHKERRQ(ierr);
715   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetReuseFill_C","PCFactorSetReuseFill_LU",
716                     PCFactorSetReuseFill_LU);CHKERRQ(ierr);
717   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetPivoting_C","PCFactorSetPivoting_LU",
718                     PCFactorSetPivoting_LU);CHKERRQ(ierr);
719   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetPivotInBlocks_C","PCFactorSetPivotInBlocks_LU",
720                     PCFactorSetPivotInBlocks_LU);CHKERRQ(ierr);
721   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorReorderForNonzeroDiagonal_C","PCFactorReorderForNonzeroDiagonal_LU",
722                     PCFactorReorderForNonzeroDiagonal_LU);CHKERRQ(ierr);
723   PetscFunctionReturn(0);
724 }
725 EXTERN_C_END
726