Date: 2025-03-29T05:58:31+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);
     62:   pc->ops->destroy = NULL;
     63:   pc->data         = NULL;

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

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

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

     83:   Not Collective

     85:   Input Parameter:
     86: . pc - the preconditioner context

     88:   Output Parameter:
     89: . type - name of preconditioner method

     91:   Level: intermediate

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

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

    106: /*@
    107:   PCSetFromOptions - Sets `PC` options from the options database.

    109:   Collective

    111:   Input Parameter:
    112: . pc - the preconditioner context

    114:   Options Database Key:
    115: . -pc_type - name of type, for example `bjacobi`

    117:   Level: advanced

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

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

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

    133:   PetscFunctionBegin;

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

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

    151:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &flg));
    152:   if (flg) goto skipoptions;

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

    156:   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);

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

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

    169:   Logically Collective

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

    175:   Level: intermediate

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

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

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

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

    199:   Not Collective

    201:   Input Parameter:
    202: . pc - the preconditioner context

    204:   Output Parameter:
    205: . dm - the `DM`

    207:   Level: intermediate

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

    219: /*@
    220:   PCSetApplicationContext - Sets the optional user-defined context for the preconditioner

    222:   Logically Collective

    224:   Input Parameters:
    225: + pc  - the `PC` context
    226: - ctx - optional user context

    228:   Level: advanced

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

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

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

    248:   Not Collective

    250:   Input Parameter:
    251: . pc - `PC` context

    253:   Output Parameter:
    254: . ctx - user context

    256:   Level: intermediate

    258:   Fortran Notes:
    259:   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
    260:   function that tells the Fortran compiler the derived data type that is returned as the `ctx` argument. For example,
    261: .vb
    262:   Interface PCGetApplicationContext
    263:     Subroutine PCGetApplicationContext(pc,ctx,ierr)
    264:   #include <petsc/finclude/petscpc.h>
    265:       use petscpc
    266:       PC pc
    267:       type(tUsertype), pointer :: ctx
    268:       PetscErrorCode ierr
    269:     End Subroutine
    270:   End Interface PCGetApplicationContext
    271: .ve

    273:   The prototpye for `ctx` must be
    274: .vb
    275:   type(tUsertype), pointer :: ctx
    276: .ve

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