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) PetscCall(PCSetType(pc, type));
    144:   else if (!((PetscObject)pc)->type_name && def) PetscCall(PCSetType(pc, def));

    146:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCNONE, &flg));
    147:   if (flg) goto skipoptions;

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

    151:   PetscTryTypeMethod(pc, setfromoptions, PetscOptionsObject);

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

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

    164:   Logically Collective

    166:   Input Parameters:
    167: + pc - the preconditioner context
    168: - dm - the `DM`, can be `NULL` to remove any current `DM`

    170:   Level: intermediate

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

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

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

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

    194:   Not Collective

    196:   Input Parameter:
    197: . pc - the preconditioner context

    199:   Output Parameter:
    200: . dm - the `DM`

    202:   Level: intermediate

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

    214: /*@
    215:   PCSetApplicationContext - Sets the optional user-defined context for the preconditioner

    217:   Logically Collective

    219:   Input Parameters:
    220: + pc  - the `PC` context
    221: - ctx - optional user context

    223:   Level: advanced

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

    230: .seealso: [](ch_ksp), `PC`, `PCGetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`, `PetscObjectCompose()`
    231: @*/
    232: PetscErrorCode PCSetApplicationContext(PC pc, PetscCtx ctx)
    233: {
    234:   PetscFunctionBegin;
    236:   pc->ctx = ctx;
    237:   PetscFunctionReturn(PETSC_SUCCESS);
    238: }

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

    243:   Not Collective

    245:   Input Parameter:
    246: . pc - `PC` context

    248:   Output Parameter:
    249: . ctx - user context

    251:   Level: intermediate

    253:   Fortran Note:
    254:   This only works when the context is a Fortran derived type or a `PetscObject`. Define `ctx` with
    255: .vb
    256:   type(tUsertype), pointer :: ctx
    257: .ve

    259: .seealso: [](ch_ksp), `PC`, `PCSetApplicationContext()`, `KSPSetApplicationContext()`, `KSPGetApplicationContext()`
    260: @*/
    261: PetscErrorCode PCGetApplicationContext(PC pc, PetscCtxRt ctx)
    262: {
    263:   PetscFunctionBegin;
    265:   *(void **)ctx = pc->ctx;
    266:   PetscFunctionReturn(PETSC_SUCCESS);
    267: }