Date: 2026-03-01T05:24:54+00:00

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 = PETSC_FALSE;

     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: }