1 /*
2 Routines to set PC methods and options.
3 */
4
5 #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/
6 #include <petscdm.h>
7
8 PetscBool PCRegisterAllCalled = PETSC_FALSE;
9 /*
10 Contains the list of registered PC routines
11 */
12 PetscFunctionList PCList = NULL;
13
14 /*@
15 PCSetType - Builds `PC` for a particular preconditioner type
16
17 Collective
18
19 Input Parameters:
20 + pc - the preconditioner context
21 - type - a known method, see `PCType` for possible values
22
23 Options Database Key:
24 . -pc_type <type> - Sets `PC` type
25
26 Notes:
27 Normally, it is best to use the `KSPSetFromOptions()` command and
28 then set the `PC` type from the options database rather than by using
29 this routine. Using the options database provides the user with
30 maximum flexibility in evaluating the many different preconditioners.
31 The `PCSetType()` routine is provided for those situations where it
32 is necessary to set the preconditioner independently of the command
33 line or options database. This might be the case, for example, when
34 the choice of preconditioner changes during the execution of the
35 program, and the user's application is taking responsibility for
36 choosing the appropriate preconditioner.
37
38 Level: intermediate
39
40 Developer Notes:
41 `PCRegister()` is used to add preconditioner types to `PCList` from which they
42 are accessed by `PCSetType()`.
43
44 .seealso: [](ch_ksp), `KSPSetType()`, `PCType`, `PCRegister()`, `PCCreate()`, `KSPGetPC()`
45 @*/
PCSetType(PC pc,PCType type)46 PetscErrorCode PCSetType(PC pc, PCType type)
47 {
48 PetscBool match;
49 PetscErrorCode (*r)(PC);
50
51 PetscFunctionBegin;
52 PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
53 PetscAssertPointer(type, 2);
54
55 PetscCall(PetscObjectTypeCompare((PetscObject)pc, type, &match));
56 if (match) PetscFunctionReturn(PETSC_SUCCESS);
57
58 PetscCall(PetscFunctionListFind(PCList, type, &r));
59 PetscCheck(r, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PC type %s", type);
60 /* Destroy the previous private PC context */
61 PetscTryTypeMethod(pc, destroy);
62
63 PetscCall(PetscFunctionListDestroy(&((PetscObject)pc)->qlist));
64 /* Reinitialize function pointers in PCOps structure */
65 PetscCall(PetscMemzero(pc->ops, sizeof(struct _PCOps)));
66 /* XXX Is this OK?? */
67 pc->modifysubmatrices = NULL;
68 pc->modifysubmatricesP = NULL;
69 /* Call the PCCreate_XXX routine for this particular preconditioner */
70 pc->setupcalled = PETSC_FALSE;
71
72 PetscCall(PetscObjectChangeTypeName((PetscObject)pc, type));
73 PetscCall((*r)(pc));
74 PetscFunctionReturn(PETSC_SUCCESS);
75 }
76
77 /*@
78 PCGetType - Gets the `PCType` (as a string) from the `PC`
79 context.
80
81 Not Collective
82
83 Input Parameter:
84 . pc - the preconditioner context
85
86 Output Parameter:
87 . type - name of preconditioner method
88
89 Level: intermediate
90
91 .seealso: [](ch_ksp), `PC`, `PCType`, `PCSetType()`
92 @*/
PCGetType(PC pc,PCType * type)93 PetscErrorCode PCGetType(PC pc, PCType *type)
94 {
95 PetscFunctionBegin;
96 PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
97 PetscAssertPointer(type, 2);
98 *type = ((PetscObject)pc)->type_name;
99 PetscFunctionReturn(PETSC_SUCCESS);
100 }
101
102 PETSC_INTERN PetscErrorCode PCGetDefaultType_Private(PC, const char *[]);
103
104 /*@
105 PCSetFromOptions - Sets `PC` options from the options database.
106
107 Collective
108
109 Input Parameter:
110 . pc - the preconditioner context
111
112 Options Database Key:
113 . -pc_type - name of type, for example `bjacobi`
114
115 Level: advanced
116
117 Notes:
118 This routine must be called before `PCSetUp()` if the user is to be
119 allowed to set the preconditioner method from the options database.
120
121 This is called from `KSPSetFromOptions()` so rarely needs to be called directly
122
123 .seealso: [](ch_ksp), `PC`, `PCSetType()`, `PCType`, `KSPSetFromOptions()`
124 @*/
PCSetFromOptions(PC pc)125 PetscErrorCode PCSetFromOptions(PC pc)
126 {
127 char type[256];
128 const char *def;
129 PetscBool flg;
130
131 PetscFunctionBegin;
132 PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
133
134 PetscCall(PCRegisterAll());
135 if (!((PetscObject)pc)->type_name) {
136 PetscCall(PCGetDefaultType_Private(pc, &def));
137 } else {
138 def = ((PetscObject)pc)->type_name;
139 }
140 PetscObjectOptionsBegin((PetscObject)pc);
141
142 PetscCall(PetscOptionsFList("-pc_type", "Preconditioner", "PCSetType", PCList, def, type, 256, &flg));
143 if (flg) {
144 PetscCall(PCSetType(pc, type));
145 } else if (!((PetscObject)pc)->type_name && def) {
146 PetscCall(PCSetType(pc, def));
147 }
148
149 PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &flg));
150 if (flg) goto skipoptions;
151
152 PetscCall(PetscOptionsBool("-pc_use_amat", "use Amat (instead of Pmat) to define preconditioner in nested inner solves", "PCSetUseAmat", pc->useAmat, &pc->useAmat, NULL));
153
154 PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
155
156 skipoptions:
157 /* process any options handlers added with PetscObjectAddOptionsHandler() */
158 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc, PetscOptionsObject));
159 PetscOptionsEnd();
160 pc->setfromoptionscalled++;
161 PetscFunctionReturn(PETSC_SUCCESS);
162 }
163
164 /*@
165 PCSetDM - Sets the `DM` that may be used by some preconditioners
166
167 Logically Collective
168
169 Input Parameters:
170 + pc - the preconditioner context
171 - dm - the `DM`, can be `NULL` to remove any current `DM`
172
173 Level: intermediate
174
175 Note:
176 Users generally call `KSPSetDM()`, `SNESSetDM()`, or `TSSetDM()` so this is rarely called directly
177
178 Developer Notes:
179 The routines KSP/SNES/TSSetDM() require `dm` to be non-`NULL`, but this one can be `NULL` since all it does is
180 replace the current `DM`
181
182 .seealso: [](ch_ksp), `PC`, `DM`, `PCGetDM()`, `KSPSetDM()`, `KSPGetDM()`, `SNESSetDM()`, `TSSetDM()`
183 @*/
PCSetDM(PC pc,DM dm)184 PetscErrorCode PCSetDM(PC pc, DM dm)
185 {
186 PetscFunctionBegin;
187 PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
188 if (dm) PetscCall(PetscObjectReference((PetscObject)dm));
189 PetscCall(DMDestroy(&pc->dm));
190 pc->dm = dm;
191 PetscFunctionReturn(PETSC_SUCCESS);
192 }
193
194 /*@
195 PCGetDM - Gets the `DM` that may be used by some preconditioners
196
197 Not Collective
198
199 Input Parameter:
200 . pc - the preconditioner context
201
202 Output Parameter:
203 . dm - the `DM`
204
205 Level: intermediate
206
207 .seealso: [](ch_ksp), `PC`, `DM`, `PCSetDM()`, `KSPSetDM()`, `KSPGetDM()`
208 @*/
PCGetDM(PC pc,DM * dm)209 PetscErrorCode PCGetDM(PC pc, DM *dm)
210 {
211 PetscFunctionBegin;
212 PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
213 *dm = pc->dm;
214 PetscFunctionReturn(PETSC_SUCCESS);
215 }
216
217 /*@
218 PCSetApplicationContext - Sets the optional user-defined context for the preconditioner
219
220 Logically Collective
221
222 Input Parameters:
223 + pc - the `PC` context
224 - ctx - optional user context
225
226 Level: advanced
227
228 Fortran Note:
229 This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
230 function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `PCGetApplicationContext()` for
231 an example.
232
233 .seealso: [](ch_ksp), `PC`, `PCGetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`, `PetscObjectCompose()`
234 @*/
PCSetApplicationContext(PC pc,PetscCtx ctx)235 PetscErrorCode PCSetApplicationContext(PC pc, PetscCtx ctx)
236 {
237 PetscFunctionBegin;
238 PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
239 pc->ctx = ctx;
240 PetscFunctionReturn(PETSC_SUCCESS);
241 }
242
243 /*@
244 PCGetApplicationContext - Gets the user-defined context for the preconditioner set with `PCSetApplicationContext()`
245
246 Not Collective
247
248 Input Parameter:
249 . pc - `PC` context
250
251 Output Parameter:
252 . ctx - user context
253
254 Level: intermediate
255
256 Fortran Note:
257 This only works when the context is a Fortran derived type or a `PetscObject`. Define `ctx` with
258 .vb
259 type(tUsertype), pointer :: ctx
260 .ve
261
262 .seealso: [](ch_ksp), `PC`, `PCSetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`
263 @*/
PCGetApplicationContext(PC pc,PetscCtxRt ctx)264 PetscErrorCode PCGetApplicationContext(PC pc, PetscCtxRt ctx)
265 {
266 PetscFunctionBegin;
267 PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
268 *(void **)ctx = pc->ctx;
269 PetscFunctionReturn(PETSC_SUCCESS);
270 }
271