Date: 2022-03-04T17:39:29+00:00

Actual source code: dmsnes.c

      1: #include <petsc/private/snesimpl.h>
      2: #include <petsc/private/dmimpl.h>

      4: static PetscErrorCode DMSNESDestroy(DMSNES *kdm)
      5: {

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

     17: PetscErrorCode DMSNESLoad(DMSNES kdm,PetscViewer viewer)
     18: {

     22:   PetscViewerBinaryRead(viewer,&kdm->ops->computefunction,1,NULL,PETSC_FUNCTION);
     23:   PetscViewerBinaryRead(viewer,&kdm->ops->computejacobian,1,NULL,PETSC_FUNCTION);
     24:   return(0);
     25: }

     27: PetscErrorCode DMSNESView(DMSNES kdm,PetscViewer viewer)
     28: {
     30:   PetscBool      isascii,isbinary;

     33:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
     34:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
     35:   if (isascii) {
     36: #if defined(PETSC_SERIALIZE_FUNCTIONS) && defined(PETSC_SERIALIZE_FUNCTIONS_VIEW)
     37:     const char *fname;

     39:     PetscFPTFind(kdm->ops->computefunction,&fname);
     40:     if (fname) {
     41:       PetscViewerASCIIPrintf(viewer,"Function used by SNES: %s\n",fname);
     42:     }
     43:     PetscFPTFind(kdm->ops->computejacobian,&fname);
     44:     if (fname) {
     45:       PetscViewerASCIIPrintf(viewer,"Jacobian function used by SNES: %s\n",fname);
     46:     }
     47: #endif
     48:   } else if (isbinary) {
     49:     struct {
     50:       PetscErrorCode (*func)(SNES,Vec,Vec,void*);
     51:     } funcstruct;
     52:     struct {
     53:       PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*);
     54:     } jacstruct;
     55:     funcstruct.func = kdm->ops->computefunction;
     56:     jacstruct.jac   = kdm->ops->computejacobian;
     57:     PetscViewerBinaryWrite(viewer,&funcstruct,1,PETSC_FUNCTION);
     58:     PetscViewerBinaryWrite(viewer,&jacstruct,1,PETSC_FUNCTION);
     59:   }
     60:   return(0);
     61: }

     63: static PetscErrorCode DMSNESCreate(MPI_Comm comm,DMSNES *kdm)
     64: {

     68:   SNESInitializePackage();
     69:   PetscHeaderCreate(*kdm, DMSNES_CLASSID,  "DMSNES", "DMSNES", "DMSNES", comm, DMSNESDestroy, DMSNESView);
     70:   return(0);
     71: }

     73: /* Attaches the DMSNES to the coarse level.
     74:  * Under what conditions should we copy versus duplicate?
     75:  */
     76: static PetscErrorCode DMCoarsenHook_DMSNES(DM dm,DM dmc,void *ctx)
     77: {

     81:   DMCopyDMSNES(dm,dmc);
     82:   return(0);
     83: }

     85: /* This could restrict auxiliary information to the coarse level.
     86:  */
     87: static PetscErrorCode DMRestrictHook_DMSNES(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx)
     88: {

     91:   return(0);
     92: }

     94: /* Attaches the DMSNES to the subdomain. */
     95: static PetscErrorCode DMSubDomainHook_DMSNES(DM dm,DM subdm,void *ctx)
     96: {

    100:   DMCopyDMSNES(dm,subdm);
    101:   return(0);
    102: }

    104: /* This could restrict auxiliary information to the coarse level.
    105:  */
    106: static PetscErrorCode DMSubDomainRestrictHook_DMSNES(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
    107: {

    110:   return(0);
    111: }

    113: static PetscErrorCode DMRefineHook_DMSNES(DM dm,DM dmf,void *ctx)
    114: {

    118:   DMCopyDMSNES(dm,dmf);
    119:   return(0);
    120: }

    122: /* This could restrict auxiliary information to the coarse level.
    123:  */
    124: static PetscErrorCode DMInterpolateHook_DMSNES(DM dm,Mat Interp,DM dmf,void *ctx)
    125: {

    128:   return(0);
    129: }

    131: /*@C
    132:    DMSNESCopy - copies the information in a DMSNES to another DMSNES

    134:    Not Collective

    136:    Input Parameters:
    137: +  kdm - Original DMSNES
    138: -  nkdm - DMSNES to receive the data, should have been created with DMSNESCreate()

    140:    Level: developer

    142: .seealso: DMSNESCreate(), DMSNESDestroy()
    143: @*/
    144: PetscErrorCode DMSNESCopy(DMSNES kdm,DMSNES nkdm)
    145: {

    151:   nkdm->ops->computefunction  = kdm->ops->computefunction;
    152:   nkdm->ops->computejacobian  = kdm->ops->computejacobian;
    153:   nkdm->ops->computegs        = kdm->ops->computegs;
    154:   nkdm->ops->computeobjective = kdm->ops->computeobjective;
    155:   nkdm->ops->computepjacobian = kdm->ops->computepjacobian;
    156:   nkdm->ops->computepfunction = kdm->ops->computepfunction;
    157:   nkdm->ops->destroy          = kdm->ops->destroy;
    158:   nkdm->ops->duplicate        = kdm->ops->duplicate;

    160:   nkdm->functionctx  = kdm->functionctx;
    161:   nkdm->gsctx        = kdm->gsctx;
    162:   nkdm->pctx         = kdm->pctx;
    163:   nkdm->jacobianctx  = kdm->jacobianctx;
    164:   nkdm->objectivectx = kdm->objectivectx;
    165:   nkdm->originaldm   = kdm->originaldm;

    167:   /*
    168:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
    169:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
    170:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
    171:   */

    173:   /* implementation specific copy hooks */
    174:   if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
    175:   return(0);
    176: }

    178: /*@C
    179:    DMGetDMSNES - get read-only private DMSNES context from a DM

    181:    Not Collective

    183:    Input Parameter:
    184: .  dm - DM to be used with SNES

    186:    Output Parameter:
    187: .  snesdm - private DMSNES context

    189:    Level: developer

    191:    Notes:
    192:    Use DMGetDMSNESWrite() if write access is needed. The DMSNESSetXXX API should be used wherever possible.

    194: .seealso: DMGetDMSNESWrite()
    195: @*/
    196: PetscErrorCode DMGetDMSNES(DM dm,DMSNES *snesdm)
    197: {

    202:   *snesdm = (DMSNES) dm->dmsnes;
    203:   if (!*snesdm) {
    204:     PetscInfo(dm,"Creating new DMSNES\n");
    205:     DMSNESCreate(PetscObjectComm((PetscObject)dm),snesdm);

    207:     dm->dmsnes            = (PetscObject) *snesdm;
    208:     (*snesdm)->originaldm = dm;
    209:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMSNES,DMRestrictHook_DMSNES,NULL);
    210:     DMRefineHookAdd(dm,DMRefineHook_DMSNES,DMInterpolateHook_DMSNES,NULL);
    211:     DMSubDomainHookAdd(dm,DMSubDomainHook_DMSNES,DMSubDomainRestrictHook_DMSNES,NULL);
    212:   }
    213:   return(0);
    214: }

    216: /*@C
    217:    DMGetDMSNESWrite - get write access to private DMSNES context from a DM

    219:    Not Collective

    221:    Input Parameter:
    222: .  dm - DM to be used with SNES

    224:    Output Parameter:
    225: .  snesdm - private DMSNES context

    227:    Level: developer

    229: .seealso: DMGetDMSNES()
    230: @*/
    231: PetscErrorCode DMGetDMSNESWrite(DM dm,DMSNES *snesdm)
    232: {
    234:   DMSNES         sdm;

    238:   DMGetDMSNES(dm,&sdm);
    239:   if (!sdm->originaldm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DMSNES has a NULL originaldm");
    240:   if (sdm->originaldm != dm) {  /* Copy on write */
    241:     DMSNES oldsdm = sdm;
    242:     PetscInfo(dm,"Copying DMSNES due to write\n");
    243:     DMSNESCreate(PetscObjectComm((PetscObject)dm),&sdm);
    244:     DMSNESCopy(oldsdm,sdm);
    245:     DMSNESDestroy((DMSNES*)&dm->dmsnes);
    246:     dm->dmsnes = (PetscObject)sdm;
    247:     sdm->originaldm = dm;
    248:   }
    249:   *snesdm = sdm;
    250:   return(0);
    251: }

    253: /*@C
    254:    DMCopyDMSNES - copies a DM context to a new DM

    256:    Logically Collective

    258:    Input Parameters:
    259: +  dmsrc - DM to obtain context from
    260: -  dmdest - DM to add context to

    262:    Level: developer

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

    267: .seealso: DMGetDMSNES(), SNESSetDM()
    268: @*/
    269: PetscErrorCode DMCopyDMSNES(DM dmsrc,DM dmdest)
    270: {

    276:   if (!dmdest->dmsnes) {DMSNESCreate(PetscObjectComm((PetscObject) dmdest), (DMSNES *) &dmdest->dmsnes);}
    277:   DMSNESCopy((DMSNES) dmsrc->dmsnes, (DMSNES) dmdest->dmsnes);
    278:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMSNES,NULL,NULL);
    279:   DMRefineHookAdd(dmdest,DMRefineHook_DMSNES,NULL,NULL);
    280:   DMSubDomainHookAdd(dmdest,DMSubDomainHook_DMSNES,DMSubDomainRestrictHook_DMSNES,NULL);
    281:   return(0);
    282: }

    284: /*@C
    285:    DMSNESSetFunction - set SNES residual evaluation function

    287:    Not Collective

    289:    Input Parameters:
    290: +  dm - DM to be used with SNES
    291: .  f - residual evaluation function; see SNESFunction for details
    292: -  ctx - context for residual evaluation

    294:    Level: advanced

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

    301: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), SNESFunction
    302: @*/
    303: PetscErrorCode DMSNESSetFunction(DM dm,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
    304: {
    306:   DMSNES         sdm;

    310:   if (f || ctx) {
    311:     DMGetDMSNESWrite(dm,&sdm);
    312:   }
    313:   if (f) sdm->ops->computefunction = f;
    314:   if (ctx) sdm->functionctx = ctx;
    315:   return(0);
    316: }

    318: /*@C
    319:    DMSNESSetMFFunction - set SNES residual evaluation function used in applying the matrix-free Jacobian with -snes_mf_operator

    321:    Logically Collective on dm

    323:    Input Parameters:
    324: +  dm - DM to be used with SNES
    325: -  f - residual evaluation function; see SNESFunction for details

    327:    Level: advanced

    329: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), SNESFunction, DMSNESSetFunction()
    330: @*/
    331: PetscErrorCode DMSNESSetMFFunction(DM dm,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
    332: {
    334:   DMSNES         sdm;

    338:   if (f || ctx) {
    339:     DMGetDMSNESWrite(dm,&sdm);
    340:   }
    341:   if (f) sdm->ops->computemffunction = f;
    342:   if (ctx) sdm->mffunctionctx = ctx;
    343:   return(0);
    344: }

    346: /*@C
    347:    DMSNESGetFunction - get SNES residual evaluation function

    349:    Not Collective

    351:    Input Parameter:
    352: .  dm - DM to be used with SNES

    354:    Output Parameters:
    355: +  f - residual evaluation function; see SNESFunction for details
    356: -  ctx - context for residual evaluation

    358:    Level: advanced

    360:    Note:
    361:    SNESGetFunction() is normally used, but it calls this function internally because the user context is actually
    362:    associated with the DM.

    364: .seealso: DMSNESSetContext(), DMSNESSetFunction(), SNESSetFunction(), SNESFunction
    365: @*/
    366: PetscErrorCode DMSNESGetFunction(DM dm,PetscErrorCode (**f)(SNES,Vec,Vec,void*),void **ctx)
    367: {
    369:   DMSNES         sdm;

    373:   DMGetDMSNES(dm,&sdm);
    374:   if (f) *f = sdm->ops->computefunction;
    375:   if (ctx) *ctx = sdm->functionctx;
    376:   return(0);
    377: }

    379: /*@C
    380:    DMSNESSetObjective - set SNES objective evaluation function

    382:    Not Collective

    384:    Input Parameters:
    385: +  dm - DM to be used with SNES
    386: .  obj - objective evaluation function; see SNESObjectiveFunction for details
    387: -  ctx - context for residual evaluation

    389:    Level: advanced

    391: .seealso: DMSNESSetContext(), SNESGetObjective(), DMSNESSetFunction()
    392: @*/
    393: PetscErrorCode DMSNESSetObjective(DM dm,PetscErrorCode (*obj)(SNES,Vec,PetscReal*,void*),void *ctx)
    394: {
    396:   DMSNES         sdm;

    400:   if (obj || ctx) {
    401:     DMGetDMSNESWrite(dm,&sdm);
    402:   }
    403:   if (obj) sdm->ops->computeobjective = obj;
    404:   if (ctx) sdm->objectivectx = ctx;
    405:   return(0);
    406: }

    408: /*@C
    409:    DMSNESGetObjective - get SNES objective evaluation function

    411:    Not Collective

    413:    Input Parameter:
    414: .  dm - DM to be used with SNES

    416:    Output Parameters:
    417: +  obj- residual evaluation function; see SNESObjectiveFunction for details
    418: -  ctx - context for residual evaluation

    420:    Level: advanced

    422:    Note:
    423:    SNESGetFunction() is normally used, but it calls this function internally because the user context is actually
    424:    associated with the DM.

    426: .seealso: DMSNESSetContext(), DMSNESSetObjective(), SNESSetFunction()
    427: @*/
    428: PetscErrorCode DMSNESGetObjective(DM dm,PetscErrorCode (**obj)(SNES,Vec,PetscReal*,void*),void **ctx)
    429: {
    431:   DMSNES         sdm;

    435:   DMGetDMSNES(dm,&sdm);
    436:   if (obj) *obj = sdm->ops->computeobjective;
    437:   if (ctx) *ctx = sdm->objectivectx;
    438:   return(0);
    439: }

    441: /*@C
    442:    DMSNESSetNGS - set SNES Gauss-Seidel relaxation function

    444:    Not Collective

    446:    Input Parameters:
    447: +  dm - DM to be used with SNES
    448: .  f  - relaxation function, see SNESGSFunction
    449: -  ctx - context for residual evaluation

    451:    Level: advanced

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

    458: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), DMSNESSetFunction(), SNESGSFunction
    459: @*/
    460: PetscErrorCode DMSNESSetNGS(DM dm,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
    461: {
    463:   DMSNES         sdm;

    467:   if (f || ctx) {
    468:     DMGetDMSNESWrite(dm,&sdm);
    469:   }
    470:   if (f) sdm->ops->computegs = f;
    471:   if (ctx) sdm->gsctx = ctx;
    472:   return(0);
    473: }

    475: /*@C
    476:    DMSNESGetNGS - get SNES Gauss-Seidel relaxation function

    478:    Not Collective

    480:    Input Parameter:
    481: .  dm - DM to be used with SNES

    483:    Output Parameters:
    484: +  f - relaxation function which performs Gauss-Seidel sweeps, see SNESGSFunction
    485: -  ctx - context for residual evaluation

    487:    Level: advanced

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

    494: .seealso: DMSNESSetContext(), SNESGetNGS(), DMSNESGetJacobian(), DMSNESGetFunction(), SNESNGSFunction
    495: @*/
    496: PetscErrorCode DMSNESGetNGS(DM dm,PetscErrorCode (**f)(SNES,Vec,Vec,void*),void **ctx)
    497: {
    499:   DMSNES         sdm;

    503:   DMGetDMSNES(dm,&sdm);
    504:   if (f) *f = sdm->ops->computegs;
    505:   if (ctx) *ctx = sdm->gsctx;
    506:   return(0);
    507: }

    509: /*@C
    510:    DMSNESSetJacobian - set SNES Jacobian evaluation function

    512:    Not Collective

    514:    Input Parameters:
    515: +  dm - DM to be used with SNES
    516: .  J - Jacobian evaluation function
    517: -  ctx - context for residual evaluation

    519:    Level: advanced

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

    526: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESGetJacobian(), SNESSetJacobian(), SNESJacobianFunction
    527: @*/
    528: PetscErrorCode DMSNESSetJacobian(DM dm,PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
    529: {
    531:   DMSNES         sdm;

    535:   if (J || ctx) {
    536:     DMGetDMSNESWrite(dm,&sdm);
    537:   }
    538:   if (J) sdm->ops->computejacobian = J;
    539:   if (ctx) sdm->jacobianctx = ctx;
    540:   return(0);
    541: }

    543: /*@C
    544:    DMSNESGetJacobian - get SNES Jacobian evaluation function

    546:    Not Collective

    548:    Input Parameter:
    549: .  dm - DM to be used with SNES

    551:    Output Parameters:
    552: +  J - Jacobian evaluation function; see SNESJacobianFunction for all calling sequence
    553: -  ctx - context for residual evaluation

    555:    Level: advanced

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

    562: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), SNESJacobianFunction
    563: @*/
    564: PetscErrorCode DMSNESGetJacobian(DM dm,PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
    565: {
    567:   DMSNES         sdm;

    571:   DMGetDMSNES(dm,&sdm);
    572:   if (J) *J = sdm->ops->computejacobian;
    573:   if (ctx) *ctx = sdm->jacobianctx;
    574:   return(0);
    575: }

    577: /*@C
    578:    DMSNESSetPicard - set SNES Picard iteration matrix and RHS evaluation functions.

    580:    Not Collective

    582:    Input Parameters:
    583: +  dm - DM to be used with SNES
    584: .  b - RHS evaluation function
    585: .  J - Picard matrix evaluation function
    586: -  ctx - context for residual evaluation

    588:    Level: advanced

    590: .seealso: SNESSetPicard(), DMSNESSetFunction(), DMSNESSetJacobian()
    591: @*/
    592: PetscErrorCode DMSNESSetPicard(DM dm,PetscErrorCode (*b)(SNES,Vec,Vec,void*),PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
    593: {
    595:   DMSNES         sdm;

    599:   DMGetDMSNES(dm,&sdm);
    600:   if (b) sdm->ops->computepfunction = b;
    601:   if (J) sdm->ops->computepjacobian = J;
    602:   if (ctx) sdm->pctx = ctx;
    603:   return(0);
    604: }

    606: /*@C
    607:    DMSNESGetPicard - get SNES Picard iteration evaluation functions

    609:    Not Collective

    611:    Input Parameter:
    612: .  dm - DM to be used with SNES

    614:    Output Parameters:
    615: +  b - RHS evaluation function; see SNESFunction for details
    616: .  J  - RHS evaluation function; see SNESJacobianFunction for detailsa
    617: -  ctx - context for residual evaluation

    619:    Level: advanced

    621: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
    622: @*/
    623: PetscErrorCode DMSNESGetPicard(DM dm,PetscErrorCode (**b)(SNES,Vec,Vec,void*),PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
    624: {
    626:   DMSNES         sdm;

    630:   DMGetDMSNES(dm,&sdm);
    631:   if (b) *b = sdm->ops->computepfunction;
    632:   if (J) *J = sdm->ops->computepjacobian;
    633:   if (ctx) *ctx = sdm->pctx;
    634:   return(0);
    635: }