Actual source code: cholesky.c
1: #define PETSCKSP_DLL
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
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;
24: PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetZeroPivot_Cholesky(PC pc,PetscReal z)
25: {
26: PC_Cholesky *ch;
29: ch = (PC_Cholesky*)pc->data;
30: ch->info.zeropivot = z;
31: return(0);
32: }
38: PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftNonzero_Cholesky(PC pc,PetscReal shift)
39: {
40: PC_Cholesky *dir;
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: return(0);
50: }
56: PetscErrorCode PETSCKSP_DLLEXPORT PCFactorSetShiftPd_Cholesky(PC pc,PetscTruth shift)
57: {
58: PC_Cholesky *dir;
59:
61: dir = (PC_Cholesky*)pc->data;
62: dir->info.shiftpd = shift;
63: if (shift) dir->info.shift_fraction = 0.0;
64: return(0);
65: }
71: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseOrdering_Cholesky(PC pc,PetscTruth flag)
72: {
73: PC_Cholesky *lu;
74:
76: lu = (PC_Cholesky*)pc->data;
77: lu->reuseordering = flag;
78: return(0);
79: }
85: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseFill_Cholesky(PC pc,PetscTruth flag)
86: {
87: PC_Cholesky *lu;
88:
90: lu = (PC_Cholesky*)pc->data;
91: lu->reusefill = flag;
92: return(0);
93: }
98: static PetscErrorCode PCSetFromOptions_Cholesky(PC pc)
99: {
100: PC_Cholesky *lu = (PC_Cholesky*)pc->data;
102: PetscTruth flg;
103: char tname[256];
104: PetscFList ordlist;
105:
107: MatOrderingRegisterAll(PETSC_NULL);
108: PetscOptionsHead("Cholesky options");
109: PetscOptionsName("-pc_cholesky_in_place","Form Cholesky in the same memory as the matrix","PCCholeskySetUseInPlace",&flg);
110: if (flg) {
111: PCCholeskySetUseInPlace(pc);
112: }
113: PetscOptionsReal("-pc_cholesky_fill","Expected non-zeros in Cholesky/non-zeros in matrix","PCCholeskySetFill",lu->info.fill,&lu->info.fill,0);
114:
115: PetscOptionsName("-pc_cholesky_reuse_fill","Use fill from previous factorization","PCCholeskySetReuseFill",&flg);
116: if (flg) {
117: PCCholeskySetReuseFill(pc,PETSC_TRUE);
118: }
119: PetscOptionsName("-pc_cholesky_reuse_ordering","Reuse ordering from previous factorization","PCCholeskySetReuseOrdering",&flg);
120: if (flg) {
121: PCCholeskySetReuseOrdering(pc,PETSC_TRUE);
122: }
123:
124: MatGetOrderingList(&ordlist);
125: PetscOptionsList("-pc_cholesky_mat_ordering_type","Reordering to reduce nonzeros in Cholesky","PCCholeskySetMatOrdering",ordlist,lu->ordering,tname,256,&flg);
126: if (flg) {
127: PCCholeskySetMatOrdering(pc,tname);
128: }
129: PetscOptionsName("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",&flg);
130: if (flg) {
131: PCFactorSetShiftNonzero(pc,(PetscReal) PETSC_DECIDE);
132: }
133: PetscOptionsReal("-pc_factor_shift_nonzero","Shift added to diagonal","PCFactorSetShiftNonzero",lu->info.shiftnz,&lu->info.shiftnz,0);
134: PetscOptionsName("-pc_factor_shift_positive_definite","Manteuffel shift applied to diagonal","PCFactorSetShiftPd",&flg);
135: if (flg) {
136: PCFactorSetShiftPd(pc,PETSC_TRUE);
137: }
138: PetscOptionsReal("-pc_factor_zeropivot","Pivot is considered zero if less than","PCFactorSetZeroPivot",lu->info.zeropivot,&lu->info.zeropivot,0);
140: PetscOptionsTail();
141: return(0);
142: }
146: static PetscErrorCode PCView_Cholesky(PC pc,PetscViewer viewer)
147: {
148: PC_Cholesky *lu = (PC_Cholesky*)pc->data;
150: PetscTruth iascii,isstring;
151:
153: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);
154: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
155: if (iascii) {
156: MatInfo info;
157:
158: if (lu->inplace) {PetscViewerASCIIPrintf(viewer," Cholesky: in-place factorization\n");}
159: else {PetscViewerASCIIPrintf(viewer," Cholesky: out-of-place factorization\n");}
160: PetscViewerASCIIPrintf(viewer," matrix ordering: %s\n",lu->ordering);
161: if (lu->fact) {
162: MatGetInfo(lu->fact,MAT_LOCAL,&info);
163: PetscViewerASCIIPrintf(viewer," Cholesky nonzeros %g\n",info.nz_used);
164: PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_FACTOR_INFO);
165: MatView(lu->fact,viewer);
166: PetscViewerPopFormat(viewer);
167: }
168: if (lu->reusefill) {PetscViewerASCIIPrintf(viewer," Reusing fill from past factorization\n");}
169: if (lu->reuseordering) {PetscViewerASCIIPrintf(viewer," Reusing reordering from past factorization\n");}
170: } else if (isstring) {
171: PetscViewerStringSPrintf(viewer," order=%s",lu->ordering);
172: } else {
173: SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for PCCholesky",((PetscObject)viewer)->type_name);
174: }
175: return(0);
176: }
180: static PetscErrorCode PCGetFactoredMatrix_Cholesky(PC pc,Mat *mat)
181: {
182: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
183:
185: if (!dir->fact) SETERRQ(PETSC_ERR_ORDER,"Matrix not yet factored; call after KSPSetUp() or PCSetUp()");
186: *mat = dir->fact;
187: return(0);
188: }
192: static PetscErrorCode PCSetUp_Cholesky(PC pc)
193: {
195: PetscTruth flg;
196: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
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: ISDestroy(dir->row);
204: dir->row = 0;
205: }
206: if (dir->col) {
207: ISDestroy(dir->col);
208: dir->col = 0;
209: }
210: MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);
211: if (dir->col && (dir->row != dir->col)) { /* only use row ordering for SBAIJ */
212: ISDestroy(dir->col);
213: dir->col=0;
214: }
215: if (dir->row) {PetscLogObjectParent(pc,dir->row);}
216: MatCholeskyFactor(pc->pmat,dir->row,&dir->info);
217: dir->fact = pc->pmat;
218: } else {
219: MatInfo info;
220: if (!pc->setupcalled) {
221: MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);
222: if (dir->col && (dir->row != dir->col)) { /* only use row ordering for SBAIJ */
223: ISDestroy(dir->col);
224: dir->col=0;
225: }
226: PetscOptionsHasName(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&flg);
227: if (flg) {
228: PetscReal tol = 1.e-10;
229: PetscOptionsGetReal(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&tol,PETSC_NULL);
230: MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);
231: }
232: if (dir->row) {PetscLogObjectParent(pc,dir->row);}
233: MatCholeskyFactorSymbolic(pc->pmat,dir->row,&dir->info,&dir->fact);
234: MatGetInfo(dir->fact,MAT_LOCAL,&info);
235: dir->actualfill = info.fill_ratio_needed;
236: PetscLogObjectParent(pc,dir->fact);
237: } else if (pc->flag != SAME_NONZERO_PATTERN) {
238: if (!dir->reuseordering) {
239: if (dir->row && dir->col && (dir->row != dir->col)) {
240: ISDestroy(dir->row);
241: dir->row = 0;
242: }
243: if (dir->col) {
244: ISDestroy(dir->col);
245: dir->col =0;
246: }
247: MatGetOrdering(pc->pmat,dir->ordering,&dir->row,&dir->col);
248: if (dir->col && (dir->row != dir->col)) { /* only use row ordering for SBAIJ */
249: ISDestroy(dir->col);
250: dir->col=0;
251: }
252: PetscOptionsHasName(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&flg);
253: if (flg) {
254: PetscReal tol = 1.e-10;
255: PetscOptionsGetReal(pc->prefix,"-pc_cholesky_nonzeros_along_diagonal",&tol,PETSC_NULL);
256: MatReorderForNonzeroDiagonal(pc->pmat,tol,dir->row,dir->row);
257: }
258: if (dir->row) {PetscLogObjectParent(pc,dir->row);}
259: }
260: MatDestroy(dir->fact);
261: MatCholeskyFactorSymbolic(pc->pmat,dir->row,&dir->info,&dir->fact);
262: MatGetInfo(dir->fact,MAT_LOCAL,&info);
263: dir->actualfill = info.fill_ratio_needed;
264: PetscLogObjectParent(pc,dir->fact);
265: }
266: MatCholeskyFactorNumeric(pc->pmat,&dir->info,&dir->fact);
267: }
268: return(0);
269: }
273: static PetscErrorCode PCDestroy_Cholesky(PC pc)
274: {
275: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
279: if (!dir->inplace && dir->fact) {MatDestroy(dir->fact);}
280: if (dir->row) {ISDestroy(dir->row);}
281: if (dir->col) {ISDestroy(dir->col);}
282: PetscStrfree(dir->ordering);
283: PetscFree(dir);
284: return(0);
285: }
289: static PetscErrorCode PCApply_Cholesky(PC pc,Vec x,Vec y)
290: {
291: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
293:
295: if (dir->inplace) {MatSolve(pc->pmat,x,y);}
296: else {MatSolve(dir->fact,x,y);}
297: return(0);
298: }
302: static PetscErrorCode PCApplyTranspose_Cholesky(PC pc,Vec x,Vec y)
303: {
304: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
308: if (dir->inplace) {MatSolveTranspose(pc->pmat,x,y);}
309: else {MatSolveTranspose(dir->fact,x,y);}
310: return(0);
311: }
313: /* -----------------------------------------------------------------------------------*/
318: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetFill_Cholesky(PC pc,PetscReal fill)
319: {
320: PC_Cholesky *dir;
321:
323: dir = (PC_Cholesky*)pc->data;
324: dir->info.fill = fill;
325: return(0);
326: }
332: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetUseInPlace_Cholesky(PC pc)
333: {
334: PC_Cholesky *dir;
337: dir = (PC_Cholesky*)pc->data;
338: dir->inplace = PETSC_TRUE;
339: return(0);
340: }
346: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetMatOrdering_Cholesky(PC pc,MatOrderingType ordering)
347: {
348: PC_Cholesky *dir = (PC_Cholesky*)pc->data;
352: PetscStrfree(dir->ordering);
353: PetscStrallocpy(ordering,&dir->ordering);
354: return(0);
355: }
358: /* -----------------------------------------------------------------------------------*/
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.
367: Collective on PC
369: Input Parameters:
370: + pc - the preconditioner context
371: - flag - PETSC_TRUE to reuse else PETSC_FALSE
373: Options Database Key:
374: . -pc_cholesky_reuse_ordering - Activate PCCholeskySetReuseOrdering()
376: Level: intermediate
378: .keywords: PC, levels, reordering, factorization, incomplete, LU
380: .seealso: PCCholeskySetReuseFill(), PCICholeskySetReuseOrdering(), PCICholeskyDTSetReuseFill()
381: @*/
382: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseOrdering(PC pc,PetscTruth flag)
383: {
384: PetscErrorCode ierr,(*f)(PC,PetscTruth);
388: PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetReuseOrdering_C",(void (**)(void))&f);
389: if (f) {
390: (*f)(pc,flag);
391: }
392: return(0);
393: }
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.
401: Collective on PC
403: Input Parameters:
404: + pc - the preconditioner context
405: - flag - PETSC_TRUE to reuse else PETSC_FALSE
407: Options Database Key:
408: . -pc_cholesky_reuse_fill - Activates PCCholeskySetReuseFill()
410: Level: intermediate
412: .keywords: PC, levels, reordering, factorization, incomplete, Cholesky
414: .seealso: PCICholeskySetReuseOrdering(), PCCholeskySetReuseOrdering(), PCICholeskyDTSetReuseFill()
415: @*/
416: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetReuseFill(PC pc,PetscTruth flag)
417: {
418: PetscErrorCode ierr,(*f)(PC,PetscTruth);
422: PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetReuseFill_C",(void (**)(void))&f);
423: if (f) {
424: (*f)(pc,flag);
425: }
426: return(0);
427: }
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.
435: Collective on PC
436:
437: Input Parameters:
438: + pc - the preconditioner context
439: - fill - amount of expected fill
441: Options Database Key:
442: . -pc_cholesky_fill <fill> - Sets fill amount
444: Level: intermediate
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
452: .keywords: PC, set, factorization, direct, fill
454: .seealso: PCILUSetFill()
455: @*/
456: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetFill(PC pc,PetscReal fill)
457: {
458: PetscErrorCode ierr,(*f)(PC,PetscReal);
462: if (fill < 1.0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Fill factor cannot be less then 1.0");
463: PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetFill_C",(void (**)(void))&f);
464: if (f) {
465: (*f)(pc,fill);
466: }
467: return(0);
468: }
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.
480: Collective on PC
482: Input Parameters:
483: . pc - the preconditioner context
485: Options Database Key:
486: . -pc_cholesky_in_place - Activates in-place factorization
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.
496: Level: intermediate
498: .keywords: PC, set, factorization, direct, inplace, in-place, Cholesky
500: .seealso: PCICholeskySetUseInPlace()
501: @*/
502: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetUseInPlace(PC pc)
503: {
504: PetscErrorCode ierr,(*f)(PC);
508: PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetUseInPlace_C",(void (**)(void))&f);
509: if (f) {
510: (*f)(pc);
511: }
512: return(0);
513: }
517: /*@
518: PCCholeskySetMatOrdering - Sets the ordering routine (to reduce fill) to
519: be used it the Cholesky factorization.
521: Collective on PC
523: Input Parameters:
524: + pc - the preconditioner context
525: - ordering - the matrix ordering name, for example, MATORDERING_ND or MATORDERING_RCM
527: Options Database Key:
528: . -pc_cholesky_mat_ordering_type <nd,rcm,...> - Sets ordering routine
530: Level: intermediate
532: .seealso: PCICholeskySetMatOrdering()
533: @*/
534: PetscErrorCode PETSCKSP_DLLEXPORT PCCholeskySetMatOrdering(PC pc,MatOrderingType ordering)
535: {
536: PetscErrorCode ierr,(*f)(PC,MatOrderingType);
539: PetscObjectQueryFunction((PetscObject)pc,"PCCholeskySetMatOrdering_C",(void (**)(void))&f);
540: if (f) {
541: (*f)(pc,ordering);
542: }
543: return(0);
544: }
546: /*MC
547: PCCholesky - Uses a direct solver, based on Cholesky factorization, as a preconditioner
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: . -pc_factor_shift_nonzero <shift> - Sets shift amount or PETSC_DECIDE for the default
556: - -pc_factor_shift_positive_definite [PETSC_TRUE/PETSC_FALSE] - Activate/Deactivate PCFactorSetShiftPd(); the value
557: is optional with PETSC_TRUE being the default
559: Notes: Not all options work for all matrix formats
561: Level: beginner
563: Concepts: Cholesky factorization, direct solver
565: Notes: Usually this will compute an "exact" solution in one iteration and does
566: not need a Krylov method (i.e. you can use -ksp_type preonly, or
567: KSPSetType(ksp,KSPPREONLY) for the Krylov method
569: .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC,
570: PCILU, PCLU, PCICC, PCCholeskySetReuseOrdering(), PCCholeskySetReuseFill(), PCGetFactoredMatrix(),
571: PCCholeskySetFill(), PCFactorSetShiftNonzero(), PCFactorSetShiftPd(),
572: PCCholeskySetUseInPlace(), PCCholeskySetMatOrdering(),PCFactorSetShiftNonzero(),PCFactorSetShiftPd()
574: M*/
579: PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_Cholesky(PC pc)
580: {
582: PC_Cholesky *dir;
585: PetscNew(PC_Cholesky,&dir);
586: PetscLogObjectMemory(pc,sizeof(PC_Cholesky));
588: dir->fact = 0;
589: dir->inplace = PETSC_FALSE;
590: MatFactorInfoInitialize(&dir->info);
591: dir->info.fill = 5.0;
592: dir->info.shiftnz = 0.0;
593: dir->info.shiftpd = PETSC_FALSE;
594: dir->info.shift_fraction = 0.0;
595: dir->info.pivotinblocks = 1.0;
596: dir->col = 0;
597: dir->row = 0;
598: PetscStrallocpy(MATORDERING_NATURAL,&dir->ordering);
599: dir->reusefill = PETSC_FALSE;
600: dir->reuseordering = PETSC_FALSE;
601: pc->data = (void*)dir;
603: pc->ops->destroy = PCDestroy_Cholesky;
604: pc->ops->apply = PCApply_Cholesky;
605: pc->ops->applytranspose = PCApplyTranspose_Cholesky;
606: pc->ops->setup = PCSetUp_Cholesky;
607: pc->ops->setfromoptions = PCSetFromOptions_Cholesky;
608: pc->ops->view = PCView_Cholesky;
609: pc->ops->applyrichardson = 0;
610: pc->ops->getfactoredmatrix = PCGetFactoredMatrix_Cholesky;
612: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetZeroPivot_C","PCFactorSetZeroPivot_Cholesky",
613: PCFactorSetZeroPivot_Cholesky);
614: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftNonzero_C","PCFactorSetShiftNonzero_Cholesky",
615: PCFactorSetShiftNonzero_Cholesky);
616: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCFactorSetShiftPd_C","PCFactorSetShiftPd_Cholesky",
617: PCFactorSetShiftPd_Cholesky);
619: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetFill_C","PCCholeskySetFill_Cholesky",
620: PCCholeskySetFill_Cholesky);
621: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetUseInPlace_C","PCCholeskySetUseInPlace_Cholesky",
622: PCCholeskySetUseInPlace_Cholesky);
623: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetMatOrdering_C","PCCholeskySetMatOrdering_Cholesky",
624: PCCholeskySetMatOrdering_Cholesky);
625: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetReuseOrdering_C","PCCholeskySetReuseOrdering_Cholesky",
626: PCCholeskySetReuseOrdering_Cholesky);
627: PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCCholeskySetReuseFill_C","PCCholeskySetReuseFill_Cholesky",
628: PCCholeskySetReuseFill_Cholesky);
629: return(0);
630: }