Actual source code: dmksp.c
petsc-3.13.6 2020-09-29
Report Typos and Errors

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

      5: static PetscErrorCode DMKSPDestroy(DMKSP *kdm)
      6: {

     10:   if (!*kdm) return(0);
     12:   if (--((PetscObject)(*kdm))->refct > 0) {*kdm = 0; return(0);}
     13:   if ((*kdm)->ops->destroy) {((*kdm)->ops->destroy)(kdm);}
     14:   PetscHeaderDestroy(kdm);
     15:   return(0);
     16: }

     18: static PetscErrorCode DMKSPCreate(MPI_Comm comm,DMKSP *kdm)
     19: {

     23:   KSPInitializePackage();
     24:   PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
     25:   return(0);
     26: }

     29: /* Attaches the DMKSP to the coarse level.
     30:  * Under what conditions should we copy versus duplicate?
     31:  */
     32: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm,DM dmc,void *ctx)
     33: {

     37:   DMCopyDMKSP(dm,dmc);
     38:   return(0);
     39: }

     41: /* Attaches the DMKSP to the coarse level.
     42:  * Under what conditions should we copy versus duplicate?
     43:  */
     44: static PetscErrorCode DMRefineHook_DMKSP(DM dm,DM dmc,void *ctx)
     45: {

     49:   DMCopyDMKSP(dm,dmc);
     50:   return(0);
     51: }

     53: /*@C
     54:    DMKSPCopy - copies the information in a DMKSP to another DMKSP

     56:    Not Collective

     58:    Input Argument:
     59: +  kdm - Original DMKSP
     60: -  nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()

     62:    Level: developer

     64: .seealso: DMKSPCreate(), DMKSPDestroy()
     65: @*/
     66: PetscErrorCode DMKSPCopy(DMKSP kdm,DMKSP nkdm)
     67: {

     73:   nkdm->ops->computeoperators    = kdm->ops->computeoperators;
     74:   nkdm->ops->computerhs          = kdm->ops->computerhs;
     75:   nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
     76:   nkdm->ops->destroy             = kdm->ops->destroy;
     77:   nkdm->ops->duplicate           = kdm->ops->duplicate;

     79:   nkdm->operatorsctx    = kdm->operatorsctx;
     80:   nkdm->rhsctx          = kdm->rhsctx;
     81:   nkdm->initialguessctx = kdm->initialguessctx;
     82:   nkdm->data            = kdm->data;
     83:   /* nkdm->originaldm   = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */

     85:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
     86:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
     87:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];

     89:   /* implementation specific copy hooks */
     90:   if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
     91:   return(0);
     92: }

     94: /*@C
     95:    DMGetDMKSP - get read-only private DMKSP context from a DM

     97:    Logically Collective

     99:    Input Argument:
    100: .  dm - DM to be used with KSP

    102:    Output Argument:
    103: .  snesdm - private DMKSP context

    105:    Level: developer

    107:    Notes:
    108:    Use DMGetDMKSPWrite() if write access is needed. The DMKSPSetXXX API should be used wherever possible.

    110: .seealso: DMGetDMKSPWrite()
    111: @*/
    112: PetscErrorCode DMGetDMKSP(DM dm,DMKSP *kspdm)
    113: {

    118:   *kspdm = (DMKSP) dm->dmksp;
    119:   if (!*kspdm) {
    120:     PetscInfo(dm,"Creating new DMKSP\n");
    121:     DMKSPCreate(PetscObjectComm((PetscObject)dm),kspdm);
    122:     dm->dmksp            = (PetscObject) *kspdm;
    123:     (*kspdm)->originaldm = dm;
    124:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMKSP,NULL,NULL);
    125:     DMRefineHookAdd(dm,DMRefineHook_DMKSP,NULL,NULL);
    126:   }
    127:   return(0);
    128: }

    130: /*@C
    131:    DMGetDMKSPWrite - get write access to private DMKSP context from a DM

    133:    Logically Collective

    135:    Input Argument:
    136: .  dm - DM to be used with KSP

    138:    Output Argument:
    139: .  kspdm - private DMKSP context

    141:    Level: developer

    143: .seealso: DMGetDMKSP()
    144: @*/
    145: PetscErrorCode DMGetDMKSPWrite(DM dm,DMKSP *kspdm)
    146: {
    148:   DMKSP          kdm;

    152:   DMGetDMKSP(dm,&kdm);
    153:   if (!kdm->originaldm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DMKSP has a NULL originaldm");
    154:   if (kdm->originaldm != dm) {  /* Copy on write */
    155:     DMKSP oldkdm = kdm;
    156:     PetscInfo(dm,"Copying DMKSP due to write\n");
    157:     DMKSPCreate(PetscObjectComm((PetscObject)dm),&kdm);
    158:     DMKSPCopy(oldkdm,kdm);
    159:     DMKSPDestroy((DMKSP*)&dm->dmksp);
    160:     dm->dmksp = (PetscObject)kdm;
    161:     kdm->originaldm = dm;
    162:   }
    163:   *kspdm = kdm;
    164:   return(0);
    165: }

    167: /*@C
    168:    DMCopyDMKSP - copies a DM context to a new DM

    170:    Logically Collective

    172:    Input Arguments:
    173: +  dmsrc - DM to obtain context from
    174: -  dmdest - DM to add context to

    176:    Level: developer

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

    181: .seealso: DMGetDMKSP(), KSPSetDM()
    182: @*/
    183: PetscErrorCode DMCopyDMKSP(DM dmsrc,DM dmdest)
    184: {

    190:   DMKSPDestroy((DMKSP*)&dmdest->dmksp);
    191:   dmdest->dmksp = dmsrc->dmksp;
    192:   PetscObjectReference(dmdest->dmksp);
    193:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMKSP,NULL,NULL);
    194:   DMRefineHookAdd(dmdest,DMRefineHook_DMKSP,NULL,NULL);
    195:   return(0);
    196: }

    198: /*@C
    199:    DMKSPSetComputeOperators - set KSP matrix evaluation function

    201:    Not Collective

    203:    Input Argument:
    204: +  dm - DM to be used with KSP
    205: .  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
    206: -  ctx - context for matrix evaluation

    208:    Level: advanced

    210:    Note:
    211:    KSPSetComputeOperators() is normally used, but it calls this function internally because the user context is actually
    212:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
    213:    not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.

    215: .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
    216: @*/
    217: PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,void*),void *ctx)
    218: {
    220:   DMKSP          kdm;

    224:   DMGetDMKSPWrite(dm,&kdm);
    225:   if (func) kdm->ops->computeoperators = func;
    226:   if (ctx) kdm->operatorsctx = ctx;
    227:   return(0);
    228: }

    230: /*@C
    231:    DMKSPGetComputeOperators - get KSP matrix evaluation function

    233:    Not Collective

    235:    Input Argument:
    236: .  dm - DM to be used with KSP

    238:    Output Arguments:
    239: +  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
    240: -  ctx - context for matrix evaluation

    242:    Level: advanced

    244: .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
    245: @*/
    246: PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,void*),void *ctx)
    247: {
    249:   DMKSP          kdm;

    253:   DMGetDMKSP(dm,&kdm);
    254:   if (func) *func = kdm->ops->computeoperators;
    255:   if (ctx) *(void**)ctx = kdm->operatorsctx;
    256:   return(0);
    257: }

    259: /*@C
    260:    DMKSPSetComputeRHS - set KSP right hand side evaluation function

    262:    Not Collective

    264:    Input Argument:
    265: +  dm - DM to be used with KSP
    266: .  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
    267: -  ctx - context for right hand side evaluation

    269:    Level: advanced

    271:    Note:
    272:    KSPSetComputeRHS() is normally used, but it calls this function internally because the user context is actually
    273:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
    274:    not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.

    276: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
    277: @*/
    278: PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
    279: {
    281:   DMKSP          kdm;

    285:   DMGetDMKSPWrite(dm,&kdm);
    286:   if (func) kdm->ops->computerhs = func;
    287:   if (ctx) kdm->rhsctx = ctx;
    288:   return(0);
    289: }

    291: /*@C
    292:    DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function

    294:    Not Collective

    296:    Input Argument:
    297: +  dm - DM to be used with KSP
    298: .  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
    299: -  ctx - context for right hand side evaluation

    301:    Level: advanced

    303:    Note:
    304:    KSPSetComputeInitialGuess() is normally used, but it calls this function internally because the user context is actually
    305:    associated with the DM.

    307: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
    308: @*/
    309: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
    310: {
    312:   DMKSP          kdm;

    316:   DMGetDMKSPWrite(dm,&kdm);
    317:   if (func) kdm->ops->computeinitialguess = func;
    318:   if (ctx) kdm->initialguessctx = ctx;
    319:   return(0);
    320: }

    322: /*@C
    323:    DMKSPGetComputeRHS - get KSP right hand side evaluation function

    325:    Not Collective

    327:    Input Argument:
    328: .  dm - DM to be used with KSP

    330:    Output Arguments:
    331: +  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
    332: -  ctx - context for right hand side evaluation

    334:    Level: advanced

    336: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
    337: @*/
    338: PetscErrorCode DMKSPGetComputeRHS(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
    339: {
    341:   DMKSP          kdm;

    345:   DMGetDMKSP(dm,&kdm);
    346:   if (func) *func = kdm->ops->computerhs;
    347:   if (ctx) *(void**)ctx = kdm->rhsctx;
    348:   return(0);
    349: }

    351: /*@C
    352:    DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function

    354:    Not Collective

    356:    Input Argument:
    357: .  dm - DM to be used with KSP

    359:    Output Arguments:
    360: +  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
    361: -  ctx - context for right hand side evaluation

    363:    Level: advanced

    365: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
    366: @*/
    367: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
    368: {
    370:   DMKSP          kdm;

    374:   DMGetDMKSP(dm,&kdm);
    375:   if (func) *func = kdm->ops->computeinitialguess;
    376:   if (ctx) *(void**)ctx = kdm->initialguessctx;
    377:   return(0);
    378: }