Actual source code: dmts.c

petsc-3.6.1 2015-08-06
Report Typos and Errors
  1: #include <petsc/private/tsimpl.h>     /*I "petscts.h" I*/
  2: #include <petsc/private/dmimpl.h>

  6: static PetscErrorCode DMTSDestroy(DMTS *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 DMTSLoad(DMTS kdm,PetscViewer viewer)
 22: {

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

 43: PetscErrorCode DMTSView(DMTS kdm,PetscViewer viewer)
 44: {
 46:   PetscBool      isascii,isbinary;

 49:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
 50:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
 51:   if (isascii) {
 52: #if defined(PETSC_SERIALIZE_FUNCTIONS)
 53:     const char *fname;

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

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

108: static PetscErrorCode DMTSCreate(MPI_Comm comm,DMTS *kdm)
109: {

113:   TSInitializePackage();
114:   PetscHeaderCreate(*kdm, DMTS_CLASSID, "DMTS", "DMTS", "DMTS", comm, DMTSDestroy, DMTSView);
115:   return(0);
116: }

120: /* Attaches the DMTS to the coarse level.
121:  * Under what conditions should we copy versus duplicate?
122:  */
123: static PetscErrorCode DMCoarsenHook_DMTS(DM dm,DM dmc,void *ctx)
124: {

128:   DMCopyDMTS(dm,dmc);
129:   return(0);
130: }

134: /* This could restrict auxiliary information to the coarse level.
135:  */
136: static PetscErrorCode DMRestrictHook_DMTS(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx)
137: {

140:   return(0);
141: }

145: static PetscErrorCode DMSubDomainHook_DMTS(DM dm,DM subdm,void *ctx)
146: {

150:   DMCopyDMTS(dm,subdm);
151:   return(0);
152: }

156: /* This could restrict auxiliary information to the coarse level.
157:  */
158: static PetscErrorCode DMSubDomainRestrictHook_DMTS(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
159: {
161:   return(0);
162: }

166: /*@C
167:    DMTSCopy - copies the information in a DMTS to another DMTS

169:    Not Collective

171:    Input Argument:
172: +  kdm - Original DMTS
173: -  nkdm - DMTS to receive the data, should have been created with DMTSCreate()

175:    Level: developer

177: .seealso: DMTSCreate(), DMTSDestroy()
178: @*/
179: PetscErrorCode DMTSCopy(DMTS kdm,DMTS nkdm)
180: {

186:   nkdm->ops->rhsfunction = kdm->ops->rhsfunction;
187:   nkdm->ops->rhsjacobian = kdm->ops->rhsjacobian;
188:   nkdm->ops->ifunction   = kdm->ops->ifunction;
189:   nkdm->ops->ijacobian   = kdm->ops->ijacobian;
190:   nkdm->ops->solution    = kdm->ops->solution;
191:   nkdm->ops->destroy     = kdm->ops->destroy;
192:   nkdm->ops->duplicate   = kdm->ops->duplicate;

194:   nkdm->rhsfunctionctx = kdm->rhsfunctionctx;
195:   nkdm->rhsjacobianctx = kdm->rhsjacobianctx;
196:   nkdm->ifunctionctx   = kdm->ifunctionctx;
197:   nkdm->ijacobianctx   = kdm->ijacobianctx;
198:   nkdm->solutionctx    = kdm->solutionctx;

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

202:   /*
203:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
204:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
205:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
206:   */

208:   /* implementation specific copy hooks */
209:   if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
210:   return(0);
211: }

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

218:    Not Collective

220:    Input Argument:
221: .  dm - DM to be used with TS

223:    Output Argument:
224: .  tsdm - private DMTS context

226:    Level: developer

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

231: .seealso: DMGetDMTSWrite()
232: @*/
233: PetscErrorCode DMGetDMTS(DM dm,DMTS *tsdm)
234: {

239:   *tsdm = (DMTS) dm->dmts;
240:   if (!*tsdm) {
241:     PetscInfo(dm,"Creating new DMTS\n");
242:     DMTSCreate(PetscObjectComm((PetscObject)dm),tsdm);
243:     dm->dmts = (PetscObject) *tsdm;
244:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMTS,DMRestrictHook_DMTS,NULL);
245:     DMSubDomainHookAdd(dm,DMSubDomainHook_DMTS,DMSubDomainRestrictHook_DMTS,NULL);
246:   }
247:   return(0);
248: }

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

255:    Not Collective

257:    Input Argument:
258: .  dm - DM to be used with TS

260:    Output Argument:
261: .  tsdm - private DMTS context

263:    Level: developer

265: .seealso: DMGetDMTS()
266: @*/
267: PetscErrorCode DMGetDMTSWrite(DM dm,DMTS *tsdm)
268: {
270:   DMTS           sdm;

274:   DMGetDMTS(dm,&sdm);
275:   if (!sdm->originaldm) sdm->originaldm = dm;
276:   if (sdm->originaldm != dm) {  /* Copy on write */
277:     DMTS oldsdm = sdm;
278:     PetscInfo(dm,"Copying DMTS due to write\n");
279:     DMTSCreate(PetscObjectComm((PetscObject)dm),&sdm);
280:     DMTSCopy(oldsdm,sdm);
281:     DMTSDestroy((DMTS*)&dm->dmts);
282:     dm->dmts = (PetscObject) sdm;
283:   }
284:   *tsdm = sdm;
285:   return(0);
286: }

290: /*@C
291:    DMCopyDMTS - copies a DM context to a new DM

293:    Logically Collective

295:    Input Arguments:
296: +  dmsrc - DM to obtain context from
297: -  dmdest - DM to add context to

299:    Level: developer

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

304: .seealso: DMGetDMTS(), TSSetDM()
305: @*/
306: PetscErrorCode DMCopyDMTS(DM dmsrc,DM dmdest)
307: {

313:   DMTSDestroy((DMTS*)&dmdest->dmts);
314:   dmdest->dmts = dmsrc->dmts;
315:   PetscObjectReference(dmdest->dmts);
316:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMTS,DMRestrictHook_DMTS,NULL);
317:   DMSubDomainHookAdd(dmdest,DMSubDomainHook_DMTS,DMSubDomainRestrictHook_DMTS,NULL);
318:   return(0);
319: }

323: /*@C
324:    DMTSSetIFunction - set TS implicit function evaluation function

326:    Not Collective

328:    Input Arguments:
329: +  dm - DM to be used with TS
330: .  func - function evaluation function, see TSSetIFunction() for calling sequence
331: -  ctx - context for residual evaluation

333:    Level: advanced

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

340: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
341: @*/
342: PetscErrorCode DMTSSetIFunction(DM dm,TSIFunction func,void *ctx)
343: {
345:   DMTS           tsdm;

349:   DMGetDMTSWrite(dm,&tsdm);
350:   if (func) tsdm->ops->ifunction = func;
351:   if (ctx)  tsdm->ifunctionctx = ctx;
352:   return(0);
353: }

357: /*@C
358:    DMTSGetIFunction - get TS implicit residual evaluation function

360:    Not Collective

362:    Input Argument:
363: .  dm - DM to be used with TS

365:    Output Arguments:
366: +  func - function evaluation function, see TSSetIFunction() for calling sequence
367: -  ctx - context for residual evaluation

369:    Level: advanced

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

375: .seealso: DMTSSetContext(), DMTSSetFunction(), TSSetFunction()
376: @*/
377: PetscErrorCode DMTSGetIFunction(DM dm,TSIFunction *func,void **ctx)
378: {
380:   DMTS           tsdm;

384:   DMGetDMTS(dm,&tsdm);
385:   if (func) *func = tsdm->ops->ifunction;
386:   if (ctx)  *ctx = tsdm->ifunctionctx;
387:   return(0);
388: }


393: /*@C
394:    DMTSSetRHSFunction - set TS explicit residual evaluation function

396:    Not Collective

398:    Input Arguments:
399: +  dm - DM to be used with TS
400: .  func - RHS function evaluation function, see TSSetRHSFunction() for calling sequence
401: -  ctx - context for residual evaluation

403:    Level: advanced

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

410: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
411: @*/
412: PetscErrorCode DMTSSetRHSFunction(DM dm,TSRHSFunction func,void *ctx)
413: {
415:   DMTS           tsdm;

419:   DMGetDMTSWrite(dm,&tsdm);
420:   if (func) tsdm->ops->rhsfunction = func;
421:   if (ctx)  tsdm->rhsfunctionctx = ctx;
422:   return(0);
423: }

427: /*@C
428:    DMTSGetSolutionFunction - gets the TS solution evaluation function

430:    Not Collective

432:    Input Arguments:
433: .  dm - DM to be used with TS

435:    Output Parameters:
436: +  func - solution function evaluation function, see TSSetSolution() for calling sequence
437: -  ctx - context for solution evaluation

439:    Level: advanced

441: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
442: @*/
443: PetscErrorCode DMTSGetSolutionFunction(DM dm,TSSolutionFunction *func,void **ctx)
444: {
446:   DMTS           tsdm;

450:   DMGetDMTS(dm,&tsdm);
451:   if (func) *func = tsdm->ops->solution;
452:   if (ctx)  *ctx  = tsdm->solutionctx;
453:   return(0);
454: }

458: /*@C
459:    DMTSSetSolutionFunction - set TS solution evaluation function

461:    Not Collective

463:    Input Arguments:
464: +  dm - DM to be used with TS
465: .  func - solution function evaluation function, see TSSetSolution() for calling sequence
466: -  ctx - context for solution evaluation

468:    Level: advanced

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

475: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
476: @*/
477: PetscErrorCode DMTSSetSolutionFunction(DM dm,TSSolutionFunction func,void *ctx)
478: {
480:   DMTS           tsdm;

484:   DMGetDMTSWrite(dm,&tsdm);
485:   if (func) tsdm->ops->solution = func;
486:   if (ctx)  tsdm->solutionctx   = ctx;
487:   return(0);
488: }

492: /*@C
493:    DMTSSetForcingFunction - set TS forcing function evaluation function

495:    Not Collective

497:    Input Arguments:
498: +  dm - DM to be used with TS
499: .  f - forcing function evaluation function; see TSForcingFunction
500: -  ctx - context for solution evaluation

502:    Level: advanced

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

509: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), TSSetForcingFunction(), DMTSGetForcingFunction()
510: @*/
511: PetscErrorCode DMTSSetForcingFunction(DM dm,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx)
512: {
514:   DMTS           tsdm;

518:   DMGetDMTSWrite(dm,&tsdm);
519:   if (f) tsdm->ops->forcing = f;
520:   if (ctx)  tsdm->forcingctx   = ctx;
521:   return(0);
522: }


527: /*@C
528:    DMTSGetForcingFunction - get TS forcing function evaluation function

530:    Not Collective

532:    Input Argument:
533: .   dm - DM to be used with TS

535:    Output Arguments:
536: +  f - forcing function evaluation function; see TSForcingFunction for details
537: -  ctx - context for solution evaluation

539:    Level: advanced

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

546: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), TSSetForcingFunction(), DMTSGetForcingFunction()
547: @*/
548: PetscErrorCode DMTSGetForcingFunction(DM dm,PetscErrorCode (**f)(TS,PetscReal,Vec,void*),void **ctx)
549: {
551:   DMTS           tsdm;

555:   DMGetDMTSWrite(dm,&tsdm);
556:   if (f) *f = tsdm->ops->forcing;
557:   if (ctx) *ctx = tsdm->forcingctx;
558:   return(0);
559: }

563: /*@C
564:    DMTSGetRHSFunction - get TS explicit residual evaluation function

566:    Not Collective

568:    Input Argument:
569: .  dm - DM to be used with TS

571:    Output Arguments:
572: +  func - residual evaluation function, see TSSetRHSFunction() for calling sequence
573: -  ctx - context for residual evaluation

575:    Level: advanced

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

581: .seealso: DMTSSetContext(), DMTSSetFunction(), TSSetFunction()
582: @*/
583: PetscErrorCode DMTSGetRHSFunction(DM dm,TSRHSFunction *func,void **ctx)
584: {
586:   DMTS           tsdm;

590:   DMGetDMTS(dm,&tsdm);
591:   if (func) *func = tsdm->ops->rhsfunction;
592:   if (ctx)  *ctx = tsdm->rhsfunctionctx;
593:   return(0);
594: }

598: /*@C
599:    DMTSSetIJacobian - set TS Jacobian evaluation function

601:    Not Collective

603:    Input Argument:
604: +  dm - DM to be used with TS
605: .  func - Jacobian evaluation function, see TSSetIJacobian() for calling sequence
606: -  ctx - context for residual evaluation

608:    Level: advanced

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

615: .seealso: DMTSSetContext(), TSSetFunction(), DMTSGetJacobian(), TSSetJacobian()
616: @*/
617: PetscErrorCode DMTSSetIJacobian(DM dm,TSIJacobian func,void *ctx)
618: {
620:   DMTS           sdm;

624:   DMGetDMTSWrite(dm,&sdm);
625:   if (func) sdm->ops->ijacobian = func;
626:   if (ctx)  sdm->ijacobianctx   = ctx;
627:   return(0);
628: }

632: /*@C
633:    DMTSGetIJacobian - get TS Jacobian evaluation function

635:    Not Collective

637:    Input Argument:
638: .  dm - DM to be used with TS

640:    Output Arguments:
641: +  func - Jacobian evaluation function, see TSSetIJacobian() for calling sequence
642: -  ctx - context for residual evaluation

644:    Level: advanced

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

651: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
652: @*/
653: PetscErrorCode DMTSGetIJacobian(DM dm,TSIJacobian *func,void **ctx)
654: {
656:   DMTS           tsdm;

660:   DMGetDMTS(dm,&tsdm);
661:   if (func) *func = tsdm->ops->ijacobian;
662:   if (ctx)  *ctx = tsdm->ijacobianctx;
663:   return(0);
664: }


669: /*@C
670:    DMTSSetRHSJacobian - set TS Jacobian evaluation function

672:    Not Collective

674:    Input Argument:
675: +  dm - DM to be used with TS
676: .  func - Jacobian evaluation function, see TSSetRHSJacobian() for calling sequence
677: -  ctx - context for residual evaluation

679:    Level: advanced

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

686: .seealso: DMTSSetContext(), TSSetFunction(), DMTSGetJacobian(), TSSetJacobian()
687: @*/
688: PetscErrorCode DMTSSetRHSJacobian(DM dm,TSRHSJacobian func,void *ctx)
689: {
691:   DMTS           tsdm;

695:   DMGetDMTSWrite(dm,&tsdm);
696:   if (func) tsdm->ops->rhsjacobian = func;
697:   if (ctx)  tsdm->rhsjacobianctx = ctx;
698:   return(0);
699: }

703: /*@C
704:    DMTSGetRHSJacobian - get TS Jacobian evaluation function

706:    Not Collective

708:    Input Argument:
709: .  dm - DM to be used with TS

711:    Output Arguments:
712: +  func - Jacobian evaluation function, see TSSetRHSJacobian() for calling sequence
713: -  ctx - context for residual evaluation

715:    Level: advanced

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

722: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
723: @*/
724: PetscErrorCode DMTSGetRHSJacobian(DM dm,TSRHSJacobian *func,void **ctx)
725: {
727:   DMTS           tsdm;

731:   DMGetDMTS(dm,&tsdm);
732:   if (func) *func = tsdm->ops->rhsjacobian;
733:   if (ctx)  *ctx = tsdm->rhsjacobianctx;
734:   return(0);
735: }

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

742:    Not Collective

744:    Input Arguments:
745: +  dm - DM to be used with TS
746: .  view - viewer function
747: -  load - loading function

749:    Level: advanced

751: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
752: @*/
753: PetscErrorCode DMTSSetIFunctionSerialize(DM dm,PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*load)(void**,PetscViewer))
754: {
756:   DMTS           tsdm;

760:   DMGetDMTSWrite(dm,&tsdm);
761:   tsdm->ops->ifunctionview = view;
762:   tsdm->ops->ifunctionload = load;
763:   return(0);
764: }

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

771:    Not Collective

773:    Input Arguments:
774: +  dm - DM to be used with TS
775: .  view - viewer function
776: -  load - loading function

778:    Level: advanced

780: .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
781: @*/
782: PetscErrorCode DMTSSetIJacobianSerialize(DM dm,PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*load)(void**,PetscViewer))
783: {
785:   DMTS           tsdm;

789:   DMGetDMTSWrite(dm,&tsdm);
790:   tsdm->ops->ijacobianview = view;
791:   tsdm->ops->ijacobianload = load;
792:   return(0);
793: }