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