xref: /petsc/src/ksp/pc/impls/factor/lu/lu.c (revision f68b968ce39302dfa79eb1a6cfa1998ce074e829)
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__ "PCLUReorderForNonzeroDiagonal_LU"
66 PetscErrorCode PETSCKSP_DLLEXPORT PCLUReorderForNonzeroDiagonal_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__ "PCLUSetReuseOrdering_LU"
84 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetReuseOrdering_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__ "PCLUSetReuseFill_LU"
98 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetReuseFill_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_lu_in_place","Form LU in the same memory as the matrix","PCLUSetUseInPlace",&flg);CHKERRQ(ierr);
124     if (flg) {
125       ierr = PCLUSetUseInPlace(pc);CHKERRQ(ierr);
126     }
127     ierr = PetscOptionsReal("-pc_lu_fill","Expected non-zeros in LU/non-zeros in matrix","PCLUSetFill",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_lu_reuse_fill","Use fill from previous factorization","PCLUSetReuseFill",&flg);CHKERRQ(ierr);
141     if (flg) {
142       ierr = PCLUSetReuseFill(pc,PETSC_TRUE);CHKERRQ(ierr);
143     }
144     ierr = PetscOptionsName("-pc_lu_reuse_ordering","Reuse ordering from previous factorization","PCLUSetReuseOrdering",&flg);CHKERRQ(ierr);
145     if (flg) {
146       ierr = PCLUSetReuseOrdering(pc,PETSC_TRUE);CHKERRQ(ierr);
147     }
148 
149     ierr = MatGetOrderingList(&ordlist);CHKERRQ(ierr);
150     ierr = PetscOptionsList("-pc_lu_mat_ordering_type","Reordering to reduce nonzeros in LU","PCLUSetMatOrdering",ordlist,lu->ordering,tname,256,&flg);CHKERRQ(ierr);
151     if (flg) {
152       ierr = PCLUSetMatOrdering(pc,tname);CHKERRQ(ierr);
153     }
154 
155     ierr = PetscOptionsName("-pc_lu_nonzeros_along_diagonal","Reorder to remove zeros from diagonal","PCLUReorderForNonzeroDiagonal",&flg);CHKERRQ(ierr);
156     if (flg) {
157       tol = PETSC_DECIDE;
158       ierr = PetscOptionsReal("-pc_lu_nonzeros_along_diagonal","Reorder to remove zeros from diagonal","PCLUReorderForNonzeroDiagonal",lu->nonzerosalongdiagonaltol,&tol,0);CHKERRQ(ierr);
159       ierr = PCLUReorderForNonzeroDiagonal(pc,tol);CHKERRQ(ierr);
160     }
161 
162     ierr = PetscOptionsReal("-pc_lu_pivoting","Pivoting tolerance (used only for some factorization)","PCLUSetPivoting",lu->info.dtcol,&lu->info.dtcol,&flg);CHKERRQ(ierr);
163 
164     flg = lu->info.pivotinblocks ? PETSC_TRUE : PETSC_FALSE;
165     ierr = PetscOptionsTruth("-pc_lu_pivot_in_blocks","Pivot inside matrix blocks for BAIJ and SBAIJ","PCLUSetPivotInBlocks",flg,&flg,&set);CHKERRQ(ierr);
166     if (set) {
167       ierr = PCLUSetPivotInBlocks(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     MatInfo info;
186 
187     if (lu->inplace) {ierr = PetscViewerASCIIPrintf(viewer,"  LU: in-place factorization\n");CHKERRQ(ierr);}
188     else             {ierr = PetscViewerASCIIPrintf(viewer,"  LU: out-of-place factorization\n");CHKERRQ(ierr);}
189     ierr = PetscViewerASCIIPrintf(viewer,"    matrix ordering: %s\n",lu->ordering);CHKERRQ(ierr);
190     ierr = PetscViewerASCIIPrintf(viewer,"  LU: tolerance for zero pivot %g\n",lu->info.zeropivot);CHKERRQ(ierr);
191     if (lu->info.shiftpd) {ierr = PetscViewerASCIIPrintf(viewer,"  LU: using Manteuffel shift\n");CHKERRQ(ierr);}
192     if (lu->fact) {
193       ierr = MatGetInfo(lu->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
194       ierr = PetscViewerASCIIPrintf(viewer,"    LU nonzeros %g\n",info.nz_used);CHKERRQ(ierr);
195       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_FACTOR_INFO);CHKERRQ(ierr);
196       ierr = MatView(lu->fact,viewer);CHKERRQ(ierr);
197       ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
198     }
199     if (lu->reusefill)    {ierr = PetscViewerASCIIPrintf(viewer,"       Reusing fill from past factorization\n");CHKERRQ(ierr);}
200     if (lu->reuseordering) {ierr = PetscViewerASCIIPrintf(viewer,"       Reusing reordering from past factorization\n");CHKERRQ(ierr);}
201   } else if (isstring) {
202     ierr = PetscViewerStringSPrintf(viewer," order=%s",lu->ordering);CHKERRQ(ierr);CHKERRQ(ierr);
203   } else {
204     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCLU",((PetscObject)viewer)->type_name);
205   }
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "PCGetFactoredMatrix_LU"
211 static PetscErrorCode PCGetFactoredMatrix_LU(PC pc,Mat *mat)
212 {
213   PC_LU *dir = (PC_LU*)pc->data;
214 
215   PetscFunctionBegin;
216   if (!dir->fact) SETERRQ(PETSC_ERR_ORDER,"Matrix not yet factored; call after KSPSetUp() or PCSetUp()");
217   *mat = dir->fact;
218   PetscFunctionReturn(0);
219 }
220 
221 #undef __FUNCT__
222 #define __FUNCT__ "PCSetUp_LU"
223 static PetscErrorCode PCSetUp_LU(PC pc)
224 {
225   PetscErrorCode ierr;
226   PC_LU          *dir = (PC_LU*)pc->data;
227 
228   PetscFunctionBegin;
229   if (dir->reusefill && pc->setupcalled) dir->info.fill = dir->actualfill;
230 
231   if (dir->inplace) {
232     if (dir->row && dir->col && dir->row != dir->col) {ierr = ISDestroy(dir->row);CHKERRQ(ierr);}
233     if (dir->col) {ierr = ISDestroy(dir->col);CHKERRQ(ierr);}
234     ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
235     if (dir->row) {ierr = PetscLogObjectParent(pc,dir->row); CHKERRQ(ierr); ierr = PetscLogObjectParent(pc,dir->col);CHKERRQ(ierr);}
236     ierr = MatLUFactor(pc->pmat,dir->row,dir->col,&dir->info);CHKERRQ(ierr);
237     dir->fact = pc->pmat;
238   } else {
239     MatInfo info;
240     if (!pc->setupcalled) {
241       ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
242       if (dir->nonzerosalongdiagonal) {
243         ierr = MatReorderForNonzeroDiagonal(pc->pmat,dir->nonzerosalongdiagonaltol,dir->row,dir->col);CHKERRQ(ierr);
244       }
245       if (dir->row) {ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr); ierr = PetscLogObjectParent(pc,dir->col);CHKERRQ(ierr);}
246       ierr = MatLUFactorSymbolic(pc->pmat,dir->row,dir->col,&dir->info,&dir->fact);CHKERRQ(ierr);
247       ierr = MatGetInfo(dir->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
248       dir->actualfill = info.fill_ratio_needed;
249       ierr = PetscLogObjectParent(pc,dir->fact);CHKERRQ(ierr);
250     } else if (pc->flag != SAME_NONZERO_PATTERN) {
251       if (!dir->reuseordering) {
252         if (dir->row && dir->col && dir->row != dir->col) {ierr = ISDestroy(dir->row);CHKERRQ(ierr);}
253         if (dir->col) {ierr = ISDestroy(dir->col);CHKERRQ(ierr);}
254         ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
255         if (dir->nonzerosalongdiagonal) {
256          ierr = MatReorderForNonzeroDiagonal(pc->pmat,dir->nonzerosalongdiagonaltol,dir->row,dir->col);CHKERRQ(ierr);
257         }
258         if (dir->row) {ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);ierr =  PetscLogObjectParent(pc,dir->col);CHKERRQ(ierr);}
259       }
260       ierr = MatDestroy(dir->fact);CHKERRQ(ierr);
261       ierr = MatLUFactorSymbolic(pc->pmat,dir->row,dir->col,&dir->info,&dir->fact);CHKERRQ(ierr);
262       ierr = MatGetInfo(dir->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
263       dir->actualfill = info.fill_ratio_needed;
264       ierr = PetscLogObjectParent(pc,dir->fact);CHKERRQ(ierr);
265     }
266     ierr = MatLUFactorNumeric(pc->pmat,&dir->info,&dir->fact);CHKERRQ(ierr);
267   }
268   PetscFunctionReturn(0);
269 }
270 
271 #undef __FUNCT__
272 #define __FUNCT__ "PCDestroy_LU"
273 static PetscErrorCode PCDestroy_LU(PC pc)
274 {
275   PC_LU          *dir = (PC_LU*)pc->data;
276   PetscErrorCode ierr;
277 
278   PetscFunctionBegin;
279   if (!dir->inplace && dir->fact) {ierr = MatDestroy(dir->fact);CHKERRQ(ierr);}
280   if (dir->row && dir->col && dir->row != dir->col) {ierr = ISDestroy(dir->row);CHKERRQ(ierr);}
281   if (dir->col) {ierr = ISDestroy(dir->col);CHKERRQ(ierr);}
282   ierr = PetscStrfree(dir->ordering);CHKERRQ(ierr);
283   ierr = PetscFree(dir);CHKERRQ(ierr);
284   PetscFunctionReturn(0);
285 }
286 
287 #undef __FUNCT__
288 #define __FUNCT__ "PCApply_LU"
289 static PetscErrorCode PCApply_LU(PC pc,Vec x,Vec y)
290 {
291   PC_LU          *dir = (PC_LU*)pc->data;
292   PetscErrorCode ierr;
293 
294   PetscFunctionBegin;
295   if (dir->inplace) {ierr = MatSolve(pc->pmat,x,y);CHKERRQ(ierr);}
296   else              {ierr = MatSolve(dir->fact,x,y);CHKERRQ(ierr);}
297   PetscFunctionReturn(0);
298 }
299 
300 #undef __FUNCT__
301 #define __FUNCT__ "PCApplyTranspose_LU"
302 static PetscErrorCode PCApplyTranspose_LU(PC pc,Vec x,Vec y)
303 {
304   PC_LU          *dir = (PC_LU*)pc->data;
305   PetscErrorCode ierr;
306 
307   PetscFunctionBegin;
308   if (dir->inplace) {ierr = MatSolveTranspose(pc->pmat,x,y);CHKERRQ(ierr);}
309   else              {ierr = MatSolveTranspose(dir->fact,x,y);CHKERRQ(ierr);}
310   PetscFunctionReturn(0);
311 }
312 
313 /* -----------------------------------------------------------------------------------*/
314 
315 EXTERN_C_BEGIN
316 #undef __FUNCT__
317 #define __FUNCT__ "PCLUSetFill_LU"
318 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetFill_LU(PC pc,PetscReal fill)
319 {
320   PC_LU *dir;
321 
322   PetscFunctionBegin;
323   dir = (PC_LU*)pc->data;
324   dir->info.fill = fill;
325   PetscFunctionReturn(0);
326 }
327 EXTERN_C_END
328 
329 EXTERN_C_BEGIN
330 #undef __FUNCT__
331 #define __FUNCT__ "PCLUSetUseInPlace_LU"
332 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetUseInPlace_LU(PC pc)
333 {
334   PC_LU *dir;
335 
336   PetscFunctionBegin;
337   dir = (PC_LU*)pc->data;
338   dir->inplace = PETSC_TRUE;
339   PetscFunctionReturn(0);
340 }
341 EXTERN_C_END
342 
343 EXTERN_C_BEGIN
344 #undef __FUNCT__
345 #define __FUNCT__ "PCLUSetMatOrdering_LU"
346 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetMatOrdering_LU(PC pc,MatOrderingType ordering)
347 {
348   PC_LU          *dir = (PC_LU*)pc->data;
349   PetscErrorCode ierr;
350 
351   PetscFunctionBegin;
352   ierr = PetscStrfree(dir->ordering);CHKERRQ(ierr);
353   ierr = PetscStrallocpy(ordering,&dir->ordering);CHKERRQ(ierr);
354   PetscFunctionReturn(0);
355 }
356 EXTERN_C_END
357 
358 EXTERN_C_BEGIN
359 #undef __FUNCT__
360 #define __FUNCT__ "PCLUSetPivoting_LU"
361 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetPivoting_LU(PC pc,PetscReal dtcol)
362 {
363   PC_LU *dir = (PC_LU*)pc->data;
364 
365   PetscFunctionBegin;
366   if (dtcol < 0.0 || dtcol > 1.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Column pivot tolerance is %g must be between 0 and 1",dtcol);
367   dir->info.dtcol = dtcol;
368   PetscFunctionReturn(0);
369 }
370 EXTERN_C_END
371 
372 EXTERN_C_BEGIN
373 #undef __FUNCT__
374 #define __FUNCT__ "PCLUSetPivotInBlocks_LU"
375 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetPivotInBlocks_LU(PC pc,PetscTruth pivot)
376 {
377   PC_LU *dir = (PC_LU*)pc->data;
378 
379   PetscFunctionBegin;
380   dir->info.pivotinblocks = pivot ? 1.0 : 0.0;
381   PetscFunctionReturn(0);
382 }
383 EXTERN_C_END
384 
385 /* -----------------------------------------------------------------------------------*/
386 
387 #undef __FUNCT__
388 #define __FUNCT__ "PCLUReorderForNonzeroDiagonal"
389 /*@
390    PCLUReorderForNonzeroDiagonal - reorders rows/columns of matrix to remove zeros from diagonal
391 
392    Collective on PC
393 
394    Input Parameters:
395 +  pc - the preconditioner context
396 -  tol - diagonal entries smaller than this in absolute value are considered zero
397 
398    Options Database Key:
399 .  -pc_lu_nonzeros_along_diagonal
400 
401    Level: intermediate
402 
403 .keywords: PC, set, factorization, direct, fill
404 
405 .seealso: PCLUSetFill(), PCFactorSetShiftNonzero(), PCFactorSetZeroPivot(), MatReorderForNonzeroDiagonal()
406 @*/
407 PetscErrorCode PETSCKSP_DLLEXPORT PCLUReorderForNonzeroDiagonal(PC pc,PetscReal rtol)
408 {
409   PetscErrorCode ierr,(*f)(PC,PetscReal);
410 
411   PetscFunctionBegin;
412   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
413   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCLUReorderForNonzeroDiagonal_C",(void (**)(void))&f);CHKERRQ(ierr);
414   if (f) {
415     ierr = (*f)(pc,rtol);CHKERRQ(ierr);
416   }
417   PetscFunctionReturn(0);
418 }
419 
420 #undef __FUNCT__
421 #define __FUNCT__ "PCLUSetReuseOrdering"
422 /*@
423    PCLUSetReuseOrdering - When similar matrices are factored, this
424    causes the ordering computed in the first factor to be used for all
425    following factors; applies to both fill and drop tolerance LUs.
426 
427    Collective on PC
428 
429    Input Parameters:
430 +  pc - the preconditioner context
431 -  flag - PETSC_TRUE to reuse else PETSC_FALSE
432 
433    Options Database Key:
434 .  -pc_lu_reuse_ordering - Activate PCLUSetReuseOrdering()
435 
436    Level: intermediate
437 
438 .keywords: PC, levels, reordering, factorization, incomplete, LU
439 
440 .seealso: PCLUSetReuseFill(), PCILUSetReuseOrdering(), PCILUDTSetReuseFill()
441 @*/
442 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetReuseOrdering(PC pc,PetscTruth flag)
443 {
444   PetscErrorCode ierr,(*f)(PC,PetscTruth);
445 
446   PetscFunctionBegin;
447   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
448   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCLUSetReuseOrdering_C",(void (**)(void))&f);CHKERRQ(ierr);
449   if (f) {
450     ierr = (*f)(pc,flag);CHKERRQ(ierr);
451   }
452   PetscFunctionReturn(0);
453 }
454 
455 #undef __FUNCT__
456 #define __FUNCT__ "PCLUSetReuseFill"
457 /*@
458    PCLUSetReuseFill - When matrices with same nonzero structure are LU factored,
459    this causes later ones to use the fill computed in the initial factorization.
460 
461    Collective on PC
462 
463    Input Parameters:
464 +  pc - the preconditioner context
465 -  flag - PETSC_TRUE to reuse else PETSC_FALSE
466 
467    Options Database Key:
468 .  -pc_lu_reuse_fill - Activates PCLUSetReuseFill()
469 
470    Level: intermediate
471 
472 .keywords: PC, levels, reordering, factorization, incomplete, LU
473 
474 .seealso: PCILUSetReuseOrdering(), PCLUSetReuseOrdering(), PCILUDTSetReuseFill()
475 @*/
476 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetReuseFill(PC pc,PetscTruth flag)
477 {
478   PetscErrorCode ierr,(*f)(PC,PetscTruth);
479 
480   PetscFunctionBegin;
481   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
482   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCLUSetReuseFill_C",(void (**)(void))&f);CHKERRQ(ierr);
483   if (f) {
484     ierr = (*f)(pc,flag);CHKERRQ(ierr);
485   }
486   PetscFunctionReturn(0);
487 }
488 
489 #undef __FUNCT__
490 #define __FUNCT__ "PCLUSetFill"
491 /*@
492    PCLUSetFill - Indicate the amount of fill you expect in the factored matrix,
493    fill = number nonzeros in factor/number nonzeros in original matrix.
494 
495    Collective on PC
496 
497    Input Parameters:
498 +  pc - the preconditioner context
499 -  fill - amount of expected fill
500 
501    Options Database Key:
502 .  -pc_lu_fill <fill> - Sets fill amount
503 
504    Level: intermediate
505 
506    Note:
507    For sparse matrix factorizations it is difficult to predict how much
508    fill to expect. By running with the option -log_info PETSc will print the
509    actual amount of fill used; allowing you to set the value accurately for
510    future runs. Default PETSc uses a value of 5.0
511 
512 .keywords: PC, set, factorization, direct, fill
513 
514 .seealso: PCILUSetFill()
515 @*/
516 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetFill(PC pc,PetscReal fill)
517 {
518   PetscErrorCode ierr,(*f)(PC,PetscReal);
519 
520   PetscFunctionBegin;
521   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
522   if (fill < 1.0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Fill factor cannot be less then 1.0");
523   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCLUSetFill_C",(void (**)(void))&f);CHKERRQ(ierr);
524   if (f) {
525     ierr = (*f)(pc,fill);CHKERRQ(ierr);
526   }
527   PetscFunctionReturn(0);
528 }
529 
530 #undef __FUNCT__
531 #define __FUNCT__ "PCLUSetUseInPlace"
532 /*@
533    PCLUSetUseInPlace - Tells the system to do an in-place factorization.
534    For dense matrices, this enables the solution of much larger problems.
535    For sparse matrices the factorization cannot be done truly in-place
536    so this does not save memory during the factorization, but after the matrix
537    is factored, the original unfactored matrix is freed, thus recovering that
538    space.
539 
540    Collective on PC
541 
542    Input Parameters:
543 .  pc - the preconditioner context
544 
545    Options Database Key:
546 .  -pc_lu_in_place - Activates in-place factorization
547 
548    Notes:
549    PCLUSetUseInplace() can only be used with the KSP method KSPPREONLY or when
550    a different matrix is provided for the multiply and the preconditioner in
551    a call to KSPSetOperators().
552    This is because the Krylov space methods require an application of the
553    matrix multiplication, which is not possible here because the matrix has
554    been factored in-place, replacing the original matrix.
555 
556    Level: intermediate
557 
558 .keywords: PC, set, factorization, direct, inplace, in-place, LU
559 
560 .seealso: PCILUSetUseInPlace()
561 @*/
562 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetUseInPlace(PC pc)
563 {
564   PetscErrorCode ierr,(*f)(PC);
565 
566   PetscFunctionBegin;
567   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
568   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCLUSetUseInPlace_C",(void (**)(void))&f);CHKERRQ(ierr);
569   if (f) {
570     ierr = (*f)(pc);CHKERRQ(ierr);
571   }
572   PetscFunctionReturn(0);
573 }
574 
575 #undef __FUNCT__
576 #define __FUNCT__ "PCLUSetMatOrdering"
577 /*@C
578     PCLUSetMatOrdering - Sets the ordering routine (to reduce fill) to
579     be used in the LU factorization.
580 
581     Collective on PC
582 
583     Input Parameters:
584 +   pc - the preconditioner context
585 -   ordering - the matrix ordering name, for example, MATORDERING_ND or MATORDERING_RCM
586 
587     Options Database Key:
588 .   -pc_lu_mat_ordering_type <nd,rcm,...> - Sets ordering routine
589 
590     Level: intermediate
591 
592     Notes: nested dissection is used by default
593 
594 .seealso: PCILUSetMatOrdering()
595 @*/
596 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetMatOrdering(PC pc,MatOrderingType ordering)
597 {
598   PetscErrorCode ierr,(*f)(PC,MatOrderingType);
599 
600   PetscFunctionBegin;
601   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCLUSetMatOrdering_C",(void (**)(void))&f);CHKERRQ(ierr);
602   if (f) {
603     ierr = (*f)(pc,ordering);CHKERRQ(ierr);
604   }
605   PetscFunctionReturn(0);
606 }
607 
608 #undef __FUNCT__
609 #define __FUNCT__ "PCLUSetPivoting"
610 /*@
611     PCLUSetPivoting - Determines when pivoting is done during LU.
612       For PETSc dense matrices column pivoting is always done, for PETSc sparse matrices
613       it is never done. For the Matlab and SuperLU factorization this is used.
614 
615     Collective on PC
616 
617     Input Parameters:
618 +   pc - the preconditioner context
619 -   dtcol - 0.0 implies no pivoting, 1.0 complete pivoting (slower, requires more memory but more stable)
620 
621     Options Database Key:
622 .   -pc_lu_pivoting <dtcol>
623 
624     Level: intermediate
625 
626 .seealso: PCILUSetMatOrdering(), PCLUSetPivotInBlocks()
627 @*/
628 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetPivoting(PC pc,PetscReal dtcol)
629 {
630   PetscErrorCode ierr,(*f)(PC,PetscReal);
631 
632   PetscFunctionBegin;
633   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCLUSetPivoting_C",(void (**)(void))&f);CHKERRQ(ierr);
634   if (f) {
635     ierr = (*f)(pc,dtcol);CHKERRQ(ierr);
636   }
637   PetscFunctionReturn(0);
638 }
639 
640 #undef __FUNCT__
641 #define __FUNCT__ "PCLUSetPivotInBlocks"
642 /*@
643     PCLUSetPivotInBlocks - Determines if pivoting is done while factoring each block
644       with BAIJ or SBAIJ matrices
645 
646     Collective on PC
647 
648     Input Parameters:
649 +   pc - the preconditioner context
650 -   pivot - PETSC_TRUE or PETSC_FALSE
651 
652     Options Database Key:
653 .   -pc_lu_pivot_in_blocks <true,false>
654 
655     Level: intermediate
656 
657 .seealso: PCILUSetMatOrdering(), PCLUSetPivoting()
658 @*/
659 PetscErrorCode PETSCKSP_DLLEXPORT PCLUSetPivotInBlocks(PC pc,PetscTruth pivot)
660 {
661   PetscErrorCode ierr,(*f)(PC,PetscTruth);
662 
663   PetscFunctionBegin;
664   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCLUSetPivotInBlocks_C",(void (**)(void))&f);CHKERRQ(ierr);
665   if (f) {
666     ierr = (*f)(pc,pivot);CHKERRQ(ierr);
667   }
668   PetscFunctionReturn(0);
669 }
670 
671 /* ------------------------------------------------------------------------ */
672 
673 /*MC
674    PCLU - Uses a direct solver, based on LU factorization, as a preconditioner
675 
676    Options Database Keys:
677 +  -pc_lu_reuse_ordering - Activate PCLUSetReuseOrdering()
678 .  -pc_lu_reuse_fill - Activates PCLUSetReuseFill()
679 .  -pc_lu_fill <fill> - Sets fill amount
680 .  -pc_lu_in_place - Activates in-place factorization
681 .  -pc_lu_mat_ordering_type <nd,rcm,...> - Sets ordering routine
682 .  -pc_lu_pivot_in_blocks <true,false> - allow pivoting within the small blocks during factorization (may increase
683                                          stability of factorization.
684 .  -pc_factor_shift_nonzero <shift> - Sets shift amount or PETSC_DECIDE for the default
685 -  -pc_factor_shift_positive_definite [PETSC_TRUE/PETSC_FALSE] - Activate/Deactivate PCFactorSetShiftPd(); the value
686    is optional with PETSC_TRUE being the default
687 
688    Notes: Not all options work for all matrix formats
689           Run with -help to see additional options for particular matrix formats or factorization
690           algorithms
691 
692    Level: beginner
693 
694    Concepts: LU factorization, direct solver
695 
696    Notes: Usually this will compute an "exact" solution in one iteration and does
697           not need a Krylov method (i.e. you can use -ksp_type preonly, or
698           KSPSetType(ksp,KSPPREONLY) for the Krylov method
699 
700 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
701            PCILU, PCCHOLESKY, PCICC, PCLUSetReuseOrdering(), PCLUSetReuseFill(), PCGetFactoredMatrix(),
702            PCLUSetFill(), PCLUSetUseInPlace(), PCLUSetMatOrdering(), PCFactorSetPivoting(),
703            PCLUSetPivotingInBlocks(),PCFactorSetShiftNonzero(),PCFactorSetShiftPd()
704 M*/
705 
706 EXTERN_C_BEGIN
707 #undef __FUNCT__
708 #define __FUNCT__ "PCCreate_LU"
709 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_LU(PC pc)
710 {
711   PetscErrorCode ierr;
712   PetscMPIInt    size;
713   PC_LU          *dir;
714 
715   PetscFunctionBegin;
716   ierr = PetscNew(PC_LU,&dir);CHKERRQ(ierr);
717   ierr = PetscLogObjectMemory(pc,sizeof(PC_LU));CHKERRQ(ierr);
718 
719   ierr = MatFactorInfoInitialize(&dir->info);CHKERRQ(ierr);
720   dir->fact                  = 0;
721   dir->inplace               = PETSC_FALSE;
722   dir->nonzerosalongdiagonal = PETSC_FALSE;
723 
724   dir->info.fill           = 5.0;
725   dir->info.dtcol          = 1.e-6; /* default to pivoting; this is only thing PETSc LU supports */
726   dir->info.shiftnz        = 0.0;
727   dir->info.zeropivot      = 1.e-12;
728   dir->info.pivotinblocks  = 1.0;
729   dir->info.shiftpd        = 0.0; /* false */
730   dir->info.shift_fraction = 0.0;
731   dir->col                 = 0;
732   dir->row                 = 0;
733   ierr = MPI_Comm_size(pc->comm,&size);CHKERRQ(ierr);
734   if (size == 1) {
735     ierr = PetscStrallocpy(MATORDERING_ND,&dir->ordering);CHKERRQ(ierr);
736   } else {
737     ierr = PetscStrallocpy(MATORDERING_NATURAL,&dir->ordering);CHKERRQ(ierr);
738   }
739   dir->reusefill        = PETSC_FALSE;
740   dir->reuseordering    = PETSC_FALSE;
741   pc->data              = (void*)dir;
742 
743   pc->ops->destroy           = PCDestroy_LU;
744   pc->ops->apply             = PCApply_LU;
745   pc->ops->applytranspose    = PCApplyTranspose_LU;
746   pc->ops->setup             = PCSetUp_LU;
747   pc->ops->setfromoptions    = PCSetFromOptions_LU;
748   pc->ops->view              = PCView_LU;
749   pc->ops->applyrichardson   = 0;
750   pc->ops->getfactoredmatrix = PCGetFactoredMatrix_LU;
751 
752   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_LU",
753                     PCFactorSetZeroPivot_LU);CHKERRQ(ierr);
754   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftNonzero_C","PCFactorSetShiftNonzero_LU",
755                     PCFactorSetShiftNonzero_LU);CHKERRQ(ierr);
756   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftPd_C","PCFactorSetShiftPd_LU",
757                     PCFactorSetShiftPd_LU);CHKERRQ(ierr);
758 
759   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCLUSetFill_C","PCLUSetFill_LU",
760                     PCLUSetFill_LU);CHKERRQ(ierr);
761   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCLUSetUseInPlace_C","PCLUSetUseInPlace_LU",
762                     PCLUSetUseInPlace_LU);CHKERRQ(ierr);
763   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCLUSetMatOrdering_C","PCLUSetMatOrdering_LU",
764                     PCLUSetMatOrdering_LU);CHKERRQ(ierr);
765   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCLUSetReuseOrdering_C","PCLUSetReuseOrdering_LU",
766                     PCLUSetReuseOrdering_LU);CHKERRQ(ierr);
767   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCLUSetReuseFill_C","PCLUSetReuseFill_LU",
768                     PCLUSetReuseFill_LU);CHKERRQ(ierr);
769   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCLUSetPivoting_C","PCLUSetPivoting_LU",
770                     PCLUSetPivoting_LU);CHKERRQ(ierr);
771   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCLUSetPivotInBlocks_C","PCLUSetPivotInBlocks_LU",
772                     PCLUSetPivotInBlocks_LU);CHKERRQ(ierr);
773   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCLUReorderForNonzeroDiagonal_C","PCLUReorderForNonzeroDiagonal_LU",
774                     PCLUReorderForNonzeroDiagonal_LU);CHKERRQ(ierr);
775   PetscFunctionReturn(0);
776 }
777 EXTERN_C_END
778