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: }