Actual source code: pcset.c

  1: /*
  2:     Routines to set PC methods and options.
  3: */

  5: #include <petsc/private/pcimpl.h>
  6: #include <petscdm.h>

  8: PetscBool PCRegisterAllCalled = PETSC_FALSE;
  9: /*
 10:    Contains the list of registered PC routines
 11: */
 12: PetscFunctionList PCList = NULL;

 14: /*@
 15:   PCSetType - Builds `PC` for a particular preconditioner type

 17:   Collective

 19:   Input Parameters:
 20: + pc   - the preconditioner context
 21: - type - a known method, see `PCType` for possible values

 23:   Options Database Key:
 24: . -pc_type <type> - Sets `PC` type

 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.

 38:   Level: intermediate

 40:   Developer Notes:
 41:   `PCRegister()` is used to add preconditioner types to `PCList` from which they
 42:   are accessed by `PCSetType()`.

 44: .seealso: [](ch_ksp), `KSPSetType()`, `PCType`, `PCRegister()`, `PCCreate()`, `KSPGetPC()`
 45: @*/
 46: PetscErrorCode PCSetType(PC pc, PCType type)
 47: {
 48:   PetscBool match;
 49:   PetscErrorCode (*r)(PC);

 51:   PetscFunctionBegin;
 53:   PetscAssertPointer(type, 2);

 55:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, type, &match));
 56:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

 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);

 63:   PetscCall(PetscFunctionListDestroy(&((PetscObject)pc)->qlist));
 64:   /* Reinitialize function pointers in PCOps structure */
 65:   PetscCall(PetscMemzero(pc->ops, sizeof(struct _PCOps)));
 66:   /* XXX Is this OK?? */
 67:   pc->modifysubmatrices  = NULL;
 68:   pc->modifysubmatricesP = NULL;
 69:   /* Call the PCCreate_XXX routine for this particular preconditioner */
 70:   pc->setupcalled = 0;

 72:   PetscCall(PetscObjectChangeTypeName((PetscObject)pc, type));
 73:   PetscCall((*r)(pc));
 74:   PetscFunctionReturn(PETSC_SUCCESS);
 75: }

 77: /*@
 78:   PCGetType - Gets the `PCType` (as a string) from the `PC`
 79:   context.

 81:   Not Collective

 83:   Input Parameter:
 84: . pc - the preconditioner context

 86:   Output Parameter:
 87: . type - name of preconditioner method

 89:   Level: intermediate

 91: .seealso: [](ch_ksp), `PC`, `PCType`, `PCSetType()`
 92: @*/
 93: PetscErrorCode PCGetType(PC pc, PCType *type)
 94: {
 95:   PetscFunctionBegin;
 97:   PetscAssertPointer(type, 2);
 98:   *type = ((PetscObject)pc)->type_name;
 99:   PetscFunctionReturn(PETSC_SUCCESS);
100: }

102: PETSC_INTERN PetscErrorCode PCGetDefaultType_Private(PC, const char *[]);

104: /*@
105:   PCSetFromOptions - Sets `PC` options from the options database.

107:   Collective

109:   Input Parameter:
110: . pc - the preconditioner context

112:   Options Database Key:
113: . -pc_type - name of type, for example `bjacobi`

115:   Level: advanced

117:   Notes:
118:   This routine must be called before `PCSetUp()` if the user is to be
119:   allowed to set the preconditioner method from the options database.

121:   This is called from `KSPSetFromOptions()` so rarely needs to be called directly

123: .seealso: [](ch_ksp), `PC`, `PCSetType()`, `PCType`, `KSPSetFromOptions()`
124: @*/
125: PetscErrorCode PCSetFromOptions(PC pc)
126: {
127:   char        type[256];
128:   const char *def;
129:   PetscBool   flg;

131:   PetscFunctionBegin;

134:   PetscCall(PCRegisterAll());
135:   if (!((PetscObject)pc)->type_name) {
136:     PetscCall(PCGetDefaultType_Private(pc, &def));
137:   } else {
138:     def = ((PetscObject)pc)->type_name;
139:   }
140:   PetscObjectOptionsBegin((PetscObject)pc);

142:   PetscCall(PetscOptionsFList("-pc_type", "Preconditioner", "PCSetType", PCList, def, type, 256, &flg));
143:   if (flg) {
144:     PetscCall(PCSetType(pc, type));
145:   } else if (!((PetscObject)pc)->type_name && def) {
146:     PetscCall(PCSetType(pc, def));
147:   }

149:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &flg));
150:   if (flg) goto skipoptions;

152:   PetscCall(PetscOptionsBool("-pc_use_amat", "use Amat (instead of Pmat) to define preconditioner in nested inner solves", "PCSetUseAmat", pc->useAmat, &pc->useAmat, NULL));

154:   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);

156: skipoptions:
157:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
158:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc, PetscOptionsObject));
159:   PetscOptionsEnd();
160:   pc->setfromoptionscalled++;
161:   PetscFunctionReturn(PETSC_SUCCESS);
162: }

164: /*@
165:   PCSetDM - Sets the `DM` that may be used by some preconditioners

167:   Logically Collective

169:   Input Parameters:
170: + pc - the preconditioner context
171: - dm - the `DM`, can be `NULL` to remove any current `DM`

173:   Level: intermediate

175:   Note:
176:   Users generally call  `KSPSetDM()`, `SNESSetDM()`, or `TSSetDM()` so this is rarely called directly

178:   Developer Notes:
179:   The routines KSP/SNES/TSSetDM() require `dm` to be non-`NULL`, but this one can be `NULL` since all it does is
180:   replace the current `DM`

182: .seealso: [](ch_ksp), `PC`, `DM`, `PCGetDM()`, `KSPSetDM()`, `KSPGetDM()`, `SNESSetDM()`, `TSSetDM()`
183: @*/
184: PetscErrorCode PCSetDM(PC pc, DM dm)
185: {
186:   PetscFunctionBegin;
188:   if (dm) PetscCall(PetscObjectReference((PetscObject)dm));
189:   PetscCall(DMDestroy(&pc->dm));
190:   pc->dm = dm;
191:   PetscFunctionReturn(PETSC_SUCCESS);
192: }

194: /*@
195:   PCGetDM - Gets the `DM` that may be used by some preconditioners

197:   Not Collective

199:   Input Parameter:
200: . pc - the preconditioner context

202:   Output Parameter:
203: . dm - the `DM`

205:   Level: intermediate

207: .seealso: [](ch_ksp), `PC`, `DM`, `PCSetDM()`, `KSPSetDM()`, `KSPGetDM()`
208: @*/
209: PetscErrorCode PCGetDM(PC pc, DM *dm)
210: {
211:   PetscFunctionBegin;
213:   *dm = pc->dm;
214:   PetscFunctionReturn(PETSC_SUCCESS);
215: }

217: /*@
218:   PCSetApplicationContext - Sets the optional user-defined context for the preconditioner

220:   Logically Collective

222:   Input Parameters:
223: + pc  - the `PC` context
224: - ctx - optional user context

226:   Level: advanced

228:   Fortran Note:
229:   This only works when `ctx` is a Fortran derived type (it cannot be a `PetscObject`), we recommend writing a Fortran interface definition for this
230:   function that tells the Fortran compiler the derived data type that is passed in as the `ctx` argument. See `PCGetApplicationContext()` for
231:   an example.

233: .seealso: [](ch_ksp), `PC`, `PCGetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`, `PetscObjectCompose()`
234: @*/
235: PetscErrorCode PCSetApplicationContext(PC pc, void *ctx)
236: {
237:   PetscFunctionBegin;
239:   pc->ctx = ctx;
240:   PetscFunctionReturn(PETSC_SUCCESS);
241: }

243: /*@
244:   PCGetApplicationContext - Gets the user-defined context for the preconditioner set with `PCSetApplicationContext()`

246:   Not Collective

248:   Input Parameter:
249: . pc - `PC` context

251:   Output Parameter:
252: . ctx - user context

254:   Level: intermediate

256:   Fortran Notes:
257:   This only works when the context is a Fortran derived type (it cannot be a `PetscObject`) and you **must** write a Fortran interface definition for this
258:   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
259: .vb
260:   Interface PCGetApplicationContext
261:     Subroutine PCGetApplicationContext(pc,ctx,ierr)
262:   #include <petsc/finclude/petscpc.h>
263:       use petscpc
264:       PC pc
265:       type(tUsertype), pointer :: ctx
266:       PetscErrorCode ierr
267:     End Subroutine
268:   End Interface PCGetApplicationContext
269: .ve

271:   The prototype for `ctx` must be
272: .vb
273:   type(tUsertype), pointer :: ctx
274: .ve

276: .seealso: [](ch_ksp), `PC`, `PCSetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`
277: @*/
278: PetscErrorCode PCGetApplicationContext(PC pc, PeCtx ctx)
279: {
280:   PetscFunctionBegin;
282:   *(void **)ctx = pc->ctx;
283:   PetscFunctionReturn(PETSC_SUCCESS);
284: }