xref: /petsc/src/ksp/pc/impls/factor/icc/icc.c (revision 2ff79c18c26c94ed8cb599682f680f231dca6444)
1 #include <../src/ksp/pc/impls/factor/icc/icc.h> /*I "petscpc.h" I*/
2 
3 static PetscErrorCode PCSetUp_ICC(PC pc)
4 {
5   PC_ICC        *icc  = (PC_ICC *)pc->data;
6   IS             perm = NULL, cperm = NULL;
7   MatInfo        info;
8   MatSolverType  stype;
9   MatFactorError err;
10   PetscBool      canuseordering;
11   const char    *prefix;
12 
13   PetscFunctionBegin;
14   pc->failedreason = PC_NOERROR;
15 
16   PetscCall(PCGetOptionsPrefix(pc, &prefix));
17   PetscCall(MatSetOptionsPrefixFactor(pc->pmat, prefix));
18 
19   PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure));
20   if (!pc->setupcalled) {
21     PetscCall(PCFactorSetUpMatSolverType(pc));
22     PetscCall(MatFactorGetCanUseOrdering(((PC_Factor *)icc)->fact, &canuseordering));
23     if (canuseordering) {
24       PetscCall(PCFactorSetDefaultOrdering_Factor(pc));
25       PetscCall(MatGetOrdering(pc->pmat, ((PC_Factor *)icc)->ordering, &perm, &cperm));
26     }
27     PetscCall(MatICCFactorSymbolic(((PC_Factor *)icc)->fact, pc->pmat, perm, &((PC_Factor *)icc)->info));
28   } else if (pc->flag != SAME_NONZERO_PATTERN) {
29     PetscCall(MatDestroy(&((PC_Factor *)icc)->fact));
30     PetscCall(PCFactorSetUpMatSolverType(pc));
31     PetscCall(MatFactorGetCanUseOrdering(((PC_Factor *)icc)->fact, &canuseordering));
32     if (canuseordering) {
33       PetscCall(PCFactorSetDefaultOrdering_Factor(pc));
34       PetscCall(MatGetOrdering(pc->pmat, ((PC_Factor *)icc)->ordering, &perm, &cperm));
35     }
36     PetscCall(MatICCFactorSymbolic(((PC_Factor *)icc)->fact, pc->pmat, perm, &((PC_Factor *)icc)->info));
37   }
38   PetscCall(MatGetInfo(((PC_Factor *)icc)->fact, MAT_LOCAL, &info));
39   icc->hdr.actualfill = info.fill_ratio_needed;
40 
41   PetscCall(ISDestroy(&cperm));
42   PetscCall(ISDestroy(&perm));
43 
44   PetscCall(MatFactorGetError(((PC_Factor *)icc)->fact, &err));
45   if (err) { /* FactorSymbolic() fails */
46     pc->failedreason = (PCFailedReason)err;
47     PetscFunctionReturn(PETSC_SUCCESS);
48   }
49 
50   PetscCall(MatCholeskyFactorNumeric(((PC_Factor *)icc)->fact, pc->pmat, &((PC_Factor *)icc)->info));
51   PetscCall(MatFactorGetError(((PC_Factor *)icc)->fact, &err));
52   if (err) { /* FactorNumeric() fails */
53     pc->failedreason = (PCFailedReason)err;
54   }
55 
56   PetscCall(PCFactorGetMatSolverType(pc, &stype));
57   if (!stype) {
58     MatSolverType solverpackage;
59     PetscCall(MatFactorGetSolverType(((PC_Factor *)icc)->fact, &solverpackage));
60     PetscCall(PCFactorSetMatSolverType(pc, solverpackage));
61   }
62   PetscFunctionReturn(PETSC_SUCCESS);
63 }
64 
65 static PetscErrorCode PCReset_ICC(PC pc)
66 {
67   PC_ICC *icc = (PC_ICC *)pc->data;
68 
69   PetscFunctionBegin;
70   PetscCall(MatDestroy(&((PC_Factor *)icc)->fact));
71   PetscFunctionReturn(PETSC_SUCCESS);
72 }
73 
74 static PetscErrorCode PCDestroy_ICC(PC pc)
75 {
76   PC_ICC *icc = (PC_ICC *)pc->data;
77 
78   PetscFunctionBegin;
79   PetscCall(PCReset_ICC(pc));
80   PetscCall(PetscFree(((PC_Factor *)icc)->ordering));
81   PetscCall(PetscFree(((PC_Factor *)icc)->solvertype));
82   PetscCall(PCFactorClearComposedFunctions(pc));
83   PetscCall(PetscFree(pc->data));
84   PetscFunctionReturn(PETSC_SUCCESS);
85 }
86 
87 static PetscErrorCode PCApply_ICC(PC pc, Vec x, Vec y)
88 {
89   PC_ICC *icc = (PC_ICC *)pc->data;
90 
91   PetscFunctionBegin;
92   PetscCall(MatSolve(((PC_Factor *)icc)->fact, x, y));
93   PetscFunctionReturn(PETSC_SUCCESS);
94 }
95 
96 static PetscErrorCode PCMatApply_ICC(PC pc, Mat X, Mat Y)
97 {
98   PC_ICC *icc = (PC_ICC *)pc->data;
99 
100   PetscFunctionBegin;
101   PetscCall(MatMatSolve(((PC_Factor *)icc)->fact, X, Y));
102   PetscFunctionReturn(PETSC_SUCCESS);
103 }
104 
105 static PetscErrorCode PCApplySymmetricLeft_ICC(PC pc, Vec x, Vec y)
106 {
107   PC_ICC *icc = (PC_ICC *)pc->data;
108 
109   PetscFunctionBegin;
110   PetscCall(MatForwardSolve(((PC_Factor *)icc)->fact, x, y));
111   PetscFunctionReturn(PETSC_SUCCESS);
112 }
113 
114 static PetscErrorCode PCApplySymmetricRight_ICC(PC pc, Vec x, Vec y)
115 {
116   PC_ICC *icc = (PC_ICC *)pc->data;
117 
118   PetscFunctionBegin;
119   PetscCall(MatBackwardSolve(((PC_Factor *)icc)->fact, x, y));
120   PetscFunctionReturn(PETSC_SUCCESS);
121 }
122 
123 static PetscErrorCode PCSetFromOptions_ICC(PC pc, PetscOptionItems PetscOptionsObject)
124 {
125   PC_ICC   *icc = (PC_ICC *)pc->data;
126   PetscBool flg;
127   /* PetscReal      dt[3];*/
128 
129   PetscFunctionBegin;
130   PetscOptionsHeadBegin(PetscOptionsObject, "ICC Options");
131   PetscCall(PCSetFromOptions_Factor(pc, PetscOptionsObject));
132 
133   PetscCall(PetscOptionsReal("-pc_factor_levels", "levels of fill", "PCFactorSetLevels", ((PC_Factor *)icc)->info.levels, &((PC_Factor *)icc)->info.levels, &flg));
134   /*dt[0] = ((PC_Factor*)icc)->info.dt;
135   dt[1] = ((PC_Factor*)icc)->info.dtcol;
136   dt[2] = ((PC_Factor*)icc)->info.dtcount;
137   PetscInt       dtmax = 3;
138   PetscCall(PetscOptionsRealArray("-pc_factor_drop_tolerance","<dt,dtcol,maxrowcount>","PCFactorSetDropTolerance",dt,&dtmax,&flg));
139   if (flg) PetscCall(PCFactorSetDropTolerance(pc,dt[0],dt[1],(PetscInt)dt[2]));
140   */
141   PetscOptionsHeadEnd();
142   PetscFunctionReturn(PETSC_SUCCESS);
143 }
144 
145 /*MC
146      PCICC - Incomplete Cholesky factorization preconditioners {cite}`chan1997approximate`
147 
148    Options Database Keys:
149 +  -pc_factor_levels <k>                                 - number of levels of fill for ICC(k)
150 .  -pc_factor_in_place                                   - only for ICC(0) with natural ordering, reuses the space of the matrix for
151                                                          its factorization (overwrites original matrix)
152 .  -pc_factor_fill <nfill>                               - expected amount of fill in factored matrix compared to original matrix, nfill > 1
153 -  -pc_factor_mat_ordering_type <natural,nd,1wd,rcm,qmd> - set the row/column ordering of the factored matrix
154 
155    Level: beginner
156 
157    Notes:
158    Only implemented for some matrix formats. Not implemented in parallel.
159 
160    For `MATSEQBAIJ` matrices this implements a point block ICC.
161 
162    By default, the Manteuffel shift {cite}`manteuffel1979shifted` is applied, for matrices with block size 1 only. Call `PCFactorSetShiftType`(pc,`MAT_SHIFT_POSITIVE_DEFINITE`);
163    to turn off the shift.
164 
165 .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCSOR`, `MatOrderingType`, `PCILU`, `PCLU`, `PCCHOLESKY`,
166           `PCFactorSetZeroPivot()`, `PCFactorSetShiftType()`, `PCFactorSetShiftAmount()`,
167           `PCFactorSetFill()`, `PCFactorSetMatOrderingType()`, `PCFactorSetReuseOrdering()`,
168           `PCFactorSetLevels()`
169 M*/
170 
171 PETSC_EXTERN PetscErrorCode PCCreate_ICC(PC pc)
172 {
173   PC_ICC *icc;
174 
175   PetscFunctionBegin;
176   PetscCall(PetscNew(&icc));
177   pc->data = (void *)icc;
178   PetscCall(PCFactorInitialize(pc, MAT_FACTOR_ICC));
179 
180   ((PC_Factor *)icc)->info.fill      = 1.0;
181   ((PC_Factor *)icc)->info.dtcol     = PETSC_DEFAULT;
182   ((PC_Factor *)icc)->info.shifttype = (PetscReal)MAT_SHIFT_POSITIVE_DEFINITE;
183 
184   pc->ops->apply               = PCApply_ICC;
185   pc->ops->matapply            = PCMatApply_ICC;
186   pc->ops->applytranspose      = PCApply_ICC;
187   pc->ops->matapplytranspose   = PCMatApply_ICC;
188   pc->ops->setup               = PCSetUp_ICC;
189   pc->ops->reset               = PCReset_ICC;
190   pc->ops->destroy             = PCDestroy_ICC;
191   pc->ops->setfromoptions      = PCSetFromOptions_ICC;
192   pc->ops->view                = PCView_Factor;
193   pc->ops->applysymmetricleft  = PCApplySymmetricLeft_ICC;
194   pc->ops->applysymmetricright = PCApplySymmetricRight_ICC;
195   PetscFunctionReturn(PETSC_SUCCESS);
196 }
197