xref: /petsc/src/ksp/pc/interface/pcset.c (revision 66af8762ec03dbef0e079729eb2a1734a35ed7ff)
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 /*@C
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: `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 /*@C
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: `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 extern 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: `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   PetscObjectOptionsBegin((PetscObject)pc);
138   if (!((PetscObject)pc)->type_name) {
139     PetscCall(PCGetDefaultType_Private(pc, &def));
140   } else {
141     def = ((PetscObject)pc)->type_name;
142   }
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) {
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: `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: `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 - usrP - optional user context
227 
228   Level: advanced
229 
230 .seealso: `PC`, `PCGetApplicationContext()`
231 @*/
232 PetscErrorCode PCSetApplicationContext(PC pc, void *usrP)
233 {
234   PetscFunctionBegin;
235   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
236   pc->user = usrP;
237   PetscFunctionReturn(PETSC_SUCCESS);
238 }
239 
240 /*@
241   PCGetApplicationContext - Gets the user-defined context for the preconditioner set with `PCSetApplicationContext()`
242 
243   Not Collective
244 
245   Input Parameter:
246 . pc - `PC` context
247 
248   Output Parameter:
249 . usrP - user context
250 
251   Level: intermediate
252 
253 .seealso: `PC`, `PCSetApplicationContext()`
254 @*/
255 PetscErrorCode PCGetApplicationContext(PC pc, void *usrP)
256 {
257   PetscFunctionBegin;
258   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
259   *(void **)usrP = pc->user;
260   PetscFunctionReturn(PETSC_SUCCESS);
261 }
262