Actual source code: dmksp.c

      1: #include <petsc/private/dmimpl.h>
      2: #include <petsc/private/kspimpl.h>
      3: #include <petscdm.h>

      5: static PetscErrorCode DMKSPDestroy(DMKSP *kdm)
      6: {
      7:   PetscFunctionBegin;
      8:   if (!*kdm) PetscFunctionReturn(PETSC_SUCCESS);
     10:   if (--((PetscObject)*kdm)->refct > 0) {
     11:     *kdm = NULL;
     12:     PetscFunctionReturn(PETSC_SUCCESS);
     13:   }
     14:   if ((*kdm)->ops->destroy) PetscCall(((*kdm)->ops->destroy)(kdm));
     15:   PetscCall(PetscHeaderDestroy(kdm));
     16:   PetscFunctionReturn(PETSC_SUCCESS);
     17: }

     19: static PetscErrorCode DMKSPCreate(MPI_Comm comm, DMKSP *kdm)
     20: {
     21:   PetscFunctionBegin;
     22:   PetscCall(KSPInitializePackage());
     23:   PetscCall(PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL));
     24:   PetscFunctionReturn(PETSC_SUCCESS);
     25: }

     27: /* Attaches the DMKSP to the coarse level.
     28:  * Under what conditions should we copy versus duplicate?
     29:  */
     30: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm, DM dmc, void *ctx)
     31: {
     32:   PetscFunctionBegin;
     33:   PetscCall(DMCopyDMKSP(dm, dmc));
     34:   PetscFunctionReturn(PETSC_SUCCESS);
     35: }

     37: /* Attaches the DMKSP to the coarse level.
     38:  * Under what conditions should we copy versus duplicate?
     39:  */
     40: static PetscErrorCode DMRefineHook_DMKSP(DM dm, DM dmc, void *ctx)
     41: {
     42:   PetscFunctionBegin;
     43:   PetscCall(DMCopyDMKSP(dm, dmc));
     44:   PetscFunctionReturn(PETSC_SUCCESS);
     45: }

     47: /*
     48:   DMKSPCopy - copies the information in a `DMKSP` to another `DMKSP`

     50:   Not Collective

     52:   Input Parameters:
     53: + kdm  - Original `DMKSP`
     54: - nkdm - `DMKSP` to receive the data, created with `DMKSPCreate()`

     56:   Level: developer

     58: .seealso: [](ch_ksp), `DMKSP`, `DMKSPCreate()`, `DMKSPDestroy()`
     59: */
     60: static PetscErrorCode DMKSPCopy(DMKSP kdm, DMKSP nkdm)
     61: {
     62:   PetscFunctionBegin;
     65:   nkdm->ops->computeoperators    = kdm->ops->computeoperators;
     66:   nkdm->ops->computerhs          = kdm->ops->computerhs;
     67:   nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
     68:   nkdm->ops->destroy             = kdm->ops->destroy;
     69:   nkdm->ops->duplicate           = kdm->ops->duplicate;

     71:   nkdm->operatorsctx    = kdm->operatorsctx;
     72:   nkdm->rhsctx          = kdm->rhsctx;
     73:   nkdm->initialguessctx = kdm->initialguessctx;
     74:   nkdm->data            = kdm->data;
     75:   /* nkdm->originaldm   = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */

     77:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
     78:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
     79:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];

     81:   /* implementation specific copy hooks */
     82:   PetscTryTypeMethod(kdm, duplicate, nkdm);
     83:   PetscFunctionReturn(PETSC_SUCCESS);
     84: }

     86: /*@C
     87:   DMGetDMKSP - get the read-only private `DMKSP` context from a `DM`

     89:   Logically Collective

     91:   Input Parameter:
     92: . dm - `DM` used with a `KSP`

     94:   Output Parameter:
     95: . kspdm - private `DMKSP` context

     97:   Level: developer

     99:   Note:
    100:   Use `DMGetDMKSPWrite()` if write access is needed. The DMKSPSetXXX API should be used wherever possible.

    102: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSPWrite()`
    103: @*/
    104: PetscErrorCode DMGetDMKSP(DM dm, DMKSP *kspdm)
    105: {
    106:   PetscFunctionBegin;
    108:   *kspdm = (DMKSP)dm->dmksp;
    109:   if (!*kspdm) {
    110:     PetscCall(PetscInfo(dm, "Creating new DMKSP\n"));
    111:     PetscCall(DMKSPCreate(PetscObjectComm((PetscObject)dm), kspdm));
    112:     dm->dmksp            = (PetscObject)*kspdm;
    113:     (*kspdm)->originaldm = dm;
    114:     PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_DMKSP, NULL, NULL));
    115:     PetscCall(DMRefineHookAdd(dm, DMRefineHook_DMKSP, NULL, NULL));
    116:   }
    117:   PetscFunctionReturn(PETSC_SUCCESS);
    118: }

    120: /*@C
    121:   DMGetDMKSPWrite - get write access to private `DMKSP` context from a `DM`

    123:   Logically Collective

    125:   Input Parameter:
    126: . dm - `DM` used with a `KSP`

    128:   Output Parameter:
    129: . kspdm - private `DMKSP` context

    131:   Level: developer

    133: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`
    134: @*/
    135: PetscErrorCode DMGetDMKSPWrite(DM dm, DMKSP *kspdm)
    136: {
    137:   DMKSP kdm;

    139:   PetscFunctionBegin;
    141:   PetscCall(DMGetDMKSP(dm, &kdm));
    142:   PetscCheck(kdm->originaldm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DMKSP has a NULL originaldm");
    143:   if (kdm->originaldm != dm) { /* Copy on write */
    144:     DMKSP oldkdm = kdm;
    145:     PetscCall(PetscInfo(dm, "Copying DMKSP due to write\n"));
    146:     PetscCall(DMKSPCreate(PetscObjectComm((PetscObject)dm), &kdm));
    147:     PetscCall(DMKSPCopy(oldkdm, kdm));
    148:     PetscCall(DMKSPDestroy((DMKSP *)&dm->dmksp));
    149:     dm->dmksp       = (PetscObject)kdm;
    150:     kdm->originaldm = dm;
    151:   }
    152:   *kspdm = kdm;
    153:   PetscFunctionReturn(PETSC_SUCCESS);
    154: }

    156: /*@
    157:   DMCopyDMKSP - copies a `DM` `DMKSP` context to a new `DM`

    159:   Logically Collective

    161:   Input Parameters:
    162: + dmsrc  - `DM` to obtain context from
    163: - dmdest - `DM` to add context to

    165:   Level: developer

    167:   Note:
    168:   The context is copied by reference. This function does not ensure that a context exists.

    170: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`, `KSPSetDM()`
    171: @*/
    172: PetscErrorCode DMCopyDMKSP(DM dmsrc, DM dmdest)
    173: {
    174:   PetscFunctionBegin;
    177:   PetscCall(DMKSPDestroy((DMKSP *)&dmdest->dmksp));
    178:   dmdest->dmksp = dmsrc->dmksp;
    179:   PetscCall(PetscObjectReference(dmdest->dmksp));
    180:   PetscCall(DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMKSP, NULL, NULL));
    181:   PetscCall(DMRefineHookAdd(dmdest, DMRefineHook_DMKSP, NULL, NULL));
    182:   PetscFunctionReturn(PETSC_SUCCESS);
    183: }

    185: /*@C
    186:   DMKSPSetComputeOperators - set `KSP` matrix evaluation function

    188:   Not Collective

    190:   Input Parameters:
    191: + dm   - `DM` to be used with `KSP`
    192: . func - matrix evaluation function,  for calling sequence see `KSPComputeOperatorsFn`
    193: - ctx  - context for matrix evaluation

    195:   Level: developer

    197:   Note:
    198:   `KSPSetComputeOperators()` is normally used, but it calls this function internally because the user context is actually
    199:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
    200:   not.

    202:   Developer Note:
    203:   If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.

    205: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeOperators()`, `KSPSetOperators()`, `KSPComputeOperatorsFn`
    206: @*/
    207: PetscErrorCode DMKSPSetComputeOperators(DM dm, KSPComputeOperatorsFn *func, void *ctx)
    208: {
    209:   DMKSP kdm;

    211:   PetscFunctionBegin;
    213:   PetscCall(DMGetDMKSPWrite(dm, &kdm));
    214:   if (func) kdm->ops->computeoperators = func;
    215:   if (ctx) kdm->operatorsctx = ctx;
    216:   PetscFunctionReturn(PETSC_SUCCESS);
    217: }

    219: /*@C
    220:   DMKSPGetComputeOperators - get `KSP` matrix evaluation function

    222:   Not Collective

    224:   Input Parameter:
    225: . dm - `DM` used with a `KSP`

    227:   Output Parameters:
    228: + func - matrix evaluation function,  for calling sequence see `KSPComputeOperatorsFn`
    229: - ctx  - context for matrix evaluation

    231:   Level: developer

    233: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeOperators()`, `DMKSPSetComputeOperators()`, `KSPComputeOperatorsFn`
    234: @*/
    235: PetscErrorCode DMKSPGetComputeOperators(DM dm, KSPComputeOperatorsFn **func, void *ctx)
    236: {
    237:   DMKSP kdm;

    239:   PetscFunctionBegin;
    241:   PetscCall(DMGetDMKSP(dm, &kdm));
    242:   if (func) *func = kdm->ops->computeoperators;
    243:   if (ctx) *(void **)ctx = kdm->operatorsctx;
    244:   PetscFunctionReturn(PETSC_SUCCESS);
    245: }

    247: /*@C
    248:   DMKSPSetComputeRHS - set `KSP` right-hand side evaluation function

    250:   Not Collective

    252:   Input Parameters:
    253: + dm   - `DM` used with a `KSP`
    254: . func - right-hand side evaluation function,  for calling sequence see `KSPComputeRHSFn`
    255: - ctx  - context for right-hand side evaluation

    257:   Level: developer

    259:   Note:
    260:   `KSPSetComputeRHS()` is normally used, but it calls this function internally because the user context is actually
    261:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
    262:   not.

    264:   Developer Note:
    265:   If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.

    267: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`
    268: @*/
    269: PetscErrorCode DMKSPSetComputeRHS(DM dm, KSPComputeRHSFn *func, void *ctx)
    270: {
    271:   DMKSP kdm;

    273:   PetscFunctionBegin;
    275:   PetscCall(DMGetDMKSPWrite(dm, &kdm));
    276:   if (func) kdm->ops->computerhs = func;
    277:   if (ctx) kdm->rhsctx = ctx;
    278:   PetscFunctionReturn(PETSC_SUCCESS);
    279: }

    281: /*@C
    282:   DMKSPSetComputeInitialGuess - set `KSP` initial guess evaluation function

    284:   Not Collective

    286:   Input Parameters:
    287: + dm   - `DM` to be used with `KSP`
    288: . func - initial guess evaluation function, for calling sequence see `KSPComputeInitialGuessFn`
    289: - ctx  - context for initial guess evaluation

    291:   Level: developer

    293:   Note:
    294:   `KSPSetComputeInitialGuess()` is normally used, but it calls this function internally because the user context is actually
    295:   associated with the `DM`.

    297: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPComputeInitialGuessFn`
    298: @*/
    299: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn *func, void *ctx)
    300: {
    301:   DMKSP kdm;

    303:   PetscFunctionBegin;
    305:   PetscCall(DMGetDMKSPWrite(dm, &kdm));
    306:   if (func) kdm->ops->computeinitialguess = func;
    307:   if (ctx) kdm->initialguessctx = ctx;
    308:   PetscFunctionReturn(PETSC_SUCCESS);
    309: }

    311: /*@C
    312:   DMKSPGetComputeRHS - get `KSP` right-hand side evaluation function

    314:   Not Collective

    316:   Input Parameter:
    317: . dm - `DM` to be used with `KSP`

    319:   Output Parameters:
    320: + func - right-hand side evaluation function,  for calling sequence see `KSPComputeRHSFn`
    321: - ctx  - context for right-hand side evaluation

    323:   Level: advanced

    325: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeRHSFn`
    326: @*/
    327: PetscErrorCode DMKSPGetComputeRHS(DM dm, KSPComputeRHSFn **func, void *ctx)
    328: {
    329:   DMKSP kdm;

    331:   PetscFunctionBegin;
    333:   PetscCall(DMGetDMKSP(dm, &kdm));
    334:   if (func) *func = kdm->ops->computerhs;
    335:   if (ctx) *(void **)ctx = kdm->rhsctx;
    336:   PetscFunctionReturn(PETSC_SUCCESS);
    337: }

    339: /*@C
    340:   DMKSPGetComputeInitialGuess - get `KSP` initial guess evaluation function

    342:   Not Collective

    344:   Input Parameter:
    345: . dm - `DM` used with a `KSP`

    347:   Output Parameters:
    348: + func - initial guess evaluation function, for calling sequence see `KSPComputeInitialGuessFn`
    349: - ctx  - context for right-hand side evaluation

    351:   Level: advanced

    353: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeInitialGuessFn`
    354: @*/
    355: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn **func, void *ctx)
    356: {
    357:   DMKSP kdm;

    359:   PetscFunctionBegin;
    361:   PetscCall(DMGetDMKSP(dm, &kdm));
    362:   if (func) *func = kdm->ops->computeinitialguess;
    363:   if (ctx) *(void **)ctx = kdm->initialguessctx;
    364:   PetscFunctionReturn(PETSC_SUCCESS);
    365: }