Date: 2015-10-02T22:26:00+00:00

Actual source code: dmsnes.c
petsc-3.6.2 2015-10-02
Report Typos and Errors

      1: #include <petsc/private/snesimpl.h>   /*I "petscsnes.h" I*/
      2: #include <petsc/private/dmimpl.h>     /*I "petscdm.h" I*/

      6: static PetscErrorCode DMSNESDestroy(DMSNES *kdm)
      7: {

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

     21: PetscErrorCode DMSNESLoad(DMSNES kdm,PetscViewer viewer)
     22: {

     26:   PetscViewerBinaryRead(viewer,&kdm->ops->computefunction,1,NULL,PETSC_FUNCTION);
     27:   PetscViewerBinaryRead(viewer,&kdm->ops->computejacobian,1,NULL,PETSC_FUNCTION);
     28:   return(0);
     29: }

     33: PetscErrorCode DMSNESView(DMSNES kdm,PetscViewer viewer)
     34: {
     36:   PetscBool      isascii,isbinary;

     39:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
     40:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
     41:   if (isascii) {
     42: #if defined(PETSC_SERIALIZE_FUNCTIONS)
     43:     const char *fname;

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

     71: static PetscErrorCode DMSNESCreate(MPI_Comm comm,DMSNES *kdm)
     72: {

     76:   SNESInitializePackage();
     77:   PetscHeaderCreate(*kdm, DMSNES_CLASSID,  "DMSNES", "DMSNES", "DMSNES", comm, DMSNESDestroy, DMSNESView);
     78:   return(0);
     79: }

     83: /* Attaches the DMSNES to the coarse level.
     84:  * Under what conditions should we copy versus duplicate?
     85:  */
     86: static PetscErrorCode DMCoarsenHook_DMSNES(DM dm,DM dmc,void *ctx)
     87: {

     91:   DMCopyDMSNES(dm,dmc);
     92:   return(0);
     93: }

     97: /* This could restrict auxiliary information to the coarse level.
     98:  */
     99: static PetscErrorCode DMRestrictHook_DMSNES(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx)
    100: {

    103:   return(0);
    104: }

    108: /* Attaches the DMSNES to the subdomain. */
    109: static PetscErrorCode DMSubDomainHook_DMSNES(DM dm,DM subdm,void *ctx)
    110: {

    114:   DMCopyDMSNES(dm,subdm);
    115:   return(0);
    116: }

    120: /* This could restrict auxiliary information to the coarse level.
    121:  */
    122: static PetscErrorCode DMSubDomainRestrictHook_DMSNES(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
    123: {

    126:   return(0);
    127: }

    131: static PetscErrorCode DMRefineHook_DMSNES(DM dm,DM dmf,void *ctx)
    132: {

    136:   DMCopyDMSNES(dm,dmf);
    137:   return(0);
    138: }

    142: /* This could restrict auxiliary information to the coarse level.
    143:  */
    144: static PetscErrorCode DMInterpolateHook_DMSNES(DM dm,Mat Interp,DM dmf,void *ctx)
    145: {

    148:   return(0);
    149: }

    153: /*@C
    154:    DMSNESCopy - copies the information in a DMSNES to another DMSNES

    156:    Not Collective

    158:    Input Argument:
    159: +  kdm - Original DMSNES
    160: -  nkdm - DMSNES to receive the data, should have been created with DMSNESCreate()

    162:    Level: developer

    164: .seealso: DMSNESCreate(), DMSNESDestroy()
    165: @*/
    166: PetscErrorCode DMSNESCopy(DMSNES kdm,DMSNES nkdm)
    167: {

    173:   nkdm->ops->computefunction  = kdm->ops->computefunction;
    174:   nkdm->ops->computejacobian  = kdm->ops->computejacobian;
    175:   nkdm->ops->computegs        = kdm->ops->computegs;
    176:   nkdm->ops->computeobjective = kdm->ops->computeobjective;
    177:   nkdm->ops->computepjacobian = kdm->ops->computepjacobian;
    178:   nkdm->ops->computepfunction = kdm->ops->computepfunction;
    179:   nkdm->ops->destroy          = kdm->ops->destroy;
    180:   nkdm->ops->duplicate        = kdm->ops->duplicate;

    182:   nkdm->functionctx  = kdm->functionctx;
    183:   nkdm->gsctx        = kdm->gsctx;
    184:   nkdm->pctx         = kdm->pctx;
    185:   nkdm->jacobianctx  = kdm->jacobianctx;
    186:   nkdm->objectivectx = kdm->objectivectx;
    187:   nkdm->data         = kdm->data;

    189:   /*
    190:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
    191:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
    192:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
    193:   */

    195:   /* implementation specific copy hooks */
    196:   if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
    197:   return(0);
    198: }

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

    205:    Not Collective

    207:    Input Argument:
    208: .  dm - DM to be used with SNES

    210:    Output Argument:
    211: .  snesdm - private DMSNES context

    213:    Level: developer

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

    218: .seealso: DMGetDMSNESWrite()
    219: @*/
    220: PetscErrorCode DMGetDMSNES(DM dm,DMSNES *snesdm)
    221: {

    226:   *snesdm = (DMSNES) dm->dmsnes;
    227:   if (!*snesdm) {
    228:     PetscInfo(dm,"Creating new DMSNES\n");
    229:     DMSNESCreate(PetscObjectComm((PetscObject)dm),snesdm);

    231:     dm->dmsnes = (PetscObject) *snesdm;

    233:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMSNES,DMRestrictHook_DMSNES,NULL);
    234:     DMRefineHookAdd(dm,DMRefineHook_DMSNES,DMInterpolateHook_DMSNES,NULL);
    235:     DMSubDomainHookAdd(dm,DMSubDomainHook_DMSNES,DMSubDomainRestrictHook_DMSNES,NULL);
    236:   }
    237:   return(0);
    238: }

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

    245:    Not Collective

    247:    Input Argument:
    248: .  dm - DM to be used with SNES

    250:    Output Argument:
    251: .  snesdm - private DMSNES context

    253:    Level: developer

    255: .seealso: DMGetDMSNES()
    256: @*/
    257: PetscErrorCode DMGetDMSNESWrite(DM dm,DMSNES *snesdm)
    258: {
    260:   DMSNES         sdm;

    264:   DMGetDMSNES(dm,&sdm);
    265:   if (!sdm->originaldm) sdm->originaldm = dm;
    266:   if (sdm->originaldm != dm) {  /* Copy on write */
    267:     DMSNES oldsdm = sdm;
    268:     PetscInfo(dm,"Copying DMSNES due to write\n");
    269:     DMSNESCreate(PetscObjectComm((PetscObject)dm),&sdm);
    270:     DMSNESCopy(oldsdm,sdm);
    271:     DMSNESDestroy((DMSNES*)&dm->dmsnes);
    272:     dm->dmsnes = (PetscObject)sdm;
    273:   }
    274:   *snesdm = sdm;
    275:   return(0);
    276: }

    280: /*@C
    281:    DMCopyDMSNES - copies a DM context to a new DM

    283:    Logically Collective

    285:    Input Arguments:
    286: +  dmsrc - DM to obtain context from
    287: -  dmdest - DM to add context to

    289:    Level: developer

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

    294: .seealso: DMGetDMSNES(), SNESSetDM()
    295: @*/
    296: PetscErrorCode DMCopyDMSNES(DM dmsrc,DM dmdest)
    297: {

    303:   if (!dmdest->dmsnes) {DMSNESCreate(PetscObjectComm((PetscObject) dmdest), (DMSNES *) &dmdest->dmsnes);}
    304:   DMSNESCopy((DMSNES) dmsrc->dmsnes, (DMSNES) dmdest->dmsnes);
    305:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMSNES,NULL,NULL);
    306:   DMRefineHookAdd(dmdest,DMRefineHook_DMSNES,NULL,NULL);
    307:   DMSubDomainHookAdd(dmdest,DMSubDomainHook_DMSNES,DMSubDomainRestrictHook_DMSNES,NULL);
    308:   return(0);
    309: }

    313: /*@C
    314:    DMSNESSetFunction - set SNES residual evaluation function

    316:    Not Collective

    318:    Input Arguments:
    319: +  dm - DM to be used with SNES
    320: .  f - residual evaluation function; see SNESFunction for details
    321: -  ctx - context for residual evaluation

    323:    Level: advanced

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

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

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

    349: /*@C
    350:    DMSNESGetFunction - get SNES residual evaluation function

    352:    Not Collective

    354:    Input Argument:
    355: .  dm - DM to be used with SNES

    357:    Output Arguments:
    358: +  f - residual evaluation function; see SNESFunction for details
    359: -  ctx - context for residual evaluation

    361:    Level: advanced

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

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

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

    384: /*@C
    385:    DMSNESSetObjective - set SNES objective evaluation function

    387:    Not Collective

    389:    Input Arguments:
    390: +  dm - DM to be used with SNES
    391: .  obj - objective evaluation function; see SNESObjectiveFunction for details
    392: -  ctx - context for residual evaluation

    394:    Level: advanced

    396: .seealso: DMSNESSetContext(), SNESGetObjective(), DMSNESSetFunction()
    397: @*/
    398: PetscErrorCode DMSNESSetObjective(DM dm,PetscErrorCode (*obj)(SNES,Vec,PetscReal*,void*),void *ctx)
    399: {
    401:   DMSNES         sdm;

    405:   if (obj || ctx) {
    406:     DMGetDMSNESWrite(dm,&sdm);
    407:   }
    408:   if (obj) sdm->ops->computeobjective = obj;
    409:   if (ctx) sdm->objectivectx = ctx;
    410:   return(0);
    411: }

    415: /*@C
    416:    DMSNESGetObjective - get SNES objective evaluation function

    418:    Not Collective

    420:    Input Argument:
    421: .  dm - DM to be used with SNES

    423:    Output Arguments:
    424: +  obj- residual evaluation function; see SNESObjectiveFunction for details
    425: -  ctx - context for residual evaluation

    427:    Level: advanced

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

    433: .seealso: DMSNESSetContext(), DMSNESSetObjective(), SNESSetFunction()
    434: @*/
    435: PetscErrorCode DMSNESGetObjective(DM dm,PetscErrorCode (**obj)(SNES,Vec,PetscReal*,void*),void **ctx)
    436: {
    438:   DMSNES         sdm;

    442:   DMGetDMSNES(dm,&sdm);
    443:   if (obj) *obj = sdm->ops->computeobjective;
    444:   if (ctx) *ctx = sdm->objectivectx;
    445:   return(0);
    446: }

    450: /*@C
    451:    DMSNESSetNGS - set SNES Gauss-Seidel relaxation function

    453:    Not Collective

    455:    Input Argument:
    456: +  dm - DM to be used with SNES
    457: .  f  - relaxation function, see SNESGSFunction
    458: -  ctx - context for residual evaluation

    460:    Level: advanced

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

    467: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), DMSNESSetFunction(), SNESGSFunction
    468: @*/
    469: PetscErrorCode DMSNESSetNGS(DM dm,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx)
    470: {
    472:   DMSNES         sdm;

    476:   if (f || ctx) {
    477:     DMGetDMSNESWrite(dm,&sdm);
    478:   }
    479:   if (f) sdm->ops->computegs = f;
    480:   if (ctx) sdm->gsctx = ctx;
    481:   return(0);
    482: }

    486: /*@C
    487:    DMSNESGetNGS - get SNES Gauss-Seidel relaxation function

    489:    Not Collective

    491:    Input Argument:
    492: .  dm - DM to be used with SNES

    494:    Output Arguments:
    495: +  f - relaxation function which performs Gauss-Seidel sweeps, see SNESGSFunction
    496: -  ctx - context for residual evaluation

    498:    Level: advanced

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

    505: .seealso: DMSNESSetContext(), SNESGetNGS(), DMSNESGetJacobian(), DMSNESGetFunction(), SNESNGSFunction
    506: @*/
    507: PetscErrorCode DMSNESGetNGS(DM dm,PetscErrorCode (**f)(SNES,Vec,Vec,void*),void **ctx)
    508: {
    510:   DMSNES         sdm;

    514:   DMGetDMSNES(dm,&sdm);
    515:   if (f) *f = sdm->ops->computegs;
    516:   if (ctx) *ctx = sdm->gsctx;
    517:   return(0);
    518: }

    522: /*@C
    523:    DMSNESSetJacobian - set SNES Jacobian evaluation function

    525:    Not Collective

    527:    Input Argument:
    528: +  dm - DM to be used with SNES
    529: .  J - Jacobian evaluation function
    530: -  ctx - context for residual evaluation

    532:    Level: advanced

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

    539: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESGetJacobian(), SNESSetJacobian(), SNESJacobianFunction
    540: @*/
    541: PetscErrorCode DMSNESSetJacobian(DM dm,PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
    542: {
    544:   DMSNES         sdm;

    548:   if (J || ctx) {
    549:     DMGetDMSNESWrite(dm,&sdm);
    550:   }
    551:   if (J) sdm->ops->computejacobian = J;
    552:   if (ctx) sdm->jacobianctx = ctx;
    553:   return(0);
    554: }

    558: /*@C
    559:    DMSNESGetJacobian - get SNES Jacobian evaluation function

    561:    Not Collective

    563:    Input Argument:
    564: .  dm - DM to be used with SNES

    566:    Output Arguments:
    567: +  J - Jacobian evaluation function; see SNESJacobianFunction for all calling sequence
    568: -  ctx - context for residual evaluation

    570:    Level: advanced

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

    577: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), SNESJacobianFunction
    578: @*/
    579: PetscErrorCode DMSNESGetJacobian(DM dm,PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
    580: {
    582:   DMSNES         sdm;

    586:   DMGetDMSNES(dm,&sdm);
    587:   if (J) *J = sdm->ops->computejacobian;
    588:   if (ctx) *ctx = sdm->jacobianctx;
    589:   return(0);
    590: }

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

    597:    Not Collective

    599:    Input Argument:
    600: +  dm - DM to be used with SNES
    601: .  b - RHS evaluation function
    602: .  J - Picard matrix evaluation function
    603: -  ctx - context for residual evaluation

    605:    Level: advanced

    607: .seealso: SNESSetPicard(), DMSNESSetFunction(), DMSNESSetJacobian()
    608: @*/
    609: PetscErrorCode DMSNESSetPicard(DM dm,PetscErrorCode (*b)(SNES,Vec,Vec,void*),PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx)
    610: {
    612:   DMSNES         sdm;

    616:   DMGetDMSNES(dm,&sdm);
    617:   if (b) sdm->ops->computepfunction = b;
    618:   if (J) sdm->ops->computepjacobian = J;
    619:   if (ctx) sdm->pctx = ctx;
    620:   return(0);
    621: }

    625: /*@C
    626:    DMSNESGetPicard - get SNES Picard iteration evaluation functions

    628:    Not Collective

    630:    Input Argument:
    631: .  dm - DM to be used with SNES

    633:    Output Arguments:
    634: +  b - RHS evaluation function; see SNESFunction for details
    635: .  J  - RHS evaluation function; see SNESJacobianFunction for detailsa
    636: -  ctx - context for residual evaluation

    638:    Level: advanced

    640: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
    641: @*/
    642: PetscErrorCode DMSNESGetPicard(DM dm,PetscErrorCode (**b)(SNES,Vec,Vec,void*),PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx)
    643: {
    645:   DMSNES         sdm;

    649:   DMGetDMSNES(dm,&sdm);
    650:   if (b) *b = sdm->ops->computepfunction;
    651:   if (J) *J = sdm->ops->computepjacobian;
    652:   if (ctx) *ctx = sdm->pctx;
    653:   return(0);
    654: }