xref: /petsc/src/ksp/pc/impls/factor/cholesky/cholesky.c (revision e2df7a95c5ea77c899beea10ff9effd6061e7c8f)
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   if (shift) {
63     dir->info.shift_fraction = 0.0;
64     dir->info.shiftpd = 1.0;
65   } else {
66     dir->info.shiftpd = 0.0;
67   }
68   PetscFunctionReturn(0);
69 }
70 EXTERN_C_END
71 
72 EXTERN_C_BEGIN
73 #undef __FUNCT__
74 #define __FUNCT__ "PCCholeskySetReuseOrdering_Cholesky"
75 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseOrdering_Cholesky(PC pc,PetscTruth flag)
76 {
77   PC_Cholesky *lu;
78 
79   PetscFunctionBegin;
80   lu               = (PC_Cholesky*)pc->data;
81   lu->reuseordering = flag;
82   PetscFunctionReturn(0);
83 }
84 EXTERN_C_END
85 
86 EXTERN_C_BEGIN
87 #undef __FUNCT__
88 #define __FUNCT__ "PCCholeskySetReuseFill_Cholesky"
89 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseFill_Cholesky(PC pc,PetscTruth flag)
90 {
91   PC_Cholesky *lu;
92 
93   PetscFunctionBegin;
94   lu = (PC_Cholesky*)pc->data;
95   lu->reusefill = flag;
96   PetscFunctionReturn(0);
97 }
98 EXTERN_C_END
99 
100 #undef __FUNCT__
101 #define __FUNCT__ "PCSetFromOptions_Cholesky"
102 static PetscErrorCode PCSetFromOptions_Cholesky(PC pc)
103 {
104   PC_Cholesky    *lu = (PC_Cholesky*)pc->data;
105   PetscErrorCode ierr;
106   PetscTruth     flg;
107   char           tname[256];
108   PetscFList     ordlist;
109 
110   PetscFunctionBegin;
111   ierr = MatOrderingRegisterAll(PETSC_NULL);CHKERRQ(ierr);
112   ierr = PetscOptionsHead("Cholesky options");CHKERRQ(ierr);
113   ierr = PetscOptionsName("-pc_cholesky_in_place","Form Cholesky in the same memory as the matrix","PCCholeskySetUseInPlace",&flg);CHKERRQ(ierr);
114   if (flg) {
115     ierr = PCCholeskySetUseInPlace(pc);CHKERRQ(ierr);
116   }
117   ierr = PetscOptionsReal("-pc_cholesky_fill","Expected non-zeros in Cholesky/non-zeros in matrix","PCCholeskySetFill",lu->info.fill,&lu->info.fill,0);CHKERRQ(ierr);
118 
119   ierr = PetscOptionsName("-pc_cholesky_reuse_fill","Use fill from previous factorization","PCCholeskySetReuseFill",&flg);CHKERRQ(ierr);
120   if (flg) {
121     ierr = PCCholeskySetReuseFill(pc,PETSC_TRUE);CHKERRQ(ierr);
122   }
123   ierr = PetscOptionsName("-pc_cholesky_reuse_ordering","Reuse ordering from previous factorization","PCCholeskySetReuseOrdering",&flg);CHKERRQ(ierr);
124   if (flg) {
125     ierr = PCCholeskySetReuseOrdering(pc,PETSC_TRUE);CHKERRQ(ierr);
126   }
127 
128   ierr = MatGetOrderingList(&ordlist);CHKERRQ(ierr);
129   ierr = PetscOptionsList("-pc_cholesky_mat_ordering_type","Reordering to reduce nonzeros in Cholesky","PCCholeskySetMatOrdering",ordlist,lu->ordering,tname,256,&flg);CHKERRQ(ierr);
130   if (flg) {
131     ierr = PCCholeskySetMatOrdering(pc,tname);CHKERRQ(ierr);
132   }
133   ierr = PetscOptionsName("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",&flg);CHKERRQ(ierr);
134   if (flg) {
135     ierr = PCFactorSetShiftNonzero(pc,(PetscReal) PETSC_DECIDE);CHKERRQ(ierr);
136   }
137   ierr = PetscOptionsReal("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",lu->info.shiftnz,&lu->info.shiftnz,0);CHKERRQ(ierr);
138   ierr = PetscOptionsName("-pc_factor_shift_positive_definite","Manteuffel shift applied to diagonal","PCFactorSetShiftPd",&flg);CHKERRQ(ierr);
139   if (flg) {
140     ierr = PCFactorSetShiftPd(pc,PETSC_TRUE);CHKERRQ(ierr);
141   }
142   ierr = PetscOptionsReal("-pc_factor_zeropivot","Pivot is considered zero if less than","PCFactorSetZeroPivot",lu->info.zeropivot,&lu->info.zeropivot,0);CHKERRQ(ierr);
143 
144   ierr = PetscOptionsTail();CHKERRQ(ierr);
145   PetscFunctionReturn(0);
146 }
147 
148 #undef __FUNCT__
149 #define __FUNCT__ "PCView_Cholesky"
150 static PetscErrorCode PCView_Cholesky(PC pc,PetscViewer viewer)
151 {
152   PC_Cholesky    *lu = (PC_Cholesky*)pc->data;
153   PetscErrorCode ierr;
154   PetscTruth     iascii,isstring;
155 
156   PetscFunctionBegin;
157   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
158   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);CHKERRQ(ierr);
159   if (iascii) {
160     MatInfo info;
161 
162     if (lu->inplace) {ierr = PetscViewerASCIIPrintf(viewer,"  Cholesky: in-place factorization\n");CHKERRQ(ierr);}
163     else             {ierr = PetscViewerASCIIPrintf(viewer,"  Cholesky: out-of-place factorization\n");CHKERRQ(ierr);}
164     ierr = PetscViewerASCIIPrintf(viewer,"    matrix ordering: %s\n",lu->ordering);CHKERRQ(ierr);
165     if (lu->fact) {
166       ierr = MatGetInfo(lu->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
167       ierr = PetscViewerASCIIPrintf(viewer,"    Cholesky nonzeros %g\n",info.nz_used);CHKERRQ(ierr);
168       ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_FACTOR_INFO);CHKERRQ(ierr);
169       ierr = MatView(lu->fact,viewer);CHKERRQ(ierr);
170       ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
171     }
172     if (lu->reusefill)    {ierr = PetscViewerASCIIPrintf(viewer,"       Reusing fill from past factorization\n");CHKERRQ(ierr);}
173     if (lu->reuseordering) {ierr = PetscViewerASCIIPrintf(viewer,"       Reusing reordering from past factorization\n");CHKERRQ(ierr);}
174   } else if (isstring) {
175     ierr = PetscViewerStringSPrintf(viewer," order=%s",lu->ordering);CHKERRQ(ierr);CHKERRQ(ierr);
176   } else {
177     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCCholesky",((PetscObject)viewer)->type_name);
178   }
179   PetscFunctionReturn(0);
180 }
181 
182 #undef __FUNCT__
183 #define __FUNCT__ "PCGetFactoredMatrix_Cholesky"
184 static PetscErrorCode PCGetFactoredMatrix_Cholesky(PC pc,Mat *mat)
185 {
186   PC_Cholesky *dir = (PC_Cholesky*)pc->data;
187 
188   PetscFunctionBegin;
189   if (!dir->fact) SETERRQ(PETSC_ERR_ORDER,"Matrix not yet factored; call after KSPSetUp() or PCSetUp()");
190   *mat = dir->fact;
191   PetscFunctionReturn(0);
192 }
193 
194 #undef __FUNCT__
195 #define __FUNCT__ "PCSetUp_Cholesky"
196 static PetscErrorCode PCSetUp_Cholesky(PC pc)
197 {
198   PetscErrorCode ierr;
199   PetscTruth     flg;
200   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;
201 
202   PetscFunctionBegin;
203   if (dir->reusefill && pc->setupcalled) dir->info.fill = dir->actualfill;
204 
205   if (dir->inplace) {
206     if (dir->row && dir->col && (dir->row != dir->col)) {
207       ierr = ISDestroy(dir->row);CHKERRQ(ierr);
208       dir->row = 0;
209     }
210     if (dir->col) {
211       ierr = ISDestroy(dir->col);CHKERRQ(ierr);
212       dir->col = 0;
213     }
214     ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
215     if (dir->col && (dir->row != dir->col)) {  /* only use row ordering for SBAIJ */
216       ierr = ISDestroy(dir->col);CHKERRQ(ierr);
217       dir->col=0;
218     }
219     if (dir->row) {ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);}
220     ierr = MatCholeskyFactor(pc->pmat,dir->row,&dir->info);CHKERRQ(ierr);
221     dir->fact = pc->pmat;
222   } else {
223     MatInfo info;
224     if (!pc->setupcalled) {
225       ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
226       if (dir->col && (dir->row != dir->col)) {  /* only use row ordering for SBAIJ */
227         ierr = ISDestroy(dir->col);CHKERRQ(ierr);
228         dir->col=0;
229       }
230       ierr = PetscOptionsHasName(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&flg);CHKERRQ(ierr);
231       if (flg) {
232         PetscReal tol = 1.e-10;
233         ierr = PetscOptionsGetReal(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&tol,PETSC_NULL);CHKERRQ(ierr);
234         ierr = MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);CHKERRQ(ierr);
235       }
236       if (dir->row) {ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);}
237       ierr = MatCholeskyFactorSymbolic(pc->pmat,dir->row,&dir->info,&dir->fact);CHKERRQ(ierr);
238       ierr = MatGetInfo(dir->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
239       dir->actualfill = info.fill_ratio_needed;
240       ierr = PetscLogObjectParent(pc,dir->fact);CHKERRQ(ierr);
241     } else if (pc->flag != SAME_NONZERO_PATTERN) {
242       if (!dir->reuseordering) {
243         if (dir->row && dir->col && (dir->row != dir->col)) {
244           ierr = ISDestroy(dir->row);CHKERRQ(ierr);
245           dir->row = 0;
246         }
247         if (dir->col) {
248           ierr = ISDestroy(dir->col);CHKERRQ(ierr);
249           dir->col =0;
250         }
251         ierr = MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);CHKERRQ(ierr);
252         if (dir->col && (dir->row != dir->col)) {  /* only use row ordering for SBAIJ */
253           ierr = ISDestroy(dir->col);CHKERRQ(ierr);
254           dir->col=0;
255         }
256         ierr = PetscOptionsHasName(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&flg);CHKERRQ(ierr);
257         if (flg) {
258           PetscReal tol = 1.e-10;
259           ierr = PetscOptionsGetReal(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&tol,PETSC_NULL);CHKERRQ(ierr);
260           ierr = MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);CHKERRQ(ierr);
261         }
262         if (dir->row) {ierr = PetscLogObjectParent(pc,dir->row);CHKERRQ(ierr);}
263       }
264       ierr = MatDestroy(dir->fact);CHKERRQ(ierr);
265       ierr = MatCholeskyFactorSymbolic(pc->pmat,dir->row,&dir->info,&dir->fact);CHKERRQ(ierr);
266       ierr = MatGetInfo(dir->fact,MAT_LOCAL,&info);CHKERRQ(ierr);
267       dir->actualfill = info.fill_ratio_needed;
268       ierr = PetscLogObjectParent(pc,dir->fact);CHKERRQ(ierr);
269     }
270     ierr = MatCholeskyFactorNumeric(pc->pmat,&dir->info,&dir->fact);CHKERRQ(ierr);
271   }
272   PetscFunctionReturn(0);
273 }
274 
275 #undef __FUNCT__
276 #define __FUNCT__ "PCDestroy_Cholesky"
277 static PetscErrorCode PCDestroy_Cholesky(PC pc)
278 {
279   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;
280   PetscErrorCode ierr;
281 
282   PetscFunctionBegin;
283   if (!dir->inplace && dir->fact) {ierr = MatDestroy(dir->fact);CHKERRQ(ierr);}
284   if (dir->row) {ierr = ISDestroy(dir->row);CHKERRQ(ierr);}
285   if (dir->col) {ierr = ISDestroy(dir->col);CHKERRQ(ierr);}
286   ierr = PetscStrfree(dir->ordering);CHKERRQ(ierr);
287   ierr = PetscFree(dir);CHKERRQ(ierr);
288   PetscFunctionReturn(0);
289 }
290 
291 #undef __FUNCT__
292 #define __FUNCT__ "PCApply_Cholesky"
293 static PetscErrorCode PCApply_Cholesky(PC pc,Vec x,Vec y)
294 {
295   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;
296   PetscErrorCode ierr;
297 
298   PetscFunctionBegin;
299   if (dir->inplace) {ierr = MatSolve(pc->pmat,x,y);CHKERRQ(ierr);}
300   else              {ierr = MatSolve(dir->fact,x,y);CHKERRQ(ierr);}
301   PetscFunctionReturn(0);
302 }
303 
304 #undef __FUNCT__
305 #define __FUNCT__ "PCApplyTranspose_Cholesky"
306 static PetscErrorCode PCApplyTranspose_Cholesky(PC pc,Vec x,Vec y)
307 {
308   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;
309   PetscErrorCode ierr;
310 
311   PetscFunctionBegin;
312   if (dir->inplace) {ierr = MatSolveTranspose(pc->pmat,x,y);CHKERRQ(ierr);}
313   else              {ierr = MatSolveTranspose(dir->fact,x,y);CHKERRQ(ierr);}
314   PetscFunctionReturn(0);
315 }
316 
317 /* -----------------------------------------------------------------------------------*/
318 
319 EXTERN_C_BEGIN
320 #undef __FUNCT__
321 #define __FUNCT__ "PCCholeskySetFill_Cholesky"
322 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetFill_Cholesky(PC pc,PetscReal fill)
323 {
324   PC_Cholesky *dir;
325 
326   PetscFunctionBegin;
327   dir = (PC_Cholesky*)pc->data;
328   dir->info.fill = fill;
329   PetscFunctionReturn(0);
330 }
331 EXTERN_C_END
332 
333 EXTERN_C_BEGIN
334 #undef __FUNCT__
335 #define __FUNCT__ "PCCholeskySetUseInPlace_Cholesky"
336 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetUseInPlace_Cholesky(PC pc)
337 {
338   PC_Cholesky *dir;
339 
340   PetscFunctionBegin;
341   dir = (PC_Cholesky*)pc->data;
342   dir->inplace = PETSC_TRUE;
343   PetscFunctionReturn(0);
344 }
345 EXTERN_C_END
346 
347 EXTERN_C_BEGIN
348 #undef __FUNCT__
349 #define __FUNCT__ "PCCholeskySetMatOrdering_Cholesky"
350 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetMatOrdering_Cholesky(PC pc,MatOrderingType ordering)
351 {
352   PC_Cholesky    *dir = (PC_Cholesky*)pc->data;
353   PetscErrorCode ierr;
354 
355   PetscFunctionBegin;
356   ierr = PetscStrfree(dir->ordering);CHKERRQ(ierr);
357   ierr = PetscStrallocpy(ordering,&dir->ordering);CHKERRQ(ierr);
358   PetscFunctionReturn(0);
359 }
360 EXTERN_C_END
361 
362 /* -----------------------------------------------------------------------------------*/
363 
364 #undef __FUNCT__
365 #define __FUNCT__ "PCCholeskySetReuseOrdering"
366 /*@
367    PCCholeskySetReuseOrdering - When similar matrices are factored, this
368    causes the ordering computed in the first factor to be used for all
369    following factors.
370 
371    Collective on PC
372 
373    Input Parameters:
374 +  pc - the preconditioner context
375 -  flag - PETSC_TRUE to reuse else PETSC_FALSE
376 
377    Options Database Key:
378 .  -pc_cholesky_reuse_ordering - Activate PCCholeskySetReuseOrdering()
379 
380    Level: intermediate
381 
382 .keywords: PC, levels, reordering, factorization, incomplete, LU
383 
384 .seealso: PCCholeskySetReuseFill(), PCICholeskySetReuseOrdering(), PCICholeskyDTSetReuseFill()
385 @*/
386 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseOrdering(PC pc,PetscTruth flag)
387 {
388   PetscErrorCode ierr,(*f)(PC,PetscTruth);
389 
390   PetscFunctionBegin;
391   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
392   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetReuseOrdering_C",(void (**)(void))&f);CHKERRQ(ierr);
393   if (f) {
394     ierr = (*f)(pc,flag);CHKERRQ(ierr);
395   }
396   PetscFunctionReturn(0);
397 }
398 
399 #undef __FUNCT__
400 #define __FUNCT__ "PCCholeskySetReuseFill"
401 /*@
402    PCCholeskySetReuseFill - When matrices with same nonzero structure are Cholesky factored,
403    this causes later ones to use the fill computed in the initial factorization.
404 
405    Collective on PC
406 
407    Input Parameters:
408 +  pc - the preconditioner context
409 -  flag - PETSC_TRUE to reuse else PETSC_FALSE
410 
411    Options Database Key:
412 .  -pc_cholesky_reuse_fill - Activates PCCholeskySetReuseFill()
413 
414    Level: intermediate
415 
416 .keywords: PC, levels, reordering, factorization, incomplete, Cholesky
417 
418 .seealso: PCICholeskySetReuseOrdering(), PCCholeskySetReuseOrdering(), PCICholeskyDTSetReuseFill()
419 @*/
420 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseFill(PC pc,PetscTruth flag)
421 {
422   PetscErrorCode ierr,(*f)(PC,PetscTruth);
423 
424   PetscFunctionBegin;
425   PetscValidHeaderSpecific(pc,PC_COOKIE,2);
426   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetReuseFill_C",(void (**)(void))&f);CHKERRQ(ierr);
427   if (f) {
428     ierr = (*f)(pc,flag);CHKERRQ(ierr);
429   }
430   PetscFunctionReturn(0);
431 }
432 
433 #undef __FUNCT__
434 #define __FUNCT__ "PCCholeskySetFill"
435 /*@
436    PCCholeskySetFill - Indicates the amount of fill you expect in the factored matrix,
437    fill = number nonzeros in factor/number nonzeros in original matrix.
438 
439    Collective on PC
440 
441    Input Parameters:
442 +  pc - the preconditioner context
443 -  fill - amount of expected fill
444 
445    Options Database Key:
446 .  -pc_cholesky_fill <fill> - Sets fill amount
447 
448    Level: intermediate
449 
450    Note:
451    For sparse matrix factorizations it is difficult to predict how much
452    fill to expect. By running with the option -log_info PETSc will print the
453    actual amount of fill used; allowing you to set the value accurately for
454    future runs. Default PETSc uses a value of 5.0
455 
456 .keywords: PC, set, factorization, direct, fill
457 
458 .seealso: PCILUSetFill()
459 @*/
460 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetFill(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,"PCCholeskySetFill_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__ "PCCholeskySetUseInPlace"
476 /*@
477    PCCholeskySetUseInPlace - 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_cholesky_in_place - Activates in-place factorization
491 
492    Notes:
493    PCCholeskySetUseInplace() 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, Cholesky
503 
504 .seealso: PCICholeskySetUseInPlace()
505 @*/
506 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetUseInPlace(PC pc)
507 {
508   PetscErrorCode ierr,(*f)(PC);
509 
510   PetscFunctionBegin;
511   PetscValidHeaderSpecific(pc,PC_COOKIE,1);
512   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetUseInPlace_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__ "PCCholeskySetMatOrdering"
521 /*@
522     PCCholeskySetMatOrdering - Sets the ordering routine (to reduce fill) to
523     be used it the Cholesky 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_cholesky_mat_ordering_type <nd,rcm,...> - Sets ordering routine
533 
534     Level: intermediate
535 
536 .seealso: PCICholeskySetMatOrdering()
537 @*/
538 PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetMatOrdering(PC pc,MatOrderingType ordering)
539 {
540   PetscErrorCode ierr,(*f)(PC,MatOrderingType);
541 
542   PetscFunctionBegin;
543   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetMatOrdering_C",(void (**)(void))&f);CHKERRQ(ierr);
544   if (f) {
545     ierr = (*f)(pc,ordering);CHKERRQ(ierr);
546   }
547   PetscFunctionReturn(0);
548 }
549 
550 /*MC
551    PCCholesky - Uses a direct solver, based on Cholesky factorization, as a preconditioner
552 
553    Options Database Keys:
554 +  -pc_cholesky_reuse_ordering - Activate PCLUSetReuseOrdering()
555 .  -pc_cholesky_reuse_fill - Activates PCLUSetReuseFill()
556 .  -pc_cholesky_fill <fill> - Sets fill amount
557 .  -pc_cholesky_in_place - Activates in-place factorization
558 .  -pc_cholesky_mat_ordering_type <nd,rcm,...> - Sets ordering routine
559 .  -pc_factor_shift_nonzero <shift> - Sets shift amount or PETSC_DECIDE for the default
560 -  -pc_factor_shift_positive_definite [PETSC_TRUE/PETSC_FALSE] - Activate/Deactivate PCFactorSetShiftPd(); the value
561    is optional with PETSC_TRUE being the default
562 
563    Notes: Not all options work for all matrix formats
564 
565    Level: beginner
566 
567    Concepts: Cholesky factorization, direct solver
568 
569    Notes: Usually this will compute an "exact" solution in one iteration and does
570           not need a Krylov method (i.e. you can use -ksp_type preonly, or
571           KSPSetType(ksp,KSPPREONLY) for the Krylov method
572 
573 .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
574            PCILU, PCLU, PCICC, PCCholeskySetReuseOrdering(), PCCholeskySetReuseFill(), PCGetFactoredMatrix(),
575            PCCholeskySetFill(), PCFactorSetShiftNonzero(), PCFactorSetShiftPd(),
576 	   PCCholeskySetUseInPlace(), PCCholeskySetMatOrdering(),PCFactorSetShiftNonzero(),PCFactorSetShiftPd()
577 
578 M*/
579 
580 EXTERN_C_BEGIN
581 #undef __FUNCT__
582 #define __FUNCT__ "PCCreate_Cholesky"
583 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Cholesky(PC pc)
584 {
585   PetscErrorCode ierr;
586   PC_Cholesky    *dir;
587 
588   PetscFunctionBegin;
589   ierr = PetscNew(PC_Cholesky,&dir);CHKERRQ(ierr);
590   ierr = PetscLogObjectMemory(pc,sizeof(PC_Cholesky));CHKERRQ(ierr);
591 
592   dir->fact                   = 0;
593   dir->inplace                = PETSC_FALSE;
594   ierr = MatFactorInfoInitialize(&dir->info);CHKERRQ(ierr);
595   dir->info.fill              = 5.0;
596   dir->info.shiftnz           = 0.0;
597   dir->info.shiftpd           = 0.0; /* false */
598   dir->info.shift_fraction    = 0.0;
599   dir->info.pivotinblocks     = 1.0;
600   dir->col                    = 0;
601   dir->row                    = 0;
602   ierr = PetscStrallocpy(MATORDERING_NATURAL,&dir->ordering);CHKERRQ(ierr);
603   dir->reusefill        = PETSC_FALSE;
604   dir->reuseordering    = PETSC_FALSE;
605   pc->data              = (void*)dir;
606 
607   pc->ops->destroy           = PCDestroy_Cholesky;
608   pc->ops->apply             = PCApply_Cholesky;
609   pc->ops->applytranspose    = PCApplyTranspose_Cholesky;
610   pc->ops->setup             = PCSetUp_Cholesky;
611   pc->ops->setfromoptions    = PCSetFromOptions_Cholesky;
612   pc->ops->view              = PCView_Cholesky;
613   pc->ops->applyrichardson   = 0;
614   pc->ops->getfactoredmatrix = PCGetFactoredMatrix_Cholesky;
615 
616   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_Cholesky",
617                     PCFactorSetZeroPivot_Cholesky);CHKERRQ(ierr);
618   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftNonzero_C","PCFactorSetShiftNonzero_Cholesky",
619                     PCFactorSetShiftNonzero_Cholesky);CHKERRQ(ierr);
620   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftPd_C","PCFactorSetShiftPd_Cholesky",
621                     PCFactorSetShiftPd_Cholesky);CHKERRQ(ierr);
622 
623   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetFill_C","PCCholeskySetFill_Cholesky",
624                     PCCholeskySetFill_Cholesky);CHKERRQ(ierr);
625   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetUseInPlace_C","PCCholeskySetUseInPlace_Cholesky",
626                     PCCholeskySetUseInPlace_Cholesky);CHKERRQ(ierr);
627   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetMatOrdering_C","PCCholeskySetMatOrdering_Cholesky",
628                     PCCholeskySetMatOrdering_Cholesky);CHKERRQ(ierr);
629   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetReuseOrdering_C","PCCholeskySetReuseOrdering_Cholesky",
630                     PCCholeskySetReuseOrdering_Cholesky);CHKERRQ(ierr);
631   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetReuseFill_C","PCCholeskySetReuseFill_Cholesky",
632                     PCCholeskySetReuseFill_Cholesky);CHKERRQ(ierr);
633   PetscFunctionReturn(0);
634 }
635 EXTERN_C_END
636