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