xref: /petsc/src/ksp/pc/impls/factor/cholesky/cholesky.c (revision 45bfc511327f17f9664eea9fee8d9f549538c00a)
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 #include "src/ksp/pc/pcimpl.h"                /*I "petscpc.h" I*/
9 
10 typedef struct {
11   Mat             fact;             /* factored matrix */
12   PetscReal       actualfill;       /* actual fill in factor */
13   PetscTruth      inplace;          /* flag indicating in-place factorization */
14   IS              row,col;          /* index sets used for reordering */
15   MatOrderingType ordering;         /* matrix ordering */
16   PetscTruth      reuseordering;    /* reuses previous reordering computed */
17   PetscTruth      reusefill;        /* reuse fill from previous Cholesky */
18   MatFactorInfo   info;
19 } PC_Cholesky;
20 
21 EXTERN_C_BEGIN
22 #undef __FUNCT__
23 #define __FUNCT__ "PCFactorSetZeroPivot_Cholesky"
24 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetZeroPivot_Cholesky(PC pc,PetscReal z)
25 {
26   PC_Cholesky *ch;
27 
28   PetscFunctionBegin;
29   ch                 = (PC_Cholesky*)pc->data;
30   ch->info.zeropivot = z;
31   PetscFunctionReturn(0);
32 }
33 EXTERN_C_END
34 
35 EXTERN_C_BEGIN
36 #undef __FUNCT__
37 #define __FUNCT__ "PCFactorSetShiftNonzero_Cholesky"
38 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftNonzero_Cholesky(PC pc,PetscReal shift)
39 {
40   PC_Cholesky *dir;
41 
42   PetscFunctionBegin;
43   dir = (PC_Cholesky*)pc->data;
44   if (shift == (PetscReal) PETSC_DECIDE) {
45     dir->info.shiftnz = 1.e-12;
46   } else {
47     dir->info.shiftnz = shift;
48   }
49   PetscFunctionReturn(0);
50 }
51 EXTERN_C_END
52 
53 EXTERN_C_BEGIN
54 #undef __FUNCT__
55 #define __FUNCT__ "PCFactorSetShiftPd_Cholesky"
56 PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftPd_Cholesky(PC pc,PetscTruth shift)
57 {
58   PC_Cholesky *dir;
59 
60   PetscFunctionBegin;
61   dir = (PC_Cholesky*)pc->data;
62   dir->info.shiftpd = shift;
63   if (shift) dir->info.shift_fraction = 0.0;
64   PetscFunctionReturn(0);
65 }
66 EXTERN_C_END
67 
68 EXTERN_C_BEGIN
69 #undef __FUNCT__
70 #define __FUNCT__ "PCCholeskySetReuseOrdering_Cholesky"
71 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseOrdering_Cholesky(PC pc,PetscTruth flag)
72 {
73   PC_Cholesky *lu;
74 
75   PetscFunctionBegin;
76   lu               = (PC_Cholesky*)pc->data;
77   lu->reuseordering = flag;
78   PetscFunctionReturn(0);
79 }
80 EXTERN_C_END
81 
82 EXTERN_C_BEGIN
83 #undef __FUNCT__
84 #define __FUNCT__ "PCCholeskySetReuseFill_Cholesky"
85 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseFill_Cholesky(PC pc,PetscTruth flag)
86 {
87   PC_Cholesky *lu;
88 
89   PetscFunctionBegin;
90   lu = (PC_Cholesky*)pc->data;
91   lu->reusefill = flag;
92   PetscFunctionReturn(0);
93 }
94 EXTERN_C_END
95 
96 #undef __FUNCT__
97 #define __FUNCT__ "PCSetFromOptions_Cholesky"
98 static PetscErrorCode PCSetFromOptions_Cholesky(PC pc)
99 {
100   PC_Cholesky    *lu = (PC_Cholesky*)pc->data;
101   PetscErrorCode ierr;
102   PetscTruth     flg;
103   char           tname[256];
104   PetscFList     ordlist;
105 
106   PetscFunctionBegin;
107   ierr = MatOrderingRegisterAll(PETSC_NULL);CHKERRQ(ierr);
108   ierr = PetscOptionsHead("Cholesky options");CHKERRQ(ierr);
109   ierr = PetscOptionsName("-pc_cholesky_in_place","Form Cholesky in the same memory as the matrix","PCCholeskySetUseInPlace",&flg);CHKERRQ(ierr);
110   if (flg) {
111     ierr = PCCholeskySetUseInPlace(pc);CHKERRQ(ierr);
112   }
113   ierr = PetscOptionsReal("-pc_cholesky_fill","Expected non-zeros in Cholesky/non-zeros in matrix","PCCholeskySetFill",lu->info.fill,&lu->info.fill,0);CHKERRQ(ierr);
114 
115   ierr = PetscOptionsName("-pc_cholesky_reuse_fill","Use fill from previous factorization","PCCholeskySetReuseFill",&flg);CHKERRQ(ierr);
116   if (flg) {
117     ierr = PCCholeskySetReuseFill(pc,PETSC_TRUE);CHKERRQ(ierr);
118   }
119   ierr = PetscOptionsName("-pc_cholesky_reuse_ordering","Reuse ordering from previous factorization","PCCholeskySetReuseOrdering",&flg);CHKERRQ(ierr);
120   if (flg) {
121     ierr = PCCholeskySetReuseOrdering(pc,PETSC_TRUE);CHKERRQ(ierr);
122   }
123 
124   ierr = MatGetOrderingList(&ordlist);CHKERRQ(ierr);
125   ierr = PetscOptionsList("-pc_cholesky_mat_ordering_type","Reordering to reduce nonzeros in Cholesky","PCCholeskySetMatOrdering",ordlist,lu->ordering,tname,256,&flg);CHKERRQ(ierr);
126   if (flg) {
127     ierr = PCCholeskySetMatOrdering(pc,tname);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 = PetscOptionsTail();CHKERRQ(ierr);
141   PetscFunctionReturn(0);
142 }
143 
144 #undef __FUNCT__
145 #define __FUNCT__ "PCView_Cholesky"
146 static PetscErrorCode PCView_Cholesky(PC pc,PetscViewer viewer)
147 {
148   PC_Cholesky    *lu = (PC_Cholesky*)pc->data;
149   PetscErrorCode ierr;
150   PetscTruth     iascii,isstring;
151 
152   PetscFunctionBegin;
153   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
154   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr);
155   if (iascii) {
156     MatInfo info;
157 
158     if (lu->inplace) {ierr = PetscViewerASCIIPrintf(viewer,"  Cholesky: in-place factorization\n");CHKERRQ(ierr);}
159     else             {ierr = PetscViewerASCIIPrintf(viewer,"  Cholesky: out-of-place factorization\n");CHKERRQ(ierr);}
160     ierr = PetscViewerASCIIPrintf(viewer,"    matrix ordering: %s\n",lu->ordering);CHKERRQ(ierr);
161     if (lu->fact) {
162       ierr = MatGetInfo(lu->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
163       ierr = PetscViewerASCIIPrintf(viewer,"    Cholesky nonzeros %g\n",info.nz_used);CHKERRQ(ierr);
164       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_FACTOR_INFO);CHKERRQ(ierr);
165       ierr = MatView(lu->fact,viewer);CHKERRQ(ierr);
166       ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
167     }
168     if (lu->reusefill)    {ierr = PetscViewerASCIIPrintf(viewer,"       Reusing fill from past factorization\n");CHKERRQ(ierr);}
169     if (lu->reuseordering) {ierr = PetscViewerASCIIPrintf(viewer,"       Reusing reordering from past factorization\n");CHKERRQ(ierr);}
170   } else if (isstring) {
171     ierr = PetscViewerStringSPrintf(viewer," order=%s",lu->ordering);CHKERRQ(ierr);CHKERRQ(ierr);
172   } else {
173     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCCholesky",((PetscObject)viewer)->type_name);
174   }
175   PetscFunctionReturn(0);
176 }
177 
178 #undef __FUNCT__
179 #define __FUNCT__ "PCGetFactoredMatrix_Cholesky"
180 static PetscErrorCode PCGetFactoredMatrix_Cholesky(PC pc,Mat *mat)
181 {
182   PC_Cholesky *dir = (PC_Cholesky*)pc->data;
183 
184   PetscFunctionBegin;
185   if (!dir->fact) SETERRQ(PETSC_ERR_ORDER,"Matrix not yet factored; call after KSPSetUp() or PCSetUp()");
186   *mat = dir->fact;
187   PetscFunctionReturn(0);
188 }
189 
190 #undef __FUNCT__
191 #define __FUNCT__ "PCSetUp_Cholesky"
192 static PetscErrorCode PCSetUp_Cholesky(PC pc)
193 {
194   PetscErrorCode ierr;
195   PetscTruth     flg;
196   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;
197 
198   PetscFunctionBegin;
199   if (dir->reusefill && pc->setupcalled) dir->info.fill = dir->actualfill;
200 
201   if (dir->inplace) {
202     if (dir->row && dir->col && (dir->row != dir->col)) {
203       ierr = ISDestroy(dir->row);CHKERRQ(ierr);
204       dir->row = 0;
205     }
206     if (dir->col) {
207       ierr = ISDestroy(dir->col);CHKERRQ(ierr);
208       dir->col = 0;
209     }
210     ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
211     if (dir->col && (dir->row != dir->col)) {  /* only use row ordering for SBAIJ */
212       ierr = ISDestroy(dir->col);CHKERRQ(ierr);
213       dir->col=0;
214     }
215     if (dir->row) {ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);}
216     ierr = MatCholeskyFactor(pc->pmat,dir->row,&dir->info);CHKERRQ(ierr);
217     dir->fact = pc->pmat;
218   } else {
219     MatInfo info;
220     if (!pc->setupcalled) {
221       ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
222       if (dir->col && (dir->row != dir->col)) {  /* only use row ordering for SBAIJ */
223         ierr = ISDestroy(dir->col);CHKERRQ(ierr);
224         dir->col=0;
225       }
226       ierr = PetscOptionsHasName(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&flg);CHKERRQ(ierr);
227       if (flg) {
228         PetscReal tol = 1.e-10;
229         ierr = PetscOptionsGetReal(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&tol,PETSC_NULL);CHKERRQ(ierr);
230         ierr = MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);CHKERRQ(ierr);
231       }
232       if (dir->row) {ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);}
233       ierr = MatCholeskyFactorSymbolic(pc->pmat,dir->row,&dir->info,&dir->fact);CHKERRQ(ierr);
234       ierr = MatGetInfo(dir->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
235       dir->actualfill = info.fill_ratio_needed;
236       ierr = PetscLogObjectParent(pc,dir->fact);CHKERRQ(ierr);
237     } else if (pc->flag != SAME_NONZERO_PATTERN) {
238       if (!dir->reuseordering) {
239         if (dir->row && dir->col && (dir->row != dir->col)) {
240           ierr = ISDestroy(dir->row);CHKERRQ(ierr);
241           dir->row = 0;
242         }
243         if (dir->col) {
244           ierr = ISDestroy(dir->col);CHKERRQ(ierr);
245           dir->col =0;
246         }
247         ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
248         if (dir->col && (dir->row != dir->col)) {  /* only use row ordering for SBAIJ */
249           ierr = ISDestroy(dir->col);CHKERRQ(ierr);
250           dir->col=0;
251         }
252         ierr = PetscOptionsHasName(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&flg);CHKERRQ(ierr);
253         if (flg) {
254           PetscReal tol = 1.e-10;
255           ierr = PetscOptionsGetReal(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&tol,PETSC_NULL);CHKERRQ(ierr);
256           ierr = MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);CHKERRQ(ierr);
257         }
258         if (dir->row) {ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);}
259       }
260       ierr = MatDestroy(dir->fact);CHKERRQ(ierr);
261       ierr = MatCholeskyFactorSymbolic(pc->pmat,dir->row,&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 = MatCholeskyFactorNumeric(pc->pmat,&dir->info,&dir->fact);CHKERRQ(ierr);
267   }
268   PetscFunctionReturn(0);
269 }
270 
271 #undef __FUNCT__
272 #define __FUNCT__ "PCDestroy_Cholesky"
273 static PetscErrorCode PCDestroy_Cholesky(PC pc)
274 {
275   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;
276   PetscErrorCode ierr;
277 
278   PetscFunctionBegin;
279   if (!dir->inplace && dir->fact) {ierr = MatDestroy(dir->fact);CHKERRQ(ierr);}
280   if (dir->row) {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_Cholesky"
289 static PetscErrorCode PCApply_Cholesky(PC pc,Vec x,Vec y)
290 {
291   PC_Cholesky    *dir = (PC_Cholesky*)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_Cholesky"
302 static PetscErrorCode PCApplyTranspose_Cholesky(PC pc,Vec x,Vec y)
303 {
304   PC_Cholesky    *dir = (PC_Cholesky*)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__ "PCCholeskySetFill_Cholesky"
318 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetFill_Cholesky(PC pc,PetscReal fill)
319 {
320   PC_Cholesky *dir;
321 
322   PetscFunctionBegin;
323   dir = (PC_Cholesky*)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__ "PCCholeskySetUseInPlace_Cholesky"
332 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetUseInPlace_Cholesky(PC pc)
333 {
334   PC_Cholesky *dir;
335 
336   PetscFunctionBegin;
337   dir = (PC_Cholesky*)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__ "PCCholeskySetMatOrdering_Cholesky"
346 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetMatOrdering_Cholesky(PC pc,MatOrderingType ordering)
347 {
348   PC_Cholesky    *dir = (PC_Cholesky*)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 /* -----------------------------------------------------------------------------------*/
359 
360 #undef __FUNCT__
361 #define __FUNCT__ "PCCholeskySetReuseOrdering"
362 /*@
363    PCCholeskySetReuseOrdering - When similar matrices are factored, this
364    causes the ordering computed in the first factor to be used for all
365    following factors.
366 
367    Collective on PC
368 
369    Input Parameters:
370 +  pc - the preconditioner context
371 -  flag - PETSC_TRUE to reuse else PETSC_FALSE
372 
373    Options Database Key:
374 .  -pc_cholesky_reuse_ordering - Activate PCCholeskySetReuseOrdering()
375 
376    Level: intermediate
377 
378 .keywords: PC, levels, reordering, factorization, incomplete, LU
379 
380 .seealso: PCCholeskySetReuseFill(), PCICholeskySetReuseOrdering(), PCICholeskyDTSetReuseFill()
381 @*/
382 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseOrdering(PC pc,PetscTruth flag)
383 {
384   PetscErrorCode ierr,(*f)(PC,PetscTruth);
385 
386   PetscFunctionBegin;
387   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
388   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetReuseOrdering_C",(void (**)(void))&f);CHKERRQ(ierr);
389   if (f) {
390     ierr = (*f)(pc,flag);CHKERRQ(ierr);
391   }
392   PetscFunctionReturn(0);
393 }
394 
395 #undef __FUNCT__
396 #define __FUNCT__ "PCCholeskySetReuseFill"
397 /*@
398    PCCholeskySetReuseFill - When matrices with same nonzero structure are Cholesky factored,
399    this causes later ones to use the fill computed in the initial factorization.
400 
401    Collective on PC
402 
403    Input Parameters:
404 +  pc - the preconditioner context
405 -  flag - PETSC_TRUE to reuse else PETSC_FALSE
406 
407    Options Database Key:
408 .  -pc_cholesky_reuse_fill - Activates PCCholeskySetReuseFill()
409 
410    Level: intermediate
411 
412 .keywords: PC, levels, reordering, factorization, incomplete, Cholesky
413 
414 .seealso: PCICholeskySetReuseOrdering(), PCCholeskySetReuseOrdering(), PCICholeskyDTSetReuseFill()
415 @*/
416 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseFill(PC pc,PetscTruth flag)
417 {
418   PetscErrorCode ierr,(*f)(PC,PetscTruth);
419 
420   PetscFunctionBegin;
421   PetscValidHeaderSpecific(pc,PC_COOKIE,2);
422   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetReuseFill_C",(void (**)(void))&f);CHKERRQ(ierr);
423   if (f) {
424     ierr = (*f)(pc,flag);CHKERRQ(ierr);
425   }
426   PetscFunctionReturn(0);
427 }
428 
429 #undef __FUNCT__
430 #define __FUNCT__ "PCCholeskySetFill"
431 /*@
432    PCCholeskySetFill - Indicates the amount of fill you expect in the factored matrix,
433    fill = number nonzeros in factor/number nonzeros in original matrix.
434 
435    Collective on PC
436 
437    Input Parameters:
438 +  pc - the preconditioner context
439 -  fill - amount of expected fill
440 
441    Options Database Key:
442 .  -pc_cholesky_fill <fill> - Sets fill amount
443 
444    Level: intermediate
445 
446    Note:
447    For sparse matrix factorizations it is difficult to predict how much
448    fill to expect. By running with the option -log_info PETSc will print the
449    actual amount of fill used; allowing you to set the value accurately for
450    future runs. Default PETSc uses a value of 5.0
451 
452 .keywords: PC, set, factorization, direct, fill
453 
454 .seealso: PCILUSetFill()
455 @*/
456 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetFill(PC pc,PetscReal fill)
457 {
458   PetscErrorCode ierr,(*f)(PC,PetscReal);
459 
460   PetscFunctionBegin;
461   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
462   if (fill < 1.0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Fill factor cannot be less then 1.0");
463   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetFill_C",(void (**)(void))&f);CHKERRQ(ierr);
464   if (f) {
465     ierr = (*f)(pc,fill);CHKERRQ(ierr);
466   }
467   PetscFunctionReturn(0);
468 }
469 
470 #undef __FUNCT__
471 #define __FUNCT__ "PCCholeskySetUseInPlace"
472 /*@
473    PCCholeskySetUseInPlace - Tells the system to do an in-place factorization.
474    For dense matrices, this enables the solution of much larger problems.
475    For sparse matrices the factorization cannot be done truly in-place
476    so this does not save memory during the factorization, but after the matrix
477    is factored, the original unfactored matrix is freed, thus recovering that
478    space.
479 
480    Collective on PC
481 
482    Input Parameters:
483 .  pc - the preconditioner context
484 
485    Options Database Key:
486 .  -pc_cholesky_in_place - Activates in-place factorization
487 
488    Notes:
489    PCCholeskySetUseInplace() can only be used with the KSP method KSPPREONLY or when
490    a different matrix is provided for the multiply and the preconditioner in
491    a call to KSPSetOperators().
492    This is because the Krylov space methods require an application of the
493    matrix multiplication, which is not possible here because the matrix has
494    been factored in-place, replacing the original matrix.
495 
496    Level: intermediate
497 
498 .keywords: PC, set, factorization, direct, inplace, in-place, Cholesky
499 
500 .seealso: PCICholeskySetUseInPlace()
501 @*/
502 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetUseInPlace(PC pc)
503 {
504   PetscErrorCode ierr,(*f)(PC);
505 
506   PetscFunctionBegin;
507   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
508   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetUseInPlace_C",(void (**)(void))&f);CHKERRQ(ierr);
509   if (f) {
510     ierr = (*f)(pc);CHKERRQ(ierr);
511   }
512   PetscFunctionReturn(0);
513 }
514 
515 #undef __FUNCT__
516 #define __FUNCT__ "PCCholeskySetMatOrdering"
517 /*@
518     PCCholeskySetMatOrdering - Sets the ordering routine (to reduce fill) to
519     be used it the Cholesky factorization.
520 
521     Collective on PC
522 
523     Input Parameters:
524 +   pc - the preconditioner context
525 -   ordering - the matrix ordering name, for example, MATORDERING_ND or MATORDERING_RCM
526 
527     Options Database Key:
528 .   -pc_cholesky_mat_ordering_type <nd,rcm,...> - Sets ordering routine
529 
530     Level: intermediate
531 
532 .seealso: PCICholeskySetMatOrdering()
533 @*/
534 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetMatOrdering(PC pc,MatOrderingType ordering)
535 {
536   PetscErrorCode ierr,(*f)(PC,MatOrderingType);
537 
538   PetscFunctionBegin;
539   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetMatOrdering_C",(void (**)(void))&f);CHKERRQ(ierr);
540   if (f) {
541     ierr = (*f)(pc,ordering);CHKERRQ(ierr);
542   }
543   PetscFunctionReturn(0);
544 }
545 
546 /*MC
547    PCCholesky - Uses a direct solver, based on Cholesky factorization, as a preconditioner
548 
549    Options Database Keys:
550 +  -pc_cholesky_reuse_ordering - Activate PCLUSetReuseOrdering()
551 .  -pc_cholesky_reuse_fill - Activates PCLUSetReuseFill()
552 .  -pc_cholesky_fill <fill> - Sets fill amount
553 .  -pc_cholesky_in_place - Activates in-place factorization
554 -  -pc_cholesky_mat_ordering_type <nd,rcm,...> - Sets ordering routine
555 
556    Notes: Not all options work for all matrix formats
557 
558    Level: beginner
559 
560    Concepts: Cholesky factorization, direct solver
561 
562    Notes: Usually this will compute an "exact" solution in one iteration and does
563           not need a Krylov method (i.e. you can use -ksp_type preonly, or
564           KSPSetType(ksp,KSPPREONLY) for the Krylov method
565 
566 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
567            PCILU, PCLU, PCICC, PCCholeskySetReuseOrdering(), PCCholeskySetReuseFill(), PCGetFactoredMatrix(),
568            PCCholeskySetFill(), PCFactorSetShiftNonzero(), PCFactorSetShiftPd(),
569 	   PCCholeskySetUseInPlace(), PCCholeskySetMatOrdering()
570 
571 M*/
572 
573 EXTERN_C_BEGIN
574 #undef __FUNCT__
575 #define __FUNCT__ "PCCreate_Cholesky"
576 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Cholesky(PC pc)
577 {
578   PetscErrorCode ierr;
579   PC_Cholesky    *dir;
580 
581   PetscFunctionBegin;
582   ierr = PetscNew(PC_Cholesky,&dir);CHKERRQ(ierr);
583   ierr = PetscLogObjectMemory(pc,sizeof(PC_Cholesky));CHKERRQ(ierr);
584 
585   dir->fact                   = 0;
586   dir->inplace                = PETSC_FALSE;
587   ierr = MatFactorInfoInitialize(&dir->info);CHKERRQ(ierr);
588   dir->info.fill              = 5.0;
589   dir->info.shiftnz           = 0.0;
590   dir->info.shiftpd           = PETSC_FALSE;
591   dir->info.shift_fraction    = 0.0;
592   dir->info.pivotinblocks     = 1.0;
593   dir->col                    = 0;
594   dir->row                    = 0;
595   ierr = PetscStrallocpy(MATORDERING_NATURAL,&dir->ordering);CHKERRQ(ierr);
596   dir->reusefill        = PETSC_FALSE;
597   dir->reuseordering    = PETSC_FALSE;
598   pc->data              = (void*)dir;
599 
600   pc->ops->destroy           = PCDestroy_Cholesky;
601   pc->ops->apply             = PCApply_Cholesky;
602   pc->ops->applytranspose    = PCApplyTranspose_Cholesky;
603   pc->ops->setup             = PCSetUp_Cholesky;
604   pc->ops->setfromoptions    = PCSetFromOptions_Cholesky;
605   pc->ops->view              = PCView_Cholesky;
606   pc->ops->applyrichardson   = 0;
607   pc->ops->getfactoredmatrix = PCGetFactoredMatrix_Cholesky;
608 
609   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_Cholesky",
610                     PCFactorSetZeroPivot_Cholesky);CHKERRQ(ierr);
611   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftNonzero_C","PCFactorSetShiftNonzero_Cholesky",
612                     PCFactorSetShiftNonzero_Cholesky);CHKERRQ(ierr);
613   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftPd_C","PCFactorSetShiftPd_Cholesky",
614                     PCFactorSetShiftPd_Cholesky);CHKERRQ(ierr);
615 
616   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetFill_C","PCCholeskySetFill_Cholesky",
617                     PCCholeskySetFill_Cholesky);CHKERRQ(ierr);
618   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetUseInPlace_C","PCCholeskySetUseInPlace_Cholesky",
619                     PCCholeskySetUseInPlace_Cholesky);CHKERRQ(ierr);
620   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetMatOrdering_C","PCCholeskySetMatOrdering_Cholesky",
621                     PCCholeskySetMatOrdering_Cholesky);CHKERRQ(ierr);
622   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetReuseOrdering_C","PCCholeskySetReuseOrdering_Cholesky",
623                     PCCholeskySetReuseOrdering_Cholesky);CHKERRQ(ierr);
624   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetReuseFill_C","PCCholeskySetReuseFill_Cholesky",
625                     PCCholeskySetReuseFill_Cholesky);CHKERRQ(ierr);
626   PetscFunctionReturn(0);
627 }
628 EXTERN_C_END
629