Actual source code: dmts.c
petsc-3.10.5 2019-03-28
Report Typos and Errors

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

      4: static PetscErrorCode DMTSDestroy(DMTS *kdm)
      5: {

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

     17: PetscErrorCode DMTSLoad(DMTS kdm,PetscViewer viewer)
     18: {

     22:   PetscViewerBinaryRead(viewer,&kdm->ops->ifunction,1,NULL,PETSC_FUNCTION);
     23:   PetscViewerBinaryRead(viewer,&kdm->ops->ifunctionview,1,NULL,PETSC_FUNCTION);
     24:   PetscViewerBinaryRead(viewer,&kdm->ops->ifunctionload,1,NULL,PETSC_FUNCTION);
     25:   if (kdm->ops->ifunctionload) {
     26:     (*kdm->ops->ifunctionload)(&kdm->ifunctionctx,viewer);
     27:   }
     28:   PetscViewerBinaryRead(viewer,&kdm->ops->ijacobian,1,NULL,PETSC_FUNCTION);
     29:   PetscViewerBinaryRead(viewer,&kdm->ops->ijacobianview,1,NULL,PETSC_FUNCTION);
     30:   PetscViewerBinaryRead(viewer,&kdm->ops->ijacobianload,1,NULL,PETSC_FUNCTION);
     31:   if (kdm->ops->ijacobianload) {
     32:     (*kdm->ops->ijacobianload)(&kdm->ijacobianctx,viewer);
     33:   }
     34:   return(0);
     35: }

     37: PetscErrorCode DMTSView(DMTS kdm,PetscViewer viewer)
     38: {
     40:   PetscBool      isascii,isbinary;

     43:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
     44:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
     45:   if (isascii) {
     46: #if defined(PETSC_SERIALIZE_FUNCTIONS)
     47:     const char *fname;

     49:     PetscFPTFind(kdm->ops->ifunction,&fname);
     50:     if (fname) {
     51:       PetscViewerASCIIPrintf(viewer,"  IFunction used by TS: %s\n",fname);
     52:     }
     53:     PetscFPTFind(kdm->ops->ijacobian,&fname);
     54:     if (fname) {
     55:       PetscViewerASCIIPrintf(viewer,"  IJacobian function used by TS: %s\n",fname);
     56:     }
     57: #endif
     58:   } else if (isbinary) {
     59:     struct {
     60:       TSIFunction ifunction;
     61:     } funcstruct;
     62:     struct {
     63:       PetscErrorCode (*ifunctionview)(void*,PetscViewer);
     64:     } funcviewstruct;
     65:     struct {
     66:       PetscErrorCode (*ifunctionload)(void**,PetscViewer);
     67:     } funcloadstruct;
     68:     struct {
     69:       TSIJacobian ijacobian;
     70:     } jacstruct;
     71:     struct {
     72:       PetscErrorCode (*ijacobianview)(void*,PetscViewer);
     73:     } jacviewstruct;
     74:     struct {
     75:       PetscErrorCode (*ijacobianload)(void**,PetscViewer);
     76:     } jacloadstruct;

     78:     funcstruct.ifunction         = kdm->ops->ifunction;
     79:     funcviewstruct.ifunctionview = kdm->ops->ifunctionview;
     80:     funcloadstruct.ifunctionload = kdm->ops->ifunctionload;
     81:     PetscViewerBinaryWrite(viewer,&funcstruct,1,PETSC_FUNCTION,PETSC_FALSE);
     82:     PetscViewerBinaryWrite(viewer,&funcviewstruct,1,PETSC_FUNCTION,PETSC_FALSE);
     83:     PetscViewerBinaryWrite(viewer,&funcloadstruct,1,PETSC_FUNCTION,PETSC_FALSE);
     84:     if (kdm->ops->ifunctionview) {
     85:       (*kdm->ops->ifunctionview)(kdm->ifunctionctx,viewer);
     86:     }
     87:     jacstruct.ijacobian = kdm->ops->ijacobian;
     88:     jacviewstruct.ijacobianview = kdm->ops->ijacobianview;
     89:     jacloadstruct.ijacobianload = kdm->ops->ijacobianload;
     90:     PetscViewerBinaryWrite(viewer,&jacstruct,1,PETSC_FUNCTION,PETSC_FALSE);
     91:     PetscViewerBinaryWrite(viewer,&jacviewstruct,1,PETSC_FUNCTION,PETSC_FALSE);
     92:     PetscViewerBinaryWrite(viewer,&jacloadstruct,1,PETSC_FUNCTION,PETSC_FALSE);
     93:     if (kdm->ops->ijacobianview) {
     94:       (*kdm->ops->ijacobianview)(kdm->ijacobianctx,viewer);
     95:     }
     96:   }
     97:   return(0);
     98: }

    100: static PetscErrorCode DMTSCreate(MPI_Comm comm,DMTS *kdm)
    101: {

    105:   TSInitializePackage();
    106:   PetscHeaderCreate(*kdm, DMTS_CLASSID, "DMTS", "DMTS", "DMTS", comm, DMTSDestroy, DMTSView);
    107:   return(0);
    108: }

    110: /* Attaches the DMTS to the coarse level.
    111:  * Under what conditions should we copy versus duplicate?
    112:  */
    113: static PetscErrorCode DMCoarsenHook_DMTS(DM dm,DM dmc,void *ctx)
    114: {

    118:   DMCopyDMTS(dm,dmc);
    119:   return(0);
    120: }

    122: /* This could restrict auxiliary information to the coarse level.
    123:  */
    124: static PetscErrorCode DMRestrictHook_DMTS(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx)
    125: {

    128:   return(0);
    129: }

    131: static PetscErrorCode DMSubDomainHook_DMTS(DM dm,DM subdm,void *ctx)
    132: {

    136:   DMCopyDMTS(dm,subdm);
    137:   return(0);
    138: }

    140: /* This could restrict auxiliary information to the coarse level.
    141:  */
    142: static PetscErrorCode DMSubDomainRestrictHook_DMTS(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
    143: {
    145:   return(0);
    146: }

    148: /*@C
    149:    DMTSCopy - copies the information in a DMTS to another DMTS

    151:    Not Collective

    153:    Input Argument:
    154: +  kdm - Original DMTS
    155: -  nkdm - DMTS to receive the data, should have been created with DMTSCreate()

    157:    Level: developer

    159: .seealso: DMTSCreate(), DMTSDestroy()
    160: @*/
    161: PetscErrorCode DMTSCopy(DMTS kdm,DMTS nkdm)
    162: {

    168:   nkdm->ops->rhsfunction = kdm->ops->rhsfunction;
    169:   nkdm->ops->rhsjacobian = kdm->ops->rhsjacobian;
    170:   nkdm->ops->ifunction   = kdm->ops->ifunction;
    171:   nkdm->ops->ijacobian   = kdm->ops->ijacobian;
    172:   nkdm->ops->i2function  = kdm->ops->i2function;
    173:   nkdm->ops->i2jacobian  = kdm->ops->i2jacobian;
    174:   nkdm->ops->solution    = kdm->ops->solution;
    175:   nkdm->ops->destroy     = kdm->ops->destroy;
    176:   nkdm->ops->duplicate   = kdm->ops->duplicate;

    178:   nkdm->rhsfunctionctx = kdm->rhsfunctionctx;
    179:   nkdm->rhsjacobianctx = kdm->rhsjacobianctx;
    180:   nkdm->ifunctionctx   = kdm->ifunctionctx;
    181:   nkdm->ijacobianctx   = kdm->ijacobianctx;
    182:   nkdm->i2functionctx  = kdm->i2functionctx;
    183:   nkdm->i2jacobianctx  = kdm->i2jacobianctx;
    184:   nkdm->solutionctx    = kdm->solutionctx;

    186:   nkdm->data = kdm->data;

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

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

    199: /*@C
    200:    DMGetDMTS - get read-only private DMTS context from a DM

    202:    Not Collective

    204:    Input Argument:
    205: .  dm - DM to be used with TS

    207:    Output Argument:
    208: .  tsdm - private DMTS context

    210:    Level: developer

    212:    Notes:
    213:    Use DMGetDMTSWrite() if write access is needed. The DMTSSetXXX API should be used wherever possible.

    215: .seealso: DMGetDMTSWrite()
    216: @*/
    217: PetscErrorCode DMGetDMTS(DM dm,DMTS *tsdm)
    218: {

    223:   *tsdm = (DMTS) dm->dmts;
    224:   if (!*tsdm) {
    225:     PetscInfo(dm,"Creating new DMTS\n");
    226:     DMTSCreate(PetscObjectComm((PetscObject)dm),tsdm);
    227:     dm->dmts = (PetscObject) *tsdm;
    228:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMTS,DMRestrictHook_DMTS,NULL);
    229:     DMSubDomainHookAdd(dm,DMSubDomainHook_DMTS,DMSubDomainRestrictHook_DMTS,NULL);
    230:   }
    231:   return(0);
    232: }

    234: /*@C
    235:    DMGetDMTSWrite - get write access to private DMTS context from a DM

    237:    Not Collective

    239:    Input Argument:
    240: .  dm - DM to be used with TS

    242:    Output Argument:
    243: .  tsdm - private DMTS context

    245:    Level: developer

    247: .seealso: DMGetDMTS()
    248: @*/
    249: PetscErrorCode DMGetDMTSWrite(DM dm,DMTS *tsdm)
    250: {
    252:   DMTS           sdm;

    256:   DMGetDMTS(dm,&sdm);
    257:   if (!sdm->originaldm) sdm->originaldm = dm;
    258:   if (sdm->originaldm != dm) {  /* Copy on write */
    259:     DMTS oldsdm = sdm;
    260:     PetscInfo(dm,"Copying DMTS due to write\n");
    261:     DMTSCreate(PetscObjectComm((PetscObject)dm),&sdm);
    262:     DMTSCopy(oldsdm,sdm);
    263:     DMTSDestroy((DMTS*)&dm->dmts);
    264:     dm->dmts = (PetscObject) sdm;
    265:   }
    266:   *tsdm = sdm;
    267:   return(0);
    268: }

    270: /*@C
    271:    DMCopyDMTS - copies a DM context to a new DM

    273:    Logically Collective

    275:    Input Arguments:
    276: +  dmsrc - DM to obtain context from
    277: -  dmdest - DM to add context to

    279:    Level: developer

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

    284: .seealso: DMGetDMTS(), TSSetDM()
    285: @*/
    286: PetscErrorCode DMCopyDMTS(DM dmsrc,DM dmdest)
    287: {

    293:   DMTSDestroy((DMTS*)&dmdest->dmts);
    294:   dmdest->dmts = dmsrc->dmts;
    295:   PetscObjectReference(dmdest->dmts);
    296:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMTS,DMRestrictHook_DMTS,NULL);
    297:   DMSubDomainHookAdd(dmdest,DMSubDomainHook_DMTS,DMSubDomainRestrictHook_DMTS,NULL);
    298:   return(0);
    299: }

    301: /*@C
    302:    DMTSSetIFunction - set TS implicit function evaluation function

    304:    Not Collective

    306:    Input Arguments:
    307: +  dm - DM to be used with TS
    308: .  func - function evaluation function, see TSSetIFunction() for calling sequence
    309: -  ctx - context for residual evaluation

    311:    Level: advanced

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

    318: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
    319: @*/
    320: PetscErrorCode DMTSSetIFunction(DM dm,TSIFunction func,void *ctx)
    321: {
    323:   DMTS           tsdm;

    327:   DMGetDMTSWrite(dm,&tsdm);
    328:   if (func) tsdm->ops->ifunction = func;
    329:   if (ctx)  tsdm->ifunctionctx = ctx;
    330:   return(0);
    331: }

    333: /*@C
    334:    DMTSGetIFunction - get TS implicit residual evaluation function

    336:    Not Collective

    338:    Input Argument:
    339: .  dm - DM to be used with TS

    341:    Output Arguments:
    342: +  func - function evaluation function, see TSSetIFunction() for calling sequence
    343: -  ctx - context for residual evaluation

    345:    Level: advanced

    347:    Note:
    348:    TSGetFunction() is normally used, but it calls this function internally because the user context is actually
    349:    associated with the DM.

    351: .seealso: DMTSSetContext(), DMTSSetFunction(), TSSetFunction()
    352: @*/
    353: PetscErrorCode DMTSGetIFunction(DM dm,TSIFunction *func,void **ctx)
    354: {
    356:   DMTS           tsdm;

    360:   DMGetDMTS(dm,&tsdm);
    361:   if (func) *func = tsdm->ops->ifunction;
    362:   if (ctx)  *ctx = tsdm->ifunctionctx;
    363:   return(0);
    364: }

    366: /*@C
    367:    DMTSSetI2Function - set TS implicit function evaluation function for 2nd order systems

    369:    Not Collective

    371:    Input Arguments:
    372: +  dm - DM to be used with TS
    373: .  fun - function evaluation function, see TSSetI2Function() for calling sequence
    374: -  ctx - context for residual evaluation

    376:    Level: advanced

    378:    Note:
    379:    TSSetI2Function() is normally used, but it calls this function internally because the user context is actually
    380:    associated with the DM.

    382: .seealso: TSSetI2Function()
    383: @*/
    384: PetscErrorCode DMTSSetI2Function(DM dm,TSI2Function fun,void *ctx)
    385: {
    386:   DMTS           tsdm;

    391:   DMGetDMTSWrite(dm,&tsdm);
    392:   if (fun) tsdm->ops->i2function = fun;
    393:   if (ctx) tsdm->i2functionctx   = ctx;
    394:   return(0);
    395: }

    397: /*@C
    398:    DMTSGetI2Function - get TS implicit residual evaluation function for 2nd order systems

    400:    Not Collective

    402:    Input Argument:
    403: .  dm - DM to be used with TS

    405:    Output Arguments:
    406: +  fun - function evaluation function, see TSSetI2Function() for calling sequence
    407: -  ctx - context for residual evaluation

    409:    Level: advanced

    411:    Note:
    412:    TSGetI2Function() is normally used, but it calls this function internally because the user context is actually
    413:    associated with the DM.

    415: .seealso: DMTSSetI2Function(),TSGetI2Function()
    416: @*/
    417: PetscErrorCode DMTSGetI2Function(DM dm,TSI2Function *fun,void **ctx)
    418: {
    419:   DMTS           tsdm;

    424:   DMGetDMTS(dm,&tsdm);
    425:   if (fun) *fun = tsdm->ops->i2function;
    426:   if (ctx) *ctx = tsdm->i2functionctx;
    427:   return(0);
    428: }

    430: /*@C
    431:    DMTSSetI2Jacobian - set TS implicit Jacobian evaluation function for 2nd order systems

    433:    Not Collective

    435:    Input Arguments:
    436: +  dm - DM to be used with TS
    437: .  fun - Jacobian evaluation function, see TSSetI2Jacobian() for calling sequence
    438: -  ctx - context for Jacobian evaluation

    440:    Level: advanced

    442:    Note:
    443:    TSSetI2Jacobian() is normally used, but it calls this function internally because the user context is actually
    444:    associated with the DM.

    446: .seealso: TSSetI2Jacobian()
    447: @*/
    448: PetscErrorCode DMTSSetI2Jacobian(DM dm,TSI2Jacobian jac,void *ctx)
    449: {
    450:   DMTS           tsdm;

    455:   DMGetDMTSWrite(dm,&tsdm);
    456:   if (jac) tsdm->ops->i2jacobian = jac;
    457:   if (ctx) tsdm->i2jacobianctx   = ctx;
    458:   return(0);
    459: }

    461: /*@C
    462:    DMTSGetI2Jacobian - get TS implicit Jacobian evaluation function for 2nd order systems

    464:    Not Collective

    466:    Input Argument:
    467: .  dm - DM to be used with TS

    469:    Output Arguments:
    470: +  jac - Jacobian evaluation function, see TSSetI2Jacobian() for calling sequence
    471: -  ctx - context for Jacobian evaluation

    473:    Level: advanced

    475:    Note:
    476:    TSGetI2Jacobian() is normally used, but it calls this function internally because the user context is actually
    477:    associated with the DM.

    479: .seealso: DMTSSetI2Jacobian(),TSGetI2Jacobian()
    480: @*/
    481: PetscErrorCode DMTSGetI2Jacobian(DM dm,TSI2Jacobian *jac,void **ctx)
    482: {
    483:   DMTS           tsdm;

    488:   DMGetDMTS(dm,&tsdm);
    489:   if (jac) *jac = tsdm->ops->i2jacobian;
    490:   if (ctx) *ctx = tsdm->i2jacobianctx;
    491:   return(0);
    492: }

    494: /*@C
    495:    DMTSSetRHSFunction - set TS explicit residual evaluation function

    497:    Not Collective

    499:    Input Arguments:
    500: +  dm - DM to be used with TS
    501: .  func - RHS function evaluation function, see TSSetRHSFunction() for calling sequence
    502: -  ctx - context for residual evaluation

    504:    Level: advanced

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

    511: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
    512: @*/
    513: PetscErrorCode DMTSSetRHSFunction(DM dm,TSRHSFunction func,void *ctx)
    514: {
    516:   DMTS           tsdm;

    520:   DMGetDMTSWrite(dm,&tsdm);
    521:   if (func) tsdm->ops->rhsfunction = func;
    522:   if (ctx)  tsdm->rhsfunctionctx = ctx;
    523:   return(0);
    524: }

    526: /*@C
    527:    DMTSGetSolutionFunction - gets the TS solution evaluation function

    529:    Not Collective

    531:    Input Arguments:
    532: .  dm - DM to be used with TS

    534:    Output Parameters:
    535: +  func - solution function evaluation function, see TSSetSolution() for calling sequence
    536: -  ctx - context for solution evaluation

    538:    Level: advanced

    540: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), DMTSSetSolutionFunction()
    541: @*/
    542: PetscErrorCode DMTSGetSolutionFunction(DM dm,TSSolutionFunction *func,void **ctx)
    543: {
    545:   DMTS           tsdm;

    549:   DMGetDMTS(dm,&tsdm);
    550:   if (func) *func = tsdm->ops->solution;
    551:   if (ctx)  *ctx  = tsdm->solutionctx;
    552:   return(0);
    553: }

    555: /*@C
    556:    DMTSSetSolutionFunction - set TS solution evaluation function

    558:    Not Collective

    560:    Input Arguments:
    561: +  dm - DM to be used with TS
    562: .  func - solution function evaluation function, see TSSetSolution() for calling sequence
    563: -  ctx - context for solution evaluation

    565:    Level: advanced

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

    572: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), DMTSGetSolutionFunction()
    573: @*/
    574: PetscErrorCode DMTSSetSolutionFunction(DM dm,TSSolutionFunction func,void *ctx)
    575: {
    577:   DMTS           tsdm;

    581:   DMGetDMTSWrite(dm,&tsdm);
    582:   if (func) tsdm->ops->solution = func;
    583:   if (ctx)  tsdm->solutionctx   = ctx;
    584:   return(0);
    585: }

    587: /*@C
    588:    DMTSSetForcingFunction - set TS forcing function evaluation function

    590:    Not Collective

    592:    Input Arguments:
    593: +  dm - DM to be used with TS
    594: .  f - forcing function evaluation function; see TSForcingFunction
    595: -  ctx - context for solution evaluation

    597:    Level: advanced

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

    604: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), TSSetForcingFunction(), DMTSGetForcingFunction()
    605: @*/
    606: PetscErrorCode DMTSSetForcingFunction(DM dm,TSForcingFunction f,void *ctx)
    607: {
    609:   DMTS           tsdm;

    613:   DMGetDMTSWrite(dm,&tsdm);
    614:   if (f)    tsdm->ops->forcing = f;
    615:   if (ctx)  tsdm->forcingctx   = ctx;
    616:   return(0);
    617: }

    620: /*@C
    621:    DMTSGetForcingFunction - get TS forcing function evaluation function

    623:    Not Collective

    625:    Input Argument:
    626: .   dm - DM to be used with TS

    628:    Output Arguments:
    629: +  f - forcing function evaluation function; see TSForcingFunction for details
    630: -  ctx - context for solution evaluation

    632:    Level: advanced

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

    639: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), TSSetForcingFunction(), DMTSGetForcingFunction()
    640: @*/
    641: PetscErrorCode DMTSGetForcingFunction(DM dm,TSForcingFunction *f,void **ctx)
    642: {
    644:   DMTS           tsdm;

    648:   DMGetDMTSWrite(dm,&tsdm);
    649:   if (f)   *f   = tsdm->ops->forcing;
    650:   if (ctx) *ctx = tsdm->forcingctx;
    651:   return(0);
    652: }

    654: /*@C
    655:    DMTSGetRHSFunction - get TS explicit residual evaluation function

    657:    Not Collective

    659:    Input Argument:
    660: .  dm - DM to be used with TS

    662:    Output Arguments:
    663: +  func - residual evaluation function, see TSSetRHSFunction() for calling sequence
    664: -  ctx - context for residual evaluation

    666:    Level: advanced

    668:    Note:
    669:    TSGetFunction() is normally used, but it calls this function internally because the user context is actually
    670:    associated with the DM.

    672: .seealso: DMTSSetContext(), DMTSSetFunction(), TSSetFunction()
    673: @*/
    674: PetscErrorCode DMTSGetRHSFunction(DM dm,TSRHSFunction *func,void **ctx)
    675: {
    677:   DMTS           tsdm;

    681:   DMGetDMTS(dm,&tsdm);
    682:   if (func) *func = tsdm->ops->rhsfunction;
    683:   if (ctx)  *ctx = tsdm->rhsfunctionctx;
    684:   return(0);
    685: }

    687: /*@C
    688:    DMTSSetIJacobian - set TS Jacobian evaluation function

    690:    Not Collective

    692:    Input Argument:
    693: +  dm - DM to be used with TS
    694: .  func - Jacobian evaluation function, see TSSetIJacobian() for calling sequence
    695: -  ctx - context for residual evaluation

    697:    Level: advanced

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

    704: .seealso: DMTSSetContext(), TSSetFunction(), DMTSGetJacobian(), TSSetJacobian()
    705: @*/
    706: PetscErrorCode DMTSSetIJacobian(DM dm,TSIJacobian func,void *ctx)
    707: {
    709:   DMTS           sdm;

    713:   DMGetDMTSWrite(dm,&sdm);
    714:   if (func) sdm->ops->ijacobian = func;
    715:   if (ctx)  sdm->ijacobianctx   = ctx;
    716:   return(0);
    717: }

    719: /*@C
    720:    DMTSGetIJacobian - get TS Jacobian evaluation function

    722:    Not Collective

    724:    Input Argument:
    725: .  dm - DM to be used with TS

    727:    Output Arguments:
    728: +  func - Jacobian evaluation function, see TSSetIJacobian() for calling sequence
    729: -  ctx - context for residual evaluation

    731:    Level: advanced

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

    738: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
    739: @*/
    740: PetscErrorCode DMTSGetIJacobian(DM dm,TSIJacobian *func,void **ctx)
    741: {
    743:   DMTS           tsdm;

    747:   DMGetDMTS(dm,&tsdm);
    748:   if (func) *func = tsdm->ops->ijacobian;
    749:   if (ctx)  *ctx = tsdm->ijacobianctx;
    750:   return(0);
    751: }

    754: /*@C
    755:    DMTSSetRHSJacobian - set TS Jacobian evaluation function

    757:    Not Collective

    759:    Input Argument:
    760: +  dm - DM to be used with TS
    761: .  func - Jacobian evaluation function, see TSSetRHSJacobian() for calling sequence
    762: -  ctx - context for residual evaluation

    764:    Level: advanced

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

    771: .seealso: DMTSSetContext(), TSSetFunction(), DMTSGetJacobian(), TSSetJacobian()
    772: @*/
    773: PetscErrorCode DMTSSetRHSJacobian(DM dm,TSRHSJacobian func,void *ctx)
    774: {
    776:   DMTS           tsdm;

    780:   DMGetDMTSWrite(dm,&tsdm);
    781:   if (func) tsdm->ops->rhsjacobian = func;
    782:   if (ctx)  tsdm->rhsjacobianctx = ctx;
    783:   return(0);
    784: }

    786: /*@C
    787:    DMTSGetRHSJacobian - get TS Jacobian evaluation function

    789:    Not Collective

    791:    Input Argument:
    792: .  dm - DM to be used with TS

    794:    Output Arguments:
    795: +  func - Jacobian evaluation function, see TSSetRHSJacobian() for calling sequence
    796: -  ctx - context for residual evaluation

    798:    Level: advanced

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

    805: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
    806: @*/
    807: PetscErrorCode DMTSGetRHSJacobian(DM dm,TSRHSJacobian *func,void **ctx)
    808: {
    810:   DMTS           tsdm;

    814:   DMGetDMTS(dm,&tsdm);
    815:   if (func) *func = tsdm->ops->rhsjacobian;
    816:   if (ctx)  *ctx = tsdm->rhsjacobianctx;
    817:   return(0);
    818: }

    820: /*@C
    821:    DMTSSetIFunctionSerialize - sets functions used to view and load a IFunction context

    823:    Not Collective

    825:    Input Arguments:
    826: +  dm - DM to be used with TS
    827: .  view - viewer function
    828: -  load - loading function

    830:    Level: advanced

    832: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
    833: @*/
    834: PetscErrorCode DMTSSetIFunctionSerialize(DM dm,PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*load)(void**,PetscViewer))
    835: {
    837:   DMTS           tsdm;

    841:   DMGetDMTSWrite(dm,&tsdm);
    842:   tsdm->ops->ifunctionview = view;
    843:   tsdm->ops->ifunctionload = load;
    844:   return(0);
    845: }

    847: /*@C
    848:    DMTSSetIJacobianSerialize - sets functions used to view and load a IJacobian context

    850:    Not Collective

    852:    Input Arguments:
    853: +  dm - DM to be used with TS
    854: .  view - viewer function
    855: -  load - loading function

    857:    Level: advanced

    859: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
    860: @*/
    861: PetscErrorCode DMTSSetIJacobianSerialize(DM dm,PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*load)(void**,PetscViewer))
    862: {
    864:   DMTS           tsdm;

    868:   DMGetDMTSWrite(dm,&tsdm);
    869:   tsdm->ops->ijacobianview = view;
    870:   tsdm->ops->ijacobianload = load;
    871:   return(0);
    872: }