xref: /petsc/src/ksp/pc/interface/pcset.c (revision d52a580b706c59ca78066c1e38754e45b6b56e2b)
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 @*/
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 @*/
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 @*/
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 @*/
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 @*/
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 @*/
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 @*/
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