Actual source code: dmts.c
1: #include <petsc/private/tsimpl.h>
2: #include <petsc/private/dmimpl.h>
4: static PetscErrorCode DMTSUnsetRHSFunctionContext_DMTS(DMTS tsdm)
5: {
6: PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", NULL);
7: tsdm->rhsfunctionctxcontainer = NULL;
8: return 0;
9: }
11: static PetscErrorCode DMTSUnsetRHSJacobianContext_DMTS(DMTS tsdm)
12: {
13: PetscObjectCompose((PetscObject)tsdm, "rhs jacobian ctx", NULL);
14: tsdm->rhsjacobianctxcontainer = NULL;
15: return 0;
16: }
18: static PetscErrorCode DMTSUnsetIFunctionContext_DMTS(DMTS tsdm)
19: {
20: PetscObjectCompose((PetscObject)tsdm, "ifunction ctx", NULL);
21: tsdm->ifunctionctxcontainer = NULL;
22: return 0;
23: }
25: static PetscErrorCode DMTSUnsetIJacobianContext_DMTS(DMTS tsdm)
26: {
27: PetscObjectCompose((PetscObject)tsdm, "ijacobian ctx", NULL);
28: tsdm->ijacobianctxcontainer = NULL;
29: return 0;
30: }
32: static PetscErrorCode DMTSUnsetI2FunctionContext_DMTS(DMTS tsdm)
33: {
34: PetscObjectCompose((PetscObject)tsdm, "i2function ctx", NULL);
35: tsdm->i2functionctxcontainer = NULL;
36: return 0;
37: }
39: static PetscErrorCode DMTSUnsetI2JacobianContext_DMTS(DMTS tsdm)
40: {
41: PetscObjectCompose((PetscObject)tsdm, "i2jacobian ctx", NULL);
42: tsdm->i2jacobianctxcontainer = NULL;
43: return 0;
44: }
46: static PetscErrorCode DMTSDestroy(DMTS *kdm)
47: {
48: if (!*kdm) return 0;
50: if (--((PetscObject)(*kdm))->refct > 0) {
51: *kdm = NULL;
52: return 0;
53: }
54: DMTSUnsetRHSFunctionContext_DMTS(*kdm);
55: DMTSUnsetRHSJacobianContext_DMTS(*kdm);
56: DMTSUnsetIFunctionContext_DMTS(*kdm);
57: DMTSUnsetIJacobianContext_DMTS(*kdm);
58: DMTSUnsetI2FunctionContext_DMTS(*kdm);
59: DMTSUnsetI2JacobianContext_DMTS(*kdm);
60: PetscTryTypeMethod(*kdm, destroy);
61: PetscHeaderDestroy(kdm);
62: return 0;
63: }
65: PetscErrorCode DMTSLoad(DMTS kdm, PetscViewer viewer)
66: {
67: PetscViewerBinaryRead(viewer, &kdm->ops->ifunction, 1, NULL, PETSC_FUNCTION);
68: PetscViewerBinaryRead(viewer, &kdm->ops->ifunctionview, 1, NULL, PETSC_FUNCTION);
69: PetscViewerBinaryRead(viewer, &kdm->ops->ifunctionload, 1, NULL, PETSC_FUNCTION);
70: if (kdm->ops->ifunctionload) {
71: void *ctx;
73: PetscContainerGetPointer(kdm->ifunctionctxcontainer, &ctx);
74: (*kdm->ops->ifunctionload)(&ctx, viewer);
75: }
76: PetscViewerBinaryRead(viewer, &kdm->ops->ijacobian, 1, NULL, PETSC_FUNCTION);
77: PetscViewerBinaryRead(viewer, &kdm->ops->ijacobianview, 1, NULL, PETSC_FUNCTION);
78: PetscViewerBinaryRead(viewer, &kdm->ops->ijacobianload, 1, NULL, PETSC_FUNCTION);
79: if (kdm->ops->ijacobianload) {
80: void *ctx;
82: PetscContainerGetPointer(kdm->ijacobianctxcontainer, &ctx);
83: (*kdm->ops->ijacobianload)(&ctx, viewer);
84: }
85: return 0;
86: }
88: PetscErrorCode DMTSView(DMTS kdm, PetscViewer viewer)
89: {
90: PetscBool isascii, isbinary;
92: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
93: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary);
94: if (isascii) {
95: #if defined(PETSC_SERIALIZE_FUNCTIONS)
96: const char *fname;
98: PetscFPTFind(kdm->ops->ifunction, &fname);
99: if (fname) PetscViewerASCIIPrintf(viewer, " IFunction used by TS: %s\n", fname);
100: PetscFPTFind(kdm->ops->ijacobian, &fname);
101: if (fname) PetscViewerASCIIPrintf(viewer, " IJacobian function used by TS: %s\n", fname);
102: #endif
103: } else if (isbinary) {
104: struct {
105: TSIFunction ifunction;
106: } funcstruct;
107: struct {
108: PetscErrorCode (*ifunctionview)(void *, PetscViewer);
109: } funcviewstruct;
110: struct {
111: PetscErrorCode (*ifunctionload)(void **, PetscViewer);
112: } funcloadstruct;
113: struct {
114: TSIJacobian ijacobian;
115: } jacstruct;
116: struct {
117: PetscErrorCode (*ijacobianview)(void *, PetscViewer);
118: } jacviewstruct;
119: struct {
120: PetscErrorCode (*ijacobianload)(void **, PetscViewer);
121: } jacloadstruct;
123: funcstruct.ifunction = kdm->ops->ifunction;
124: funcviewstruct.ifunctionview = kdm->ops->ifunctionview;
125: funcloadstruct.ifunctionload = kdm->ops->ifunctionload;
126: PetscViewerBinaryWrite(viewer, &funcstruct, 1, PETSC_FUNCTION);
127: PetscViewerBinaryWrite(viewer, &funcviewstruct, 1, PETSC_FUNCTION);
128: PetscViewerBinaryWrite(viewer, &funcloadstruct, 1, PETSC_FUNCTION);
129: if (kdm->ops->ifunctionview) {
130: void *ctx;
132: PetscContainerGetPointer(kdm->ifunctionctxcontainer, &ctx);
133: (*kdm->ops->ifunctionview)(ctx, viewer);
134: }
135: jacstruct.ijacobian = kdm->ops->ijacobian;
136: jacviewstruct.ijacobianview = kdm->ops->ijacobianview;
137: jacloadstruct.ijacobianload = kdm->ops->ijacobianload;
138: PetscViewerBinaryWrite(viewer, &jacstruct, 1, PETSC_FUNCTION);
139: PetscViewerBinaryWrite(viewer, &jacviewstruct, 1, PETSC_FUNCTION);
140: PetscViewerBinaryWrite(viewer, &jacloadstruct, 1, PETSC_FUNCTION);
141: if (kdm->ops->ijacobianview) {
142: void *ctx;
144: PetscContainerGetPointer(kdm->ijacobianctxcontainer, &ctx);
145: (*kdm->ops->ijacobianview)(ctx, viewer);
146: }
147: }
148: return 0;
149: }
151: static PetscErrorCode DMTSCreate(MPI_Comm comm, DMTS *kdm)
152: {
153: TSInitializePackage();
154: PetscHeaderCreate(*kdm, DMTS_CLASSID, "DMTS", "DMTS", "DMTS", comm, DMTSDestroy, DMTSView);
155: return 0;
156: }
158: /* Attaches the DMTS to the coarse level.
159: * Under what conditions should we copy versus duplicate?
160: */
161: static PetscErrorCode DMCoarsenHook_DMTS(DM dm, DM dmc, void *ctx)
162: {
163: DMCopyDMTS(dm, dmc);
164: return 0;
165: }
167: /* This could restrict auxiliary information to the coarse level.
168: */
169: static PetscErrorCode DMRestrictHook_DMTS(DM dm, Mat Restrict, Vec rscale, Mat Inject, DM dmc, void *ctx)
170: {
171: return 0;
172: }
174: static PetscErrorCode DMSubDomainHook_DMTS(DM dm, DM subdm, void *ctx)
175: {
176: DMCopyDMTS(dm, subdm);
177: return 0;
178: }
180: /* This could restrict auxiliary information to the coarse level.
181: */
182: static PetscErrorCode DMSubDomainRestrictHook_DMTS(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx)
183: {
184: return 0;
185: }
187: /*@C
188: DMTSCopy - copies the information in a `DMTS` to another `DMTS`
190: Not Collective
192: Input Parameters:
193: + kdm - Original `DMTS`
194: - nkdm - `DMTS` to receive the data, should have been created with `DMTSCreate()`
196: Level: developer
198: .seealso: [](chapter_ts), `DMTSCreate()`, `DMTSDestroy()`
199: @*/
200: PetscErrorCode DMTSCopy(DMTS kdm, DMTS nkdm)
201: {
204: nkdm->ops->rhsfunction = kdm->ops->rhsfunction;
205: nkdm->ops->rhsjacobian = kdm->ops->rhsjacobian;
206: nkdm->ops->ifunction = kdm->ops->ifunction;
207: nkdm->ops->ijacobian = kdm->ops->ijacobian;
208: nkdm->ops->i2function = kdm->ops->i2function;
209: nkdm->ops->i2jacobian = kdm->ops->i2jacobian;
210: nkdm->ops->solution = kdm->ops->solution;
211: nkdm->ops->destroy = kdm->ops->destroy;
212: nkdm->ops->duplicate = kdm->ops->duplicate;
214: nkdm->solutionctx = kdm->solutionctx;
215: nkdm->rhsfunctionctxcontainer = kdm->rhsfunctionctxcontainer;
216: nkdm->rhsjacobianctxcontainer = kdm->rhsjacobianctxcontainer;
217: nkdm->ifunctionctxcontainer = kdm->ifunctionctxcontainer;
218: nkdm->ijacobianctxcontainer = kdm->ijacobianctxcontainer;
219: nkdm->i2functionctxcontainer = kdm->i2functionctxcontainer;
220: nkdm->i2jacobianctxcontainer = kdm->i2jacobianctxcontainer;
221: if (nkdm->rhsfunctionctxcontainer) PetscObjectCompose((PetscObject)nkdm, "rhs function ctx", (PetscObject)nkdm->rhsfunctionctxcontainer);
222: if (nkdm->rhsjacobianctxcontainer) PetscObjectCompose((PetscObject)nkdm, "rhs jacobian ctx", (PetscObject)nkdm->rhsjacobianctxcontainer);
223: if (nkdm->ifunctionctxcontainer) PetscObjectCompose((PetscObject)nkdm, "ifunction ctx", (PetscObject)nkdm->ifunctionctxcontainer);
224: if (nkdm->ijacobianctxcontainer) PetscObjectCompose((PetscObject)nkdm, "ijacobian ctx", (PetscObject)nkdm->ijacobianctxcontainer);
225: if (nkdm->i2functionctxcontainer) PetscObjectCompose((PetscObject)nkdm, "i2function ctx", (PetscObject)nkdm->i2functionctxcontainer);
226: if (nkdm->i2jacobianctxcontainer) PetscObjectCompose((PetscObject)nkdm, "i2jacobian ctx", (PetscObject)nkdm->i2jacobianctxcontainer);
228: nkdm->data = kdm->data;
230: /*
231: nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
232: nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
233: nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
234: */
236: /* implementation specific copy hooks */
237: PetscTryTypeMethod(kdm, duplicate, nkdm);
238: return 0;
239: }
241: /*@C
242: DMGetDMTS - get read-only private `DMTS` context from a `DM`
244: Not Collective
246: Input Parameter:
247: . dm - `DM` to be used with `TS`
249: Output Parameter:
250: . tsdm - private `DMTS` context
252: Level: developer
254: Notes:
255: Use `DMGetDMTSWrite()` if write access is needed. The `DMTSSetXXX()` API should be used wherever possible.
257: .seealso: [](chapter_ts), `DMTS`, `DMGetDMTSWrite()`
258: @*/
259: PetscErrorCode DMGetDMTS(DM dm, DMTS *tsdm)
260: {
262: *tsdm = (DMTS)dm->dmts;
263: if (!*tsdm) {
264: PetscInfo(dm, "Creating new DMTS\n");
265: DMTSCreate(PetscObjectComm((PetscObject)dm), tsdm);
266: dm->dmts = (PetscObject)*tsdm;
267: (*tsdm)->originaldm = dm;
268: DMCoarsenHookAdd(dm, DMCoarsenHook_DMTS, DMRestrictHook_DMTS, NULL);
269: DMSubDomainHookAdd(dm, DMSubDomainHook_DMTS, DMSubDomainRestrictHook_DMTS, NULL);
270: }
271: return 0;
272: }
274: /*@C
275: DMGetDMTSWrite - get write access to private `DMTS` context from a `DM`
277: Not Collective
279: Input Parameter:
280: . dm - `DM` to be used with `TS`
282: Output Parameter:
283: . tsdm - private `DMTS` context
285: Level: developer
287: .seealso: [](chapter_ts), `DMTS`, `DMGetDMTS()`
288: @*/
289: PetscErrorCode DMGetDMTSWrite(DM dm, DMTS *tsdm)
290: {
291: DMTS sdm;
294: DMGetDMTS(dm, &sdm);
296: if (sdm->originaldm != dm) { /* Copy on write */
297: DMTS oldsdm = sdm;
298: PetscInfo(dm, "Copying DMTS due to write\n");
299: DMTSCreate(PetscObjectComm((PetscObject)dm), &sdm);
300: DMTSCopy(oldsdm, sdm);
301: DMTSDestroy((DMTS *)&dm->dmts);
302: dm->dmts = (PetscObject)sdm;
303: sdm->originaldm = dm;
304: }
305: *tsdm = sdm;
306: return 0;
307: }
309: /*@C
310: DMCopyDMTS - copies a `DM` context to a new `DM`
312: Logically Collective
314: Input Parameters:
315: + dmsrc - `DM` to obtain context from
316: - dmdest - `DM` to add context to
318: Level: developer
320: Note:
321: The context is copied by reference. This function does not ensure that a context exists.
323: .seealso: [](chapter_ts), `DMTS`, `DMGetDMTS()`, `TSSetDM()`
324: @*/
325: PetscErrorCode DMCopyDMTS(DM dmsrc, DM dmdest)
326: {
329: DMTSDestroy((DMTS *)&dmdest->dmts);
330: dmdest->dmts = dmsrc->dmts;
331: PetscObjectReference(dmdest->dmts);
332: DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMTS, DMRestrictHook_DMTS, NULL);
333: DMSubDomainHookAdd(dmdest, DMSubDomainHook_DMTS, DMSubDomainRestrictHook_DMTS, NULL);
334: return 0;
335: }
337: /*@C
338: DMTSSetIFunction - set `TS` implicit function evaluation function
340: Not Collective
342: Input Parameters:
343: + dm - `DM` to be used with `TS`
344: . func - function evaluating f(t,u,u_t)
345: - ctx - context for residual evaluation
347: Calling sequence of func:
348: $ PetscErrorCode func(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx);
350: + t - time at step/stage being solved
351: . u - state vector
352: . u_t - time derivative of state vector
353: . F - function vector
354: - ctx - [optional] user-defined context for matrix evaluation routine
356: Level: advanced
358: Note:
359: `TSSetFunction()` is normally used, but it calls this function internally because the user context is actually
360: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
361: not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
363: .seealso: [](chapter_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetIFunction()`, `DMTSSetJacobian()`
364: @*/
365: PetscErrorCode DMTSSetIFunction(DM dm, TSIFunction func, void *ctx)
366: {
367: DMTS tsdm;
370: DMGetDMTSWrite(dm, &tsdm);
371: if (func) tsdm->ops->ifunction = func;
372: if (ctx) {
373: PetscContainer ctxcontainer;
374: PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer);
375: PetscContainerSetPointer(ctxcontainer, ctx);
376: PetscObjectCompose((PetscObject)tsdm, "ifunction ctx", (PetscObject)ctxcontainer);
377: tsdm->ifunctionctxcontainer = ctxcontainer;
378: PetscContainerDestroy(&ctxcontainer);
379: }
380: return 0;
381: }
383: /*@C
384: DMTSSetIFunctionContextDestroy - set `TS` implicit evaluation context destroy function
386: Not Collective
388: Input Parameters:
389: + dm - `DM` to be used with `TS`
390: - f - implicit evaluation context destroy function
392: Level: advanced
394: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetIFunction()`, `TSSetIFunction()`
395: @*/
396: PetscErrorCode DMTSSetIFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
397: {
398: DMTS tsdm;
401: DMGetDMTSWrite(dm, &tsdm);
402: if (tsdm->ifunctionctxcontainer) PetscContainerSetUserDestroy(tsdm->ifunctionctxcontainer, f);
403: return 0;
404: }
406: PetscErrorCode DMTSUnsetIFunctionContext_Internal(DM dm)
407: {
408: DMTS tsdm;
411: DMGetDMTSWrite(dm, &tsdm);
412: DMTSUnsetIFunctionContext_DMTS(tsdm);
413: return 0;
414: }
416: /*@C
417: DMTSGetIFunction - get `TS` implicit residual evaluation function
419: Not Collective
421: Input Parameter:
422: . dm - `DM` to be used with `TS`
424: Output Parameters:
425: + func - function evaluation function, see `TSSetIFunction()` for calling sequence
426: - ctx - context for residual evaluation
428: Level: advanced
430: Note:
431: `TSGetFunction()` is normally used, but it calls this function internally because the user context is actually
432: associated with the `DM`.
434: .seealso: [](chapter_ts), `TS`, `DM`, `DMTSSetContext()`, `DMTSSetFunction()`, `TSSetFunction()`
435: @*/
436: PetscErrorCode DMTSGetIFunction(DM dm, TSIFunction *func, void **ctx)
437: {
438: DMTS tsdm;
441: DMGetDMTS(dm, &tsdm);
442: if (func) *func = tsdm->ops->ifunction;
443: if (ctx) {
444: if (tsdm->ifunctionctxcontainer) PetscContainerGetPointer(tsdm->ifunctionctxcontainer, ctx);
445: else *ctx = NULL;
446: }
447: return 0;
448: }
450: /*@C
451: DMTSSetI2Function - set `TS` implicit function evaluation function for 2nd order systems
453: Not Collective
455: Input Parameters:
456: + dm - `DM` to be used with `TS`
457: . fun - function evaluation routine
458: - ctx - context for residual evaluation
460: Calling sequence of fun:
461: $ PetscErrorCode fun(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,Vec F,ctx);
463: + t - time at step/stage being solved
464: . U - state vector
465: . U_t - time derivative of state vector
466: . U_tt - second time derivative of state vector
467: . F - function vector
468: - ctx - [optional] user-defined context for matrix evaluation routine (may be NULL)
470: Level: advanced
472: Note:
473: `TSSetI2Function()` is normally used, but it calls this function internally because the user context is actually
474: associated with the `DM`.
476: .seealso: [](chapter_ts), `DM`, `TS`, `TSSetI2Function()`
477: @*/
478: PetscErrorCode DMTSSetI2Function(DM dm, TSI2Function fun, void *ctx)
479: {
480: DMTS tsdm;
483: DMGetDMTSWrite(dm, &tsdm);
484: if (fun) tsdm->ops->i2function = fun;
485: if (ctx) {
486: PetscContainer ctxcontainer;
487: PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer);
488: PetscContainerSetPointer(ctxcontainer, ctx);
489: PetscObjectCompose((PetscObject)tsdm, "i2function ctx", (PetscObject)ctxcontainer);
490: tsdm->i2functionctxcontainer = ctxcontainer;
491: PetscContainerDestroy(&ctxcontainer);
492: }
493: return 0;
494: }
496: /*@C
497: DMTSSetI2FunctionContextDestroy - set `TS` implicit evaluation for 2nd order systems context destroy
499: Not Collective
501: Input Parameters:
502: + dm - `DM` to be used with `TS`
503: - f - implicit evaluation context destroy function
505: Level: advanced
507: Note:
508: `TSSetI2FunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
509: associated with the `DM`.
511: .seealso: [](chapter_ts), `TSSetI2FunctionContextDestroy()`, `DMTSSetI2Function()`, `TSSetI2Function()`
512: @*/
513: PetscErrorCode DMTSSetI2FunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
514: {
515: DMTS tsdm;
518: DMGetDMTSWrite(dm, &tsdm);
519: if (tsdm->i2functionctxcontainer) PetscContainerSetUserDestroy(tsdm->i2functionctxcontainer, f);
520: return 0;
521: }
523: PetscErrorCode DMTSUnsetI2FunctionContext_Internal(DM dm)
524: {
525: DMTS tsdm;
528: DMGetDMTSWrite(dm, &tsdm);
529: DMTSUnsetI2FunctionContext_DMTS(tsdm);
530: return 0;
531: }
533: /*@C
534: DMTSGetI2Function - get `TS` implicit residual evaluation function for 2nd order systems
536: Not Collective
538: Input Parameter:
539: . dm - `DM` to be used with `TS`
541: Output Parameters:
542: + fun - function evaluation function, see `TSSetI2Function()` for calling sequence
543: - ctx - context for residual evaluation
545: Level: advanced
547: Note:
548: `TSGetI2Function()` is normally used, but it calls this function internally because the user context is actually
549: associated with the `DM`.
551: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetI2Function()`, `TSGetI2Function()`
552: @*/
553: PetscErrorCode DMTSGetI2Function(DM dm, TSI2Function *fun, void **ctx)
554: {
555: DMTS tsdm;
558: DMGetDMTS(dm, &tsdm);
559: if (fun) *fun = tsdm->ops->i2function;
560: if (ctx) {
561: if (tsdm->i2functionctxcontainer) PetscContainerGetPointer(tsdm->i2functionctxcontainer, ctx);
562: else *ctx = NULL;
563: }
564: return 0;
565: }
567: /*@C
568: DMTSSetI2Jacobian - set `TS` implicit Jacobian evaluation function for 2nd order systems
570: Not Collective
572: Input Parameters:
573: + dm - `DM` to be used with `TS`
574: . fun - Jacobian evaluation routine
575: - ctx - context for Jacobian evaluation
577: Calling sequence of jac:
578: $ PetscErrorCode jac(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,PetscReal v,PetscReal a,Mat J,Mat P,void *ctx);
580: + t - time at step/stage being solved
581: . U - state vector
582: . U_t - time derivative of state vector
583: . U_tt - second time derivative of state vector
584: . v - shift for U_t
585: . a - shift for U_tt
586: . J - Jacobian of G(U) = F(t,U,W+v*U,W'+a*U), equivalent to dF/dU + v*dF/dU_t + a*dF/dU_tt
587: . P - preconditioning matrix for J, may be same as J
588: - ctx - [optional] user-defined context for matrix evaluation routine
590: Level: advanced
592: Note:
593: `TSSetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
594: associated with the `DM`.
596: .seealso: [](chapter_ts), `DM`, `TS`, `TSSetI2Jacobian()`
597: @*/
598: PetscErrorCode DMTSSetI2Jacobian(DM dm, TSI2Jacobian jac, void *ctx)
599: {
600: DMTS tsdm;
603: DMGetDMTSWrite(dm, &tsdm);
604: if (jac) tsdm->ops->i2jacobian = jac;
605: if (ctx) {
606: PetscContainer ctxcontainer;
607: PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer);
608: PetscContainerSetPointer(ctxcontainer, ctx);
609: PetscObjectCompose((PetscObject)tsdm, "i2jacobian ctx", (PetscObject)ctxcontainer);
610: tsdm->i2jacobianctxcontainer = ctxcontainer;
611: PetscContainerDestroy(&ctxcontainer);
612: }
613: return 0;
614: }
616: /*@C
617: DMTSSetI2JacobianContextDestroy - set `TS` implicit Jacobian evaluation for 2nd order systems context destroy function
619: Not Collective
621: Input Parameters:
622: + dm - `DM` to be used with `TS`
623: - f - implicit Jacobian evaluation context destroy function
625: Level: advanced
627: .seealso: [](chapter_ts), `DM`, `TS`, `TSSetI2JacobianContextDestroy()`, `DMTSSetI2Jacobian()`, `TSSetI2Jacobian()`
628: @*/
629: PetscErrorCode DMTSSetI2JacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
630: {
631: DMTS tsdm;
634: DMGetDMTSWrite(dm, &tsdm);
635: if (tsdm->i2jacobianctxcontainer) PetscContainerSetUserDestroy(tsdm->i2jacobianctxcontainer, f);
636: return 0;
637: }
639: PetscErrorCode DMTSUnsetI2JacobianContext_Internal(DM dm)
640: {
641: DMTS tsdm;
644: DMGetDMTSWrite(dm, &tsdm);
645: DMTSUnsetI2JacobianContext_DMTS(tsdm);
646: return 0;
647: }
649: /*@C
650: DMTSGetI2Jacobian - get `TS` implicit Jacobian evaluation function for 2nd order systems
652: Not Collective
654: Input Parameter:
655: . dm - `DM` to be used with `TS`
657: Output Parameters:
658: + jac - Jacobian evaluation function, see `TSSetI2Jacobian()` for calling sequence
659: - ctx - context for Jacobian evaluation
661: Level: advanced
663: Note:
664: `TSGetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
665: associated with the `DM`.
667: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetI2Jacobian()`, `TSGetI2Jacobian()`
668: @*/
669: PetscErrorCode DMTSGetI2Jacobian(DM dm, TSI2Jacobian *jac, void **ctx)
670: {
671: DMTS tsdm;
674: DMGetDMTS(dm, &tsdm);
675: if (jac) *jac = tsdm->ops->i2jacobian;
676: if (ctx) {
677: if (tsdm->i2jacobianctxcontainer) PetscContainerGetPointer(tsdm->i2jacobianctxcontainer, ctx);
678: else *ctx = NULL;
679: }
680: return 0;
681: }
683: /*@C
684: DMTSSetRHSFunction - set `TS` explicit residual evaluation function
686: Not Collective
688: Input Parameters:
689: + dm - `DM` to be used with `TS`
690: . func - RHS function evaluation routine
691: - ctx - context for residual evaluation
693: Calling sequence of func:
694: $ PetscErrorCode func(TS ts,PetscReal t,Vec u,Vec F,void *ctx);
696: + ts - timestep context
697: . t - current timestep
698: . u - input vector
699: . F - function vector
700: - ctx - [optional] user-defined function context
702: Level: advanced
704: Note:
705: `TSSetRHSFunction()` is normally used, but it calls this function internally because the user context is actually
706: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
707: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
709: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSSetJacobian()`
710: @*/
711: PetscErrorCode DMTSSetRHSFunction(DM dm, TSRHSFunction func, void *ctx)
712: {
713: DMTS tsdm;
716: DMGetDMTSWrite(dm, &tsdm);
717: if (func) tsdm->ops->rhsfunction = func;
718: if (ctx) {
719: PetscContainer ctxcontainer;
720: PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer);
721: PetscContainerSetPointer(ctxcontainer, ctx);
722: PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", (PetscObject)ctxcontainer);
723: tsdm->rhsfunctionctxcontainer = ctxcontainer;
724: PetscContainerDestroy(&ctxcontainer);
725: }
726: return 0;
727: }
729: /*@C
730: DMTSSetRHSFunctionContextDestroy - set `TS` explicit residual evaluation context destroy function
732: Not Collective
734: Input Parameters:
735: + dm - `DM` to be used with `TS`
736: - f - explicit evaluation context destroy function
738: Level: advanced
740: Note:
741: `TSSetRHSFunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
742: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
743: not.
745: Developer Note:
746: If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
748: .seealso: [](chapter_ts), `TSSetRHSFunctionContextDestroy()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
749: @*/
750: PetscErrorCode DMTSSetRHSFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
751: {
752: DMTS tsdm;
755: DMGetDMTSWrite(dm, &tsdm);
756: if (tsdm->rhsfunctionctxcontainer) PetscContainerSetUserDestroy(tsdm->rhsfunctionctxcontainer, f);
757: return 0;
758: }
760: PetscErrorCode DMTSUnsetRHSFunctionContext_Internal(DM dm)
761: {
762: DMTS tsdm;
765: DMGetDMTSWrite(dm, &tsdm);
766: DMTSUnsetRHSFunctionContext_DMTS(tsdm);
767: tsdm->rhsfunctionctxcontainer = NULL;
768: return 0;
769: }
771: /*@C
772: DMTSSetTransientVariable - sets function to transform from state to transient variables
774: Logically Collective
776: Input Parameters:
777: + dm - `DM` to be used with `TS`
778: . tvar - a function that transforms to transient variables
779: - ctx - a context for tvar
781: Calling sequence of tvar:
782: $ PetscErrorCode tvar(TS ts,Vec p,Vec c,void *ctx);
784: + ts - timestep context
785: . p - input vector (primitive form)
786: . c - output vector, transient variables (conservative form)
787: - ctx - [optional] user-defined function context
789: Level: advanced
791: Notes:
792: This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
793: can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to
794: well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is
795: C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
796: evaluated via the chain rule, as in
798: dF/dP + shift * dF/dCdot dC/dP.
800: .seealso: [](chapter_ts), `TS`, `TSBDF`, `TSSetTransientVariable()`, `DMTSGetTransientVariable()`, `DMTSSetIFunction()`, `DMTSSetIJacobian()`
801: @*/
802: PetscErrorCode DMTSSetTransientVariable(DM dm, TSTransientVariable tvar, void *ctx)
803: {
804: DMTS dmts;
807: DMGetDMTSWrite(dm, &dmts);
808: dmts->ops->transientvar = tvar;
809: dmts->transientvarctx = ctx;
810: return 0;
811: }
813: /*@C
814: DMTSGetTransientVariable - gets function to transform from state to transient variables set with `DMTSSetTransientVariable()`
816: Logically Collective
818: Input Parameter:
819: . dm - `DM` to be used with `TS`
821: Output Parameters:
822: + tvar - a function that transforms to transient variables
823: - ctx - a context for tvar
825: Level: advanced
827: .seealso: [](chapter_ts), `DM`, `DMTSSetTransientVariable()`, `DMTSGetIFunction()`, `DMTSGetIJacobian()`
828: @*/
829: PetscErrorCode DMTSGetTransientVariable(DM dm, TSTransientVariable *tvar, void *ctx)
830: {
831: DMTS dmts;
834: DMGetDMTS(dm, &dmts);
835: if (tvar) *tvar = dmts->ops->transientvar;
836: if (ctx) *(void **)ctx = dmts->transientvarctx;
837: return 0;
838: }
840: /*@C
841: DMTSGetSolutionFunction - gets the `TS` solution evaluation function
843: Not Collective
845: Input Parameter:
846: . dm - `DM` to be used with `TS`
848: Output Parameters:
849: + func - solution function evaluation function, see `TSSetSolution()` for calling sequence
850: - ctx - context for solution evaluation
852: Level: advanced
854: .seealso: [](chapter_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSSetSolutionFunction()`
855: @*/
856: PetscErrorCode DMTSGetSolutionFunction(DM dm, TSSolutionFunction *func, void **ctx)
857: {
858: DMTS tsdm;
861: DMGetDMTS(dm, &tsdm);
862: if (func) *func = tsdm->ops->solution;
863: if (ctx) *ctx = tsdm->solutionctx;
864: return 0;
865: }
867: /*@C
868: DMTSSetSolutionFunction - set `TS` solution evaluation function
870: Not Collective
872: Input Parameters:
873: + dm - `DM` to be used with `TS`
874: . func - solution function evaluation routine
875: - ctx - context for solution evaluation
877: Calling sequence of f:
878: $ PetscErrorCode f(TS ts,PetscReal t,Vec u,void *ctx);
880: + ts - timestep context
881: . t - current timestep
882: . u - output vector
883: - ctx - [optional] user-defined function context
885: Level: advanced
887: Note:
888: `TSSetSolutionFunction()` is normally used, but it calls this function internally because the user context is actually
889: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
890: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
892: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSGetSolutionFunction()`
893: @*/
894: PetscErrorCode DMTSSetSolutionFunction(DM dm, TSSolutionFunction func, void *ctx)
895: {
896: DMTS tsdm;
899: DMGetDMTSWrite(dm, &tsdm);
900: if (func) tsdm->ops->solution = func;
901: if (ctx) tsdm->solutionctx = ctx;
902: return 0;
903: }
905: /*@C
906: DMTSSetForcingFunction - set `TS` forcing function evaluation function
908: Not Collective
910: Input Parameters:
911: + dm - `DM` to be used with `TS`
912: . f - forcing function evaluation routine
913: - ctx - context for solution evaluation
915: Calling sequence of func:
916: $ PetscErrorCode func (TS ts,PetscReal t,Vec f,void *ctx);
918: + ts - timestep context
919: . t - current timestep
920: . f - output vector
921: - ctx - [optional] user-defined function context
923: Level: advanced
925: Note:
926: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
927: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
928: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
930: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
931: @*/
932: PetscErrorCode DMTSSetForcingFunction(DM dm, TSForcingFunction f, void *ctx)
933: {
934: DMTS tsdm;
937: DMGetDMTSWrite(dm, &tsdm);
938: if (f) tsdm->ops->forcing = f;
939: if (ctx) tsdm->forcingctx = ctx;
940: return 0;
941: }
943: /*@C
944: DMTSGetForcingFunction - get `TS` forcing function evaluation function
946: Not Collective
948: Input Parameter:
949: . dm - `DM` to be used with `TS`
951: Output Parameters:
952: + f - forcing function evaluation function; see `TSForcingFunction` for details
953: - ctx - context for solution evaluation
955: Level: advanced
957: Note:
958: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
959: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
960: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
962: .seealso: [](chapter_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
963: @*/
964: PetscErrorCode DMTSGetForcingFunction(DM dm, TSForcingFunction *f, void **ctx)
965: {
966: DMTS tsdm;
969: DMGetDMTSWrite(dm, &tsdm);
970: if (f) *f = tsdm->ops->forcing;
971: if (ctx) *ctx = tsdm->forcingctx;
972: return 0;
973: }
975: /*@C
976: DMTSGetRHSFunction - get `TS` explicit residual evaluation function
978: Not Collective
980: Input Parameter:
981: . dm - `DM` to be used with `TS`
983: Output Parameters:
984: + func - residual evaluation function, see `TSSetRHSFunction()` for calling sequence
985: - ctx - context for residual evaluation
987: Level: advanced
989: Note:
990: `TSGetFunction()` is normally used, but it calls this function internally because the user context is actually
991: associated with the DM.
993: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
994: @*/
995: PetscErrorCode DMTSGetRHSFunction(DM dm, TSRHSFunction *func, void **ctx)
996: {
997: DMTS tsdm;
1000: DMGetDMTS(dm, &tsdm);
1001: if (func) *func = tsdm->ops->rhsfunction;
1002: if (ctx) {
1003: if (tsdm->rhsfunctionctxcontainer) PetscContainerGetPointer(tsdm->rhsfunctionctxcontainer, ctx);
1004: else *ctx = NULL;
1005: }
1006: return 0;
1007: }
1009: /*@C
1010: DMTSSetIJacobian - set `TS` Jacobian evaluation function
1012: Not Collective
1014: Input Parameters:
1015: + dm - `DM` to be used with `TS`
1016: . func - Jacobian evaluation routine
1017: - ctx - context for residual evaluation
1019: Calling sequence of f:
1020: $ PetscErrorCode f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat Amat,Mat Pmat,void *ctx);
1022: + t - time at step/stage being solved
1023: . U - state vector
1024: . U_t - time derivative of state vector
1025: . a - shift
1026: . Amat - (approximate) Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
1027: . Pmat - matrix used for constructing preconditioner, usually the same as Amat
1028: - ctx - [optional] user-defined context for matrix evaluation routine
1030: Level: advanced
1032: Note:
1033: `TSSetJacobian()` is normally used, but it calls this function internally because the user context is actually
1034: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1035: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1037: .seealso: [](chapter_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSGetJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()`
1038: @*/
1039: PetscErrorCode DMTSSetIJacobian(DM dm, TSIJacobian func, void *ctx)
1040: {
1041: DMTS tsdm;
1044: DMGetDMTSWrite(dm, &tsdm);
1045: if (func) tsdm->ops->ijacobian = func;
1046: if (ctx) {
1047: PetscContainer ctxcontainer;
1048: PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer);
1049: PetscContainerSetPointer(ctxcontainer, ctx);
1050: PetscObjectCompose((PetscObject)tsdm, "ijacobian ctx", (PetscObject)ctxcontainer);
1051: tsdm->ijacobianctxcontainer = ctxcontainer;
1052: PetscContainerDestroy(&ctxcontainer);
1053: }
1054: return 0;
1055: }
1057: /*@C
1058: DMTSSetIJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1060: Not Collective
1062: Input Parameters:
1063: + dm - `DM` to be used with `TS`
1064: - f - Jacobian evaluation context destroy function
1066: Level: advanced
1068: Note:
1069: `TSSetIJacobianContextDestroy()` is normally used, but it calls this function internally because the user context is actually
1070: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1071: not.
1073: Developer Note:
1074: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1076: .seealso: [](chapter_ts), `TSSetIJacobianContextDestroy()`, `TSSetI2JacobianContextDestroy()`, `DMTSSetIJacobian()`, `TSSetIJacobian()`
1077: @*/
1078: PetscErrorCode DMTSSetIJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1079: {
1080: DMTS tsdm;
1083: DMGetDMTSWrite(dm, &tsdm);
1084: if (tsdm->ijacobianctxcontainer) PetscContainerSetUserDestroy(tsdm->ijacobianctxcontainer, f);
1085: return 0;
1086: }
1088: PetscErrorCode DMTSUnsetIJacobianContext_Internal(DM dm)
1089: {
1090: DMTS tsdm;
1093: DMGetDMTSWrite(dm, &tsdm);
1094: DMTSUnsetIJacobianContext_DMTS(tsdm);
1095: return 0;
1096: }
1098: /*@C
1099: DMTSGetIJacobian - get `TS` Jacobian evaluation function
1101: Not Collective
1103: Input Parameter:
1104: . dm - `DM` to be used with `TS`
1106: Output Parameters:
1107: + func - Jacobian evaluation function, see `TSSetIJacobian()` for calling sequence
1108: - ctx - context for residual evaluation
1110: Level: advanced
1112: Note:
1113: `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1114: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1115: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1117: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1118: @*/
1119: PetscErrorCode DMTSGetIJacobian(DM dm, TSIJacobian *func, void **ctx)
1120: {
1121: DMTS tsdm;
1124: DMGetDMTS(dm, &tsdm);
1125: if (func) *func = tsdm->ops->ijacobian;
1126: if (ctx) {
1127: if (tsdm->ijacobianctxcontainer) PetscContainerGetPointer(tsdm->ijacobianctxcontainer, ctx);
1128: else *ctx = NULL;
1129: }
1130: return 0;
1131: }
1133: /*@C
1134: DMTSSetRHSJacobian - set `TS` Jacobian evaluation function
1136: Not Collective
1138: Input Parameters:
1139: + dm - `DM` to be used with `TS`
1140: . func - Jacobian evaluation routine
1141: - ctx - context for residual evaluation
1143: Calling sequence of func:
1144: $ PetscErrorCode func(TS ts,PetscReal t,Vec u,Mat A,Mat B,void *ctx);
1146: + t - current timestep
1147: . u - input vector
1148: . Amat - (approximate) Jacobian matrix
1149: . Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
1150: - ctx - [optional] user-defined context for matrix evaluation routine
1152: Level: advanced
1154: Note:
1155: `TSSetJacobian()` is normally used, but it calls this function internally because the user context is actually
1156: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1157: not.
1159: Developer Note:
1160: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1162: .seealso: [](chapter_ts), `DMTSSetContext()`, `TSSetFunction()`, `DMTSGetJacobian()`, `TSSetRHSJacobian()`
1163: @*/
1164: PetscErrorCode DMTSSetRHSJacobian(DM dm, TSRHSJacobian func, void *ctx)
1165: {
1166: DMTS tsdm;
1169: DMGetDMTSWrite(dm, &tsdm);
1170: if (func) tsdm->ops->rhsjacobian = func;
1171: if (ctx) {
1172: PetscContainer ctxcontainer;
1173: PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer);
1174: PetscContainerSetPointer(ctxcontainer, ctx);
1175: PetscObjectCompose((PetscObject)tsdm, "rhs jacobian ctx", (PetscObject)ctxcontainer);
1176: tsdm->rhsjacobianctxcontainer = ctxcontainer;
1177: PetscContainerDestroy(&ctxcontainer);
1178: }
1179: return 0;
1180: }
1182: /*@C
1183: DMTSSetRHSJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1185: Not Collective
1187: Input Parameters:
1188: + dm - `DM` to be used with `TS`
1189: - f - Jacobian evaluation context destroy function
1191: Level: advanced
1193: Note:
1194: The user usually calls `TSSetRHSJacobianContextDestroy()` which calls this routine
1196: .seealso: [](chapter_ts), `TS`, `TSSetRHSJacobianContextDestroy()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1197: @*/
1198: PetscErrorCode DMTSSetRHSJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1199: {
1200: DMTS tsdm;
1203: DMGetDMTSWrite(dm, &tsdm);
1204: if (tsdm->rhsjacobianctxcontainer) PetscContainerSetUserDestroy(tsdm->rhsjacobianctxcontainer, f);
1205: return 0;
1206: }
1208: PetscErrorCode DMTSUnsetRHSJacobianContext_Internal(DM dm)
1209: {
1210: DMTS tsdm;
1213: DMGetDMTSWrite(dm, &tsdm);
1214: DMTSUnsetRHSJacobianContext_DMTS(tsdm);
1215: return 0;
1216: }
1218: /*@C
1219: DMTSGetRHSJacobian - get `TS` Jacobian evaluation function
1221: Not Collective
1223: Input Parameter:
1224: . dm - `DM` to be used with `TS`
1226: Output Parameters:
1227: + func - Jacobian evaluation function, see `TSSetRHSJacobian()` for calling sequence
1228: - ctx - context for residual evaluation
1230: Level: advanced
1232: Note:
1233: `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1234: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1235: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1237: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1238: @*/
1239: PetscErrorCode DMTSGetRHSJacobian(DM dm, TSRHSJacobian *func, void **ctx)
1240: {
1241: DMTS tsdm;
1244: DMGetDMTS(dm, &tsdm);
1245: if (func) *func = tsdm->ops->rhsjacobian;
1246: if (ctx) {
1247: if (tsdm->rhsjacobianctxcontainer) PetscContainerGetPointer(tsdm->rhsjacobianctxcontainer, ctx);
1248: else *ctx = NULL;
1249: }
1250: return 0;
1251: }
1253: /*@C
1254: DMTSSetIFunctionSerialize - sets functions used to view and load a IFunction context
1256: Not Collective
1258: Input Parameters:
1259: + dm - `DM` to be used with `TS`
1260: . view - viewer function
1261: - load - loading function
1263: Level: advanced
1265: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1266: @*/
1267: PetscErrorCode DMTSSetIFunctionSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1268: {
1269: DMTS tsdm;
1272: DMGetDMTSWrite(dm, &tsdm);
1273: tsdm->ops->ifunctionview = view;
1274: tsdm->ops->ifunctionload = load;
1275: return 0;
1276: }
1278: /*@C
1279: DMTSSetIJacobianSerialize - sets functions used to view and load a IJacobian context
1281: Not Collective
1283: Input Parameters:
1284: + dm - `DM` to be used with `TS`
1285: . view - viewer function
1286: - load - loading function
1288: Level: advanced
1290: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1291: @*/
1292: PetscErrorCode DMTSSetIJacobianSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1293: {
1294: DMTS tsdm;
1297: DMGetDMTSWrite(dm, &tsdm);
1298: tsdm->ops->ijacobianview = view;
1299: tsdm->ops->ijacobianload = load;
1300: return 0;
1301: }