xref: /petsc/src/ksp/pc/interface/pcset.c (revision f4d061e980d13bc62f06124c58b76593bdf99e72)
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 on pc
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   PetscBool match;
56   PetscErrorCode (*r)(PC);
57 
58   PetscFunctionBegin;
59   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
60   PetscValidCharPointer(type, 2);
61 
62   PetscCall(PetscObjectTypeCompare((PetscObject)pc, type, &match));
63   if (match) PetscFunctionReturn(0);
64 
65   PetscCall(PetscFunctionListFind(PCList, type, &r));
66   PetscCheck(r, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PC type %s", type);
67   /* Destroy the previous private PC context */
68   PetscTryTypeMethod(pc, destroy);
69   pc->ops->destroy = NULL;
70   pc->data         = NULL;
71 
72   PetscCall(PetscFunctionListDestroy(&((PetscObject)pc)->qlist));
73   /* Reinitialize function pointers in PCOps structure */
74   PetscCall(PetscMemzero(pc->ops, sizeof(struct _PCOps)));
75   /* XXX Is this OK?? */
76   pc->modifysubmatrices  = NULL;
77   pc->modifysubmatricesP = NULL;
78   /* Call the PCCreate_XXX routine for this particular preconditioner */
79   pc->setupcalled        = 0;
80 
81   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, type));
82   PetscCall((*r)(pc));
83   PetscFunctionReturn(0);
84 }
85 
86 /*@C
87    PCGetType - Gets the PC method type and name (as a string) from the PC
88    context.
89 
90    Not Collective
91 
92    Input Parameter:
93 .  pc - the preconditioner context
94 
95    Output Parameter:
96 .  type - name of preconditioner method
97 
98    Level: intermediate
99 
100 .seealso: `PCSetType()`
101 
102 @*/
103 PetscErrorCode PCGetType(PC pc, PCType *type) {
104   PetscFunctionBegin;
105   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
106   PetscValidPointer(type, 2);
107   *type = ((PetscObject)pc)->type_name;
108   PetscFunctionReturn(0);
109 }
110 
111 extern PetscErrorCode PCGetDefaultType_Private(PC, const char *[]);
112 
113 /*@
114    PCSetFromOptions - Sets PC options from the options database.
115    This routine must be called before PCSetUp() if the user is to be
116    allowed to set the preconditioner method.
117 
118    Collective on pc
119 
120    Input Parameter:
121 .  pc - the preconditioner context
122 
123    Options Database Key:
124 .   -pc_use_amat true,false - see PCSetUseAmat()
125 
126    Level: developer
127 
128 .seealso: `PCSetUseAmat()`
129 
130 @*/
131 PetscErrorCode PCSetFromOptions(PC pc) {
132   char        type[256];
133   const char *def;
134   PetscBool   flg;
135 
136   PetscFunctionBegin;
137   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
138 
139   PetscCall(PCRegisterAll());
140   PetscObjectOptionsBegin((PetscObject)pc);
141   if (!((PetscObject)pc)->type_name) {
142     PetscCall(PCGetDefaultType_Private(pc, &def));
143   } else {
144     def = ((PetscObject)pc)->type_name;
145   }
146 
147   PetscCall(PetscOptionsFList("-pc_type", "Preconditioner", "PCSetType", PCList, def, type, 256, &flg));
148   if (flg) {
149     PetscCall(PCSetType(pc, type));
150   } else if (!((PetscObject)pc)->type_name) {
151     PetscCall(PCSetType(pc, def));
152   }
153 
154   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &flg));
155   if (flg) goto skipoptions;
156 
157   PetscCall(PetscOptionsBool("-pc_use_amat", "use Amat (instead of Pmat) to define preconditioner in nested inner solves", "PCSetUseAmat", pc->useAmat, &pc->useAmat, NULL));
158 
159   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);
160 
161 skipoptions:
162   /* process any options handlers added with PetscObjectAddOptionsHandler() */
163   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc, PetscOptionsObject));
164   PetscOptionsEnd();
165   pc->setfromoptionscalled++;
166   PetscFunctionReturn(0);
167 }
168 
169 /*@
170    PCSetDM - Sets the DM that may be used by some preconditioners
171 
172    Logically Collective on pc
173 
174    Input Parameters:
175 +  pc - the preconditioner context
176 -  dm - the dm, can be NULL
177 
178    Level: intermediate
179 
180    Developer Note:
181     The routines KSP/SNES/TSSetDM() require the dm to be non-NULL, but this one can be NULL since all it does is
182     replace the current DM
183 
184 .seealso: `PCGetDM()`, `KSPSetDM()`, `KSPGetDM()`
185 @*/
186 PetscErrorCode PCSetDM(PC pc, DM dm) {
187   PetscFunctionBegin;
188   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
189   if (dm) PetscCall(PetscObjectReference((PetscObject)dm));
190   PetscCall(DMDestroy(&pc->dm));
191   pc->dm = dm;
192   PetscFunctionReturn(0);
193 }
194 
195 /*@
196    PCGetDM - Gets the DM that may be used by some preconditioners
197 
198    Not Collective
199 
200    Input Parameter:
201 . pc - the preconditioner context
202 
203    Output Parameter:
204 .  dm - the dm
205 
206    Level: intermediate
207 
208 .seealso: `PCSetDM()`, `KSPSetDM()`, `KSPGetDM()`
209 @*/
210 PetscErrorCode PCGetDM(PC pc, DM *dm) {
211   PetscFunctionBegin;
212   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
213   *dm = pc->dm;
214   PetscFunctionReturn(0);
215 }
216 
217 /*@
218    PCSetApplicationContext - Sets the optional user-defined context for the linear solver.
219 
220    Logically Collective on pc
221 
222    Input Parameters:
223 +  pc - the PC context
224 -  usrP - optional user context
225 
226    Level: intermediate
227 
228 .seealso: `PCGetApplicationContext()`
229 @*/
230 PetscErrorCode PCSetApplicationContext(PC pc, void *usrP) {
231   PetscFunctionBegin;
232   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
233   pc->user = usrP;
234   PetscFunctionReturn(0);
235 }
236 
237 /*@
238    PCGetApplicationContext - Gets the user-defined context for the linear solver.
239 
240    Not Collective
241 
242    Input Parameter:
243 .  pc - PC context
244 
245    Output Parameter:
246 .  usrP - user context
247 
248    Level: intermediate
249 
250 .seealso: `PCSetApplicationContext()`
251 @*/
252 PetscErrorCode PCGetApplicationContext(PC pc, void *usrP) {
253   PetscFunctionBegin;
254   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
255   *(void **)usrP = pc->user;
256   PetscFunctionReturn(0);
257 }
258