Date: 2013-07-02T14:50:42+00:00

Actual source code: dmsnes.c
petsc-3.4.2 2013-07-02

      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,PETSC_FUNCTION);
     27:   PetscViewerBinaryRead(viewer,&kdm->ops->computejacobian,1,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:       PetscErrorCode (*jac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
     58:     } funcstruct = {kdm->ops->computefunction,kdm->ops->computejacobian};
     59:     PetscViewerBinaryWrite(viewer,&funcstruct,2,PETSC_FUNCTION,PETSC_FALSE);
     60:   }
     61:   return(0);
     62: }

     66: static PetscErrorCode DMSNESCreate(MPI_Comm comm,DMSNES *kdm)
     67: {

     71: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
     72:   SNESInitializePackage();
     73: #endif
     74:   PetscHeaderCreate(*kdm, _p_DMSNES, struct _DMSNESOps, DMSNES_CLASSID,  "DMSNES", "DMSNES", "DMSNES", comm, DMSNESDestroy, DMSNESView);
     75:   PetscMemzero((*kdm)->ops, sizeof(struct _DMSNESOps));
     76:   return(0);
     77: }

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

     89:   DMCopyDMSNES(dm,dmc);
     90:   return(0);
     91: }

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

    101:   return(0);
    102: }

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

    112:   DMCopyDMSNES(dm,subdm);
    113:   return(0);
    114: }

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

    124:   return(0);
    125: }

    129: static PetscErrorCode DMRefineHook_DMSNES(DM dm,DM dmf,void *ctx)
    130: {

    134:   DMCopyDMSNES(dm,dmf);
    135:   return(0);
    136: }

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

    146:   return(0);
    147: }

    151: /*@C
    152:    DMSNESCopy - copies the information in a DMSNES to another DMSNES

    154:    Not Collective

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

    160:    Level: developer

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

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

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

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

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

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

    203:    Not Collective

    205:    Input Argument:
    206: .  dm - DM to be used with SNES

    208:    Output Argument:
    209: .  snesdm - private DMSNES context

    211:    Level: developer

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

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

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

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

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

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

    243:    Not Collective

    245:    Input Argument:
    246: .  dm - DM to be used with SNES

    248:    Output Argument:
    249: .  snesdm - private DMSNES context

    251:    Level: developer

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

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

    278: /*@C
    279:    DMCopyDMSNES - copies a DM context to a new DM

    281:    Logically Collective

    283:    Input Arguments:
    284: +  dmsrc - DM to obtain context from
    285: -  dmdest - DM to add context to

    287:    Level: developer

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

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

    301:   DMSNESDestroy((DMSNES*)&dmdest->dmsnes);

    303:   dmdest->dmsnes = dmsrc->dmsnes;

    305:   PetscObjectReference(dmdest->dmsnes);
    306:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMSNES,NULL,NULL);
    307:   DMRefineHookAdd(dmdest,DMRefineHook_DMSNES,NULL,NULL);
    308:   DMSubDomainHookAdd(dmdest,DMSubDomainHook_DMSNES,DMSubDomainRestrictHook_DMSNES,NULL);
    309:   return(0);
    310: }

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

    317:    Not Collective

    319:    Input Arguments:
    320: +  dm - DM to be used with SNES
    321: .  SNESFunction - residual evaluation function
    322: -  ctx - context for residual evaluation

    324:    Level: advanced

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

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

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

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

    353:    Not Collective

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

    358:    Output Arguments:
    359: +  SNESFunction - residual evaluation function
    360: -  ctx - context for residual evaluation

    362:    Level: advanced

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

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

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

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

    388:    Not Collective

    390:    Input Arguments:
    391: +  dm - DM to be used with SNES
    392: .  SNESObjectiveFunction - residual evaluation function
    393: -  ctx - context for residual evaluation

    395:    Level: advanced

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

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

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

    419:    Not Collective

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

    424:    Output Arguments:
    425: +  SNESObjectiveFunction- residual evaluation function
    426: -  ctx - context for residual evaluation

    428:    Level: advanced

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

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

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

    451: /*@C
    452:    DMSNESSetGS - set SNES Gauss-Seidel relaxation function

    454:    Not Collective

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

    461:    Level: advanced

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

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

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

    487: /*@C
    488:    DMSNESGetGS - get SNES Gauss-Seidel relaxation function

    490:    Not Collective

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

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

    499:    Level: advanced

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

    506: .seealso: DMSNESSetContext(), SNESGetGS(), DMSNESGetJacobian(), DMSNESGetFunction(), SNESGSFunction
    507: @*/
    508: PetscErrorCode DMSNESGetGS(DM dm,PetscErrorCode (**SNESGSFunction)(SNES,Vec,Vec,void*),void **ctx)
    509: {
    511:   DMSNES         sdm;

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

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

    526:    Not Collective

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

    533:    Level: advanced

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

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

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

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

    562:    Not Collective

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

    567:    Output Arguments:
    568: +  SNESJacobianFunction - Jacobian evaluation function
    569: -  ctx - context for residual evaluation

    571:    Level: advanced

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

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

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

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

    598:    Not Collective

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

    606:    Level: advanced

    608: .seealso: SNESSetPicard(), DMSNESSetFunction(), DMSNESSetJacobian()
    609: @*/
    610: PetscErrorCode DMSNESSetPicard(DM dm,PetscErrorCode (*SNESFunction)(SNES,Vec,Vec,void*),PetscErrorCode (*SNESJacobianFunction)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
    611: {
    613:   DMSNES         sdm;

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

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

    629:    Not Collective

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

    634:    Output Arguments:
    635: +  SNESFunction - Jacobian evaluation function;
    636: .  SNESJacobianFunction  - RHS evaluation function;
    637: -  ctx - context for residual evaluation

    639:    Level: advanced

    641: .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
    642: @*/
    643: PetscErrorCode DMSNESGetPicard(DM dm,PetscErrorCode (**SNESFunction)(SNES,Vec,Vec,void*),PetscErrorCode (**SNESJacobianFunction)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
    644: {
    646:   DMSNES         sdm;

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