xref: /petsc/src/ksp/pc/interface/pcset.c (revision 6dd63270497ad23dcf16ae500a87ff2b2a0b7474)
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   pc->ops->destroy = NULL;
63   pc->data         = NULL;
64 
65   PetscCall(PetscFunctionListDestroy(&((PetscObject)pc)->qlist));
66   /* Reinitialize function pointers in PCOps structure */
67   PetscCall(PetscMemzero(pc->ops, sizeof(struct _PCOps)));
68   /* XXX Is this OK?? */
69   pc->modifysubmatrices  = NULL;
70   pc->modifysubmatricesP = NULL;
71   /* Call the PCCreate_XXX routine for this particular preconditioner */
72   pc->setupcalled = 0;
73 
74   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, type));
75   PetscCall((*r)(pc));
76   PetscFunctionReturn(PETSC_SUCCESS);
77 }
78 
79 /*@
80   PCGetType - Gets the `PCType` (as a string) from the `PC`
81   context.
82 
83   Not Collective
84 
85   Input Parameter:
86 . pc - the preconditioner context
87 
88   Output Parameter:
89 . type - name of preconditioner method
90 
91   Level: intermediate
92 
93 .seealso: [](ch_ksp), `PC`, `PCType`, `PCSetType()`
94 @*/
95 PetscErrorCode PCGetType(PC pc, PCType *type)
96 {
97   PetscFunctionBegin;
98   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
99   PetscAssertPointer(type, 2);
100   *type = ((PetscObject)pc)->type_name;
101   PetscFunctionReturn(PETSC_SUCCESS);
102 }
103 
104 PETSC_INTERN PetscErrorCode PCGetDefaultType_Private(PC, const char *[]);
105 
106 /*@
107   PCSetFromOptions - Sets `PC` options from the options database.
108 
109   Collective
110 
111   Input Parameter:
112 . pc - the preconditioner context
113 
114   Options Database Key:
115 . -pc_type - name of type, for example `bjacobi`
116 
117   Level: advanced
118 
119   Notes:
120   This routine must be called before `PCSetUp()` if the user is to be
121   allowed to set the preconditioner method from the options database.
122 
123   This is called from `KSPSetFromOptions()` so rarely needs to be called directly
124 
125 .seealso: [](ch_ksp), `PC`, `PCSetType()`, `PCType`, `KSPSetFromOptions()`
126 @*/
127 PetscErrorCode PCSetFromOptions(PC pc)
128 {
129   char        type[256];
130   const char *def;
131   PetscBool   flg;
132 
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
135 
136   PetscCall(PCRegisterAll());
137   if (!((PetscObject)pc)->type_name) {
138     PetscCall(PCGetDefaultType_Private(pc, &def));
139   } else {
140     def = ((PetscObject)pc)->type_name;
141   }
142   PetscObjectOptionsBegin((PetscObject)pc);
143 
144   PetscCall(PetscOptionsFList("-pc_type", "Preconditioner", "PCSetType", PCList, def, type, 256, &flg));
145   if (flg) {
146     PetscCall(PCSetType(pc, type));
147   } else if (!((PetscObject)pc)->type_name && def) {
148     PetscCall(PCSetType(pc, def));
149   }
150 
151   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &flg));
152   if (flg) goto skipoptions;
153 
154   PetscCall(PetscOptionsBool("-pc_use_amat", "use Amat (instead of Pmat) to define preconditioner in nested inner solves", "PCSetUseAmat", pc->useAmat, &pc->useAmat, NULL));
155 
156   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
157 
158 skipoptions:
159   /* process any options handlers added with PetscObjectAddOptionsHandler() */
160   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc, PetscOptionsObject));
161   PetscOptionsEnd();
162   pc->setfromoptionscalled++;
163   PetscFunctionReturn(PETSC_SUCCESS);
164 }
165 
166 /*@
167   PCSetDM - Sets the `DM` that may be used by some preconditioners
168 
169   Logically Collective
170 
171   Input Parameters:
172 + pc - the preconditioner context
173 - dm - the `DM`, can be `NULL` to remove any current `DM`
174 
175   Level: intermediate
176 
177   Note:
178   Users generally call  `KSPSetDM()`, `SNESSetDM()`, or `TSSetDM()` so this is rarely called directly
179 
180   Developer Notes:
181   The routines KSP/SNES/TSSetDM() require `dm` to be non-`NULL`, but this one can be `NULL` since all it does is
182   replace the current `DM`
183 
184 .seealso: [](ch_ksp), `PC`, `DM`, `PCGetDM()`, `KSPSetDM()`, `KSPGetDM()`, `SNESSetDM()`, `TSSetDM()`
185 @*/
186 PetscErrorCode PCSetDM(PC pc, DM dm)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
190   if (dm) PetscCall(PetscObjectReference((PetscObject)dm));
191   PetscCall(DMDestroy(&pc->dm));
192   pc->dm = dm;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 /*@
197   PCGetDM - Gets the `DM` that may be used by some preconditioners
198 
199   Not Collective
200 
201   Input Parameter:
202 . pc - the preconditioner context
203 
204   Output Parameter:
205 . dm - the `DM`
206 
207   Level: intermediate
208 
209 .seealso: [](ch_ksp), `PC`, `DM`, `PCSetDM()`, `KSPSetDM()`, `KSPGetDM()`
210 @*/
211 PetscErrorCode PCGetDM(PC pc, DM *dm)
212 {
213   PetscFunctionBegin;
214   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
215   *dm = pc->dm;
216   PetscFunctionReturn(PETSC_SUCCESS);
217 }
218 
219 /*@
220   PCSetApplicationContext - Sets the optional user-defined context for the preconditioner
221 
222   Logically Collective
223 
224   Input Parameters:
225 + pc  - the `PC` context
226 - ctx - optional user context
227 
228   Level: advanced
229 
230   Fortran Note:
231   This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
232   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `PCGetApplicationContext()` for
233   an example.
234 
235 .seealso: [](ch_ksp), `PC`, `PCGetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`, `PetscObjectCompose()`
236 @*/
237 PetscErrorCode PCSetApplicationContext(PC pc, void *ctx)
238 {
239   PetscFunctionBegin;
240   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
241   pc->ctx = ctx;
242   PetscFunctionReturn(PETSC_SUCCESS);
243 }
244 
245 /*@
246   PCGetApplicationContext - Gets the user-defined context for the preconditioner set with `PCSetApplicationContext()`
247 
248   Not Collective
249 
250   Input Parameter:
251 . pc - `PC` context
252 
253   Output Parameter:
254 . ctx - user context
255 
256   Level: intermediate
257 
258   Fortran Notes:
259   This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this
260   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
261 .vb
262   Interface PCGetApplicationContext
263     Subroutine PCGetApplicationContext(pc,ctx,ierr)
264   #include <petsc/finclude/petscpc.h>
265       use petscpc
266       PC pc
267       type(tUsertype), pointer :: ctx
268       PetscErrorCode ierr
269     End Subroutine
270   End Interface PCGetApplicationContext
271 .ve
272 
273   The prototpye for `ctx` must be
274 .vb
275   type(tUsertype), pointer :: ctx
276 .ve
277 
278 .seealso: [](ch_ksp), `PC`, `PCSetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`
279 @*/
280 PetscErrorCode PCGetApplicationContext(PC pc, PeCtx ctx)
281 {
282   PetscFunctionBegin;
283   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
284   *(void **)ctx = pc->ctx;
285   PetscFunctionReturn(PETSC_SUCCESS);
286 }
287