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