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: PetscFunctionBegin;
7: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", NULL));
8: tsdm->rhsfunctionctxcontainer = NULL;
9: PetscFunctionReturn(PETSC_SUCCESS);
10: }
12: static PetscErrorCode DMTSUnsetRHSJacobianContext_DMTS(DMTS tsdm)
13: {
14: PetscFunctionBegin;
15: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs jacobian ctx", NULL));
16: tsdm->rhsjacobianctxcontainer = NULL;
17: PetscFunctionReturn(PETSC_SUCCESS);
18: }
20: static PetscErrorCode DMTSUnsetIFunctionContext_DMTS(DMTS tsdm)
21: {
22: PetscFunctionBegin;
23: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ifunction ctx", NULL));
24: tsdm->ifunctionctxcontainer = NULL;
25: PetscFunctionReturn(PETSC_SUCCESS);
26: }
28: static PetscErrorCode DMTSUnsetIJacobianContext_DMTS(DMTS tsdm)
29: {
30: PetscFunctionBegin;
31: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ijacobian ctx", NULL));
32: tsdm->ijacobianctxcontainer = NULL;
33: PetscFunctionReturn(PETSC_SUCCESS);
34: }
36: static PetscErrorCode DMTSUnsetI2FunctionContext_DMTS(DMTS tsdm)
37: {
38: PetscFunctionBegin;
39: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2function ctx", NULL));
40: tsdm->i2functionctxcontainer = NULL;
41: PetscFunctionReturn(PETSC_SUCCESS);
42: }
44: static PetscErrorCode DMTSUnsetI2JacobianContext_DMTS(DMTS tsdm)
45: {
46: PetscFunctionBegin;
47: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2jacobian ctx", NULL));
48: tsdm->i2jacobianctxcontainer = NULL;
49: PetscFunctionReturn(PETSC_SUCCESS);
50: }
52: static PetscErrorCode DMTSDestroy(DMTS *kdm)
53: {
54: PetscFunctionBegin;
55: if (!*kdm) PetscFunctionReturn(PETSC_SUCCESS);
57: if (--((PetscObject)(*kdm))->refct > 0) {
58: *kdm = NULL;
59: PetscFunctionReturn(PETSC_SUCCESS);
60: }
61: PetscCall(DMTSUnsetRHSFunctionContext_DMTS(*kdm));
62: PetscCall(DMTSUnsetRHSJacobianContext_DMTS(*kdm));
63: PetscCall(DMTSUnsetIFunctionContext_DMTS(*kdm));
64: PetscCall(DMTSUnsetIJacobianContext_DMTS(*kdm));
65: PetscCall(DMTSUnsetI2FunctionContext_DMTS(*kdm));
66: PetscCall(DMTSUnsetI2JacobianContext_DMTS(*kdm));
67: PetscTryTypeMethod(*kdm, destroy);
68: PetscCall(PetscHeaderDestroy(kdm));
69: PetscFunctionReturn(PETSC_SUCCESS);
70: }
72: PetscErrorCode DMTSLoad(DMTS kdm, PetscViewer viewer)
73: {
74: PetscFunctionBegin;
75: PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ifunction, 1, NULL, PETSC_FUNCTION));
76: PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ifunctionview, 1, NULL, PETSC_FUNCTION));
77: PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ifunctionload, 1, NULL, PETSC_FUNCTION));
78: if (kdm->ops->ifunctionload) {
79: void *ctx;
81: PetscCall(PetscContainerGetPointer(kdm->ifunctionctxcontainer, &ctx));
82: PetscCall((*kdm->ops->ifunctionload)(&ctx, viewer));
83: }
84: PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ijacobian, 1, NULL, PETSC_FUNCTION));
85: PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ijacobianview, 1, NULL, PETSC_FUNCTION));
86: PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ijacobianload, 1, NULL, PETSC_FUNCTION));
87: if (kdm->ops->ijacobianload) {
88: void *ctx;
90: PetscCall(PetscContainerGetPointer(kdm->ijacobianctxcontainer, &ctx));
91: PetscCall((*kdm->ops->ijacobianload)(&ctx, viewer));
92: }
93: PetscFunctionReturn(PETSC_SUCCESS);
94: }
96: PetscErrorCode DMTSView(DMTS kdm, PetscViewer viewer)
97: {
98: PetscBool isascii, isbinary;
100: PetscFunctionBegin;
101: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
102: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
103: if (isascii) {
104: #if defined(PETSC_SERIALIZE_FUNCTIONS)
105: const char *fname;
107: PetscCall(PetscFPTFind(kdm->ops->ifunction, &fname));
108: if (fname) PetscCall(PetscViewerASCIIPrintf(viewer, " IFunction used by TS: %s\n", fname));
109: PetscCall(PetscFPTFind(kdm->ops->ijacobian, &fname));
110: if (fname) PetscCall(PetscViewerASCIIPrintf(viewer, " IJacobian function used by TS: %s\n", fname));
111: #endif
112: } else if (isbinary) {
113: struct {
114: TSIFunction ifunction;
115: } funcstruct;
116: struct {
117: PetscErrorCode (*ifunctionview)(void *, PetscViewer);
118: } funcviewstruct;
119: struct {
120: PetscErrorCode (*ifunctionload)(void **, PetscViewer);
121: } funcloadstruct;
122: struct {
123: TSIJacobian ijacobian;
124: } jacstruct;
125: struct {
126: PetscErrorCode (*ijacobianview)(void *, PetscViewer);
127: } jacviewstruct;
128: struct {
129: PetscErrorCode (*ijacobianload)(void **, PetscViewer);
130: } jacloadstruct;
132: funcstruct.ifunction = kdm->ops->ifunction;
133: funcviewstruct.ifunctionview = kdm->ops->ifunctionview;
134: funcloadstruct.ifunctionload = kdm->ops->ifunctionload;
135: PetscCall(PetscViewerBinaryWrite(viewer, &funcstruct, 1, PETSC_FUNCTION));
136: PetscCall(PetscViewerBinaryWrite(viewer, &funcviewstruct, 1, PETSC_FUNCTION));
137: PetscCall(PetscViewerBinaryWrite(viewer, &funcloadstruct, 1, PETSC_FUNCTION));
138: if (kdm->ops->ifunctionview) {
139: void *ctx;
141: PetscCall(PetscContainerGetPointer(kdm->ifunctionctxcontainer, &ctx));
142: PetscCall((*kdm->ops->ifunctionview)(ctx, viewer));
143: }
144: jacstruct.ijacobian = kdm->ops->ijacobian;
145: jacviewstruct.ijacobianview = kdm->ops->ijacobianview;
146: jacloadstruct.ijacobianload = kdm->ops->ijacobianload;
147: PetscCall(PetscViewerBinaryWrite(viewer, &jacstruct, 1, PETSC_FUNCTION));
148: PetscCall(PetscViewerBinaryWrite(viewer, &jacviewstruct, 1, PETSC_FUNCTION));
149: PetscCall(PetscViewerBinaryWrite(viewer, &jacloadstruct, 1, PETSC_FUNCTION));
150: if (kdm->ops->ijacobianview) {
151: void *ctx;
153: PetscCall(PetscContainerGetPointer(kdm->ijacobianctxcontainer, &ctx));
154: PetscCall((*kdm->ops->ijacobianview)(ctx, viewer));
155: }
156: }
157: PetscFunctionReturn(PETSC_SUCCESS);
158: }
160: static PetscErrorCode DMTSCreate(MPI_Comm comm, DMTS *kdm)
161: {
162: PetscFunctionBegin;
163: PetscCall(TSInitializePackage());
164: PetscCall(PetscHeaderCreate(*kdm, DMTS_CLASSID, "DMTS", "DMTS", "DMTS", comm, DMTSDestroy, DMTSView));
165: PetscFunctionReturn(PETSC_SUCCESS);
166: }
168: /* Attaches the DMTS to the coarse level.
169: * Under what conditions should we copy versus duplicate?
170: */
171: static PetscErrorCode DMCoarsenHook_DMTS(DM dm, DM dmc, void *ctx)
172: {
173: PetscFunctionBegin;
174: PetscCall(DMCopyDMTS(dm, dmc));
175: PetscFunctionReturn(PETSC_SUCCESS);
176: }
178: /* This could restrict auxiliary information to the coarse level.
179: */
180: static PetscErrorCode DMRestrictHook_DMTS(DM dm, Mat Restrict, Vec rscale, Mat Inject, DM dmc, void *ctx)
181: {
182: PetscFunctionBegin;
183: PetscFunctionReturn(PETSC_SUCCESS);
184: }
186: static PetscErrorCode DMSubDomainHook_DMTS(DM dm, DM subdm, void *ctx)
187: {
188: PetscFunctionBegin;
189: PetscCall(DMCopyDMTS(dm, subdm));
190: PetscFunctionReturn(PETSC_SUCCESS);
191: }
193: /* This could restrict auxiliary information to the coarse level.
194: */
195: static PetscErrorCode DMSubDomainRestrictHook_DMTS(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx)
196: {
197: PetscFunctionBegin;
198: PetscFunctionReturn(PETSC_SUCCESS);
199: }
201: /*@C
202: DMTSCopy - copies the information in a `DMTS` to another `DMTS`
204: Not Collective
206: Input Parameters:
207: + kdm - Original `DMTS`
208: - nkdm - `DMTS` to receive the data, should have been created with `DMTSCreate()`
210: Level: developer
212: .seealso: [](ch_ts), `DMTSCreate()`, `DMTSDestroy()`
213: @*/
214: PetscErrorCode DMTSCopy(DMTS kdm, DMTS nkdm)
215: {
216: PetscFunctionBegin;
219: nkdm->ops->rhsfunction = kdm->ops->rhsfunction;
220: nkdm->ops->rhsjacobian = kdm->ops->rhsjacobian;
221: nkdm->ops->ifunction = kdm->ops->ifunction;
222: nkdm->ops->ijacobian = kdm->ops->ijacobian;
223: nkdm->ops->i2function = kdm->ops->i2function;
224: nkdm->ops->i2jacobian = kdm->ops->i2jacobian;
225: nkdm->ops->solution = kdm->ops->solution;
226: nkdm->ops->destroy = kdm->ops->destroy;
227: nkdm->ops->duplicate = kdm->ops->duplicate;
229: nkdm->solutionctx = kdm->solutionctx;
230: nkdm->rhsfunctionctxcontainer = kdm->rhsfunctionctxcontainer;
231: nkdm->rhsjacobianctxcontainer = kdm->rhsjacobianctxcontainer;
232: nkdm->ifunctionctxcontainer = kdm->ifunctionctxcontainer;
233: nkdm->ijacobianctxcontainer = kdm->ijacobianctxcontainer;
234: nkdm->i2functionctxcontainer = kdm->i2functionctxcontainer;
235: nkdm->i2jacobianctxcontainer = kdm->i2jacobianctxcontainer;
236: if (nkdm->rhsfunctionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "rhs function ctx", (PetscObject)nkdm->rhsfunctionctxcontainer));
237: if (nkdm->rhsjacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "rhs jacobian ctx", (PetscObject)nkdm->rhsjacobianctxcontainer));
238: if (nkdm->ifunctionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "ifunction ctx", (PetscObject)nkdm->ifunctionctxcontainer));
239: if (nkdm->ijacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "ijacobian ctx", (PetscObject)nkdm->ijacobianctxcontainer));
240: if (nkdm->i2functionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "i2function ctx", (PetscObject)nkdm->i2functionctxcontainer));
241: if (nkdm->i2jacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "i2jacobian ctx", (PetscObject)nkdm->i2jacobianctxcontainer));
243: nkdm->data = kdm->data;
245: /*
246: nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
247: nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
248: nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
249: */
251: /* implementation specific copy hooks */
252: PetscTryTypeMethod(kdm, duplicate, nkdm);
253: PetscFunctionReturn(PETSC_SUCCESS);
254: }
256: /*@C
257: DMGetDMTS - get read-only private `DMTS` context from a `DM`
259: Not Collective
261: Input Parameter:
262: . dm - `DM` to be used with `TS`
264: Output Parameter:
265: . tsdm - private `DMTS` context
267: Level: developer
269: Notes:
270: Use `DMGetDMTSWrite()` if write access is needed. The `DMTSSetXXX()` API should be used wherever possible.
272: .seealso: [](ch_ts), `DMTS`, `DMGetDMTSWrite()`
273: @*/
274: PetscErrorCode DMGetDMTS(DM dm, DMTS *tsdm)
275: {
276: PetscFunctionBegin;
278: *tsdm = (DMTS)dm->dmts;
279: if (!*tsdm) {
280: PetscCall(PetscInfo(dm, "Creating new DMTS\n"));
281: PetscCall(DMTSCreate(PetscObjectComm((PetscObject)dm), tsdm));
282: dm->dmts = (PetscObject)*tsdm;
283: (*tsdm)->originaldm = dm;
284: PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_DMTS, DMRestrictHook_DMTS, NULL));
285: PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_DMTS, DMSubDomainRestrictHook_DMTS, NULL));
286: }
287: PetscFunctionReturn(PETSC_SUCCESS);
288: }
290: /*@C
291: DMGetDMTSWrite - get write access to private `DMTS` context from a `DM`
293: Not Collective
295: Input Parameter:
296: . dm - `DM` to be used with `TS`
298: Output Parameter:
299: . tsdm - private `DMTS` context
301: Level: developer
303: .seealso: [](ch_ts), `DMTS`, `DMGetDMTS()`
304: @*/
305: PetscErrorCode DMGetDMTSWrite(DM dm, DMTS *tsdm)
306: {
307: DMTS sdm;
309: PetscFunctionBegin;
311: PetscCall(DMGetDMTS(dm, &sdm));
312: PetscCheck(sdm->originaldm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DMTS has a NULL originaldm");
313: if (sdm->originaldm != dm) { /* Copy on write */
314: DMTS oldsdm = sdm;
315: PetscCall(PetscInfo(dm, "Copying DMTS due to write\n"));
316: PetscCall(DMTSCreate(PetscObjectComm((PetscObject)dm), &sdm));
317: PetscCall(DMTSCopy(oldsdm, sdm));
318: PetscCall(DMTSDestroy((DMTS *)&dm->dmts));
319: dm->dmts = (PetscObject)sdm;
320: sdm->originaldm = dm;
321: }
322: *tsdm = sdm;
323: PetscFunctionReturn(PETSC_SUCCESS);
324: }
326: /*@C
327: DMCopyDMTS - copies a `DM` context to a new `DM`
329: Logically Collective
331: Input Parameters:
332: + dmsrc - `DM` to obtain context from
333: - dmdest - `DM` to add context to
335: Level: developer
337: Note:
338: The context is copied by reference. This function does not ensure that a context exists.
340: .seealso: [](ch_ts), `DMTS`, `DMGetDMTS()`, `TSSetDM()`
341: @*/
342: PetscErrorCode DMCopyDMTS(DM dmsrc, DM dmdest)
343: {
344: PetscFunctionBegin;
347: PetscCall(DMTSDestroy((DMTS *)&dmdest->dmts));
348: dmdest->dmts = dmsrc->dmts;
349: PetscCall(PetscObjectReference(dmdest->dmts));
350: PetscCall(DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMTS, DMRestrictHook_DMTS, NULL));
351: PetscCall(DMSubDomainHookAdd(dmdest, DMSubDomainHook_DMTS, DMSubDomainRestrictHook_DMTS, NULL));
352: PetscFunctionReturn(PETSC_SUCCESS);
353: }
355: /*@C
356: DMTSSetIFunction - set `TS` implicit function evaluation function
358: Not Collective
360: Input Parameters:
361: + dm - `DM` to be used with `TS`
362: . func - function evaluating f(t,u,u_t)
363: - ctx - context for residual evaluation
365: Level: advanced
367: Note:
368: `TSSetFunction()` is normally used, but it calls this function internally because the user context is actually
369: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
370: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
372: .seealso: [](ch_ts), `TS`, `DM`, `TSIFunction`, `DMTSSetContext()`, `TSSetIFunction()`,
373: `DMTSSetJacobian()`
374: @*/
375: PetscErrorCode DMTSSetIFunction(DM dm, TSIFunction func, void *ctx)
376: {
377: DMTS tsdm;
379: PetscFunctionBegin;
381: PetscCall(DMGetDMTSWrite(dm, &tsdm));
382: if (func) tsdm->ops->ifunction = func;
383: if (ctx) {
384: PetscContainer ctxcontainer;
385: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
386: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
387: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ifunction ctx", (PetscObject)ctxcontainer));
388: tsdm->ifunctionctxcontainer = ctxcontainer;
389: PetscCall(PetscContainerDestroy(&ctxcontainer));
390: }
391: PetscFunctionReturn(PETSC_SUCCESS);
392: }
394: /*@C
395: DMTSSetIFunctionContextDestroy - set `TS` implicit evaluation context destroy function
397: Not Collective
399: Input Parameters:
400: + dm - `DM` to be used with `TS`
401: - f - implicit evaluation context destroy function
403: Level: advanced
405: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetIFunction()`, `TSSetIFunction()`
406: @*/
407: PetscErrorCode DMTSSetIFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
408: {
409: DMTS tsdm;
411: PetscFunctionBegin;
413: PetscCall(DMGetDMTSWrite(dm, &tsdm));
414: if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->ifunctionctxcontainer, f));
415: PetscFunctionReturn(PETSC_SUCCESS);
416: }
418: PetscErrorCode DMTSUnsetIFunctionContext_Internal(DM dm)
419: {
420: DMTS tsdm;
422: PetscFunctionBegin;
424: PetscCall(DMGetDMTSWrite(dm, &tsdm));
425: PetscCall(DMTSUnsetIFunctionContext_DMTS(tsdm));
426: PetscFunctionReturn(PETSC_SUCCESS);
427: }
429: /*@C
430: DMTSGetIFunction - get `TS` implicit residual evaluation function
432: Not Collective
434: Input Parameter:
435: . dm - `DM` to be used with `TS`
437: Output Parameters:
438: + func - function evaluation function, for calling sequence see `TSSetIFunction()`
439: - ctx - context for residual evaluation
441: Level: advanced
443: Note:
444: `TSGetFunction()` is normally used, but it calls this function internally because the user context is actually
445: associated with the `DM`.
447: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `DMTSSetFunction()`, `TSSetFunction()`
448: @*/
449: PetscErrorCode DMTSGetIFunction(DM dm, TSIFunction *func, void **ctx)
450: {
451: DMTS tsdm;
453: PetscFunctionBegin;
455: PetscCall(DMGetDMTS(dm, &tsdm));
456: if (func) *func = tsdm->ops->ifunction;
457: if (ctx) {
458: if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ifunctionctxcontainer, ctx));
459: else *ctx = NULL;
460: }
461: PetscFunctionReturn(PETSC_SUCCESS);
462: }
464: /*@C
465: DMTSSetI2Function - set `TS` implicit function evaluation function for 2nd order systems
467: Not Collective
469: Input Parameters:
470: + dm - `DM` to be used with `TS`
471: . fun - function evaluation routine
472: - ctx - context for residual evaluation
474: Level: advanced
476: Note:
477: `TSSetI2Function()` is normally used, but it calls this function internally because the user context is actually
478: associated with the `DM`.
480: .seealso: [](ch_ts), `DM`, `TS`, `TSSetI2Function()`
481: @*/
482: PetscErrorCode DMTSSetI2Function(DM dm, TSI2Function fun, void *ctx)
483: {
484: DMTS tsdm;
486: PetscFunctionBegin;
488: PetscCall(DMGetDMTSWrite(dm, &tsdm));
489: if (fun) tsdm->ops->i2function = fun;
490: if (ctx) {
491: PetscContainer ctxcontainer;
492: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
493: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
494: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2function ctx", (PetscObject)ctxcontainer));
495: tsdm->i2functionctxcontainer = ctxcontainer;
496: PetscCall(PetscContainerDestroy(&ctxcontainer));
497: }
498: PetscFunctionReturn(PETSC_SUCCESS);
499: }
501: /*@C
502: DMTSSetI2FunctionContextDestroy - set `TS` implicit evaluation for 2nd order systems context destroy
504: Not Collective
506: Input Parameters:
507: + dm - `DM` to be used with `TS`
508: - f - implicit evaluation context destroy function
510: Level: advanced
512: Note:
513: `TSSetI2FunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
514: associated with the `DM`.
516: .seealso: [](ch_ts), `TSSetI2FunctionContextDestroy()`, `DMTSSetI2Function()`, `TSSetI2Function()`
517: @*/
518: PetscErrorCode DMTSSetI2FunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
519: {
520: DMTS tsdm;
522: PetscFunctionBegin;
524: PetscCall(DMGetDMTSWrite(dm, &tsdm));
525: if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->i2functionctxcontainer, f));
526: PetscFunctionReturn(PETSC_SUCCESS);
527: }
529: PetscErrorCode DMTSUnsetI2FunctionContext_Internal(DM dm)
530: {
531: DMTS tsdm;
533: PetscFunctionBegin;
535: PetscCall(DMGetDMTSWrite(dm, &tsdm));
536: PetscCall(DMTSUnsetI2FunctionContext_DMTS(tsdm));
537: PetscFunctionReturn(PETSC_SUCCESS);
538: }
540: /*@C
541: DMTSGetI2Function - get `TS` implicit residual evaluation function for 2nd order systems
543: Not Collective
545: Input Parameter:
546: . dm - `DM` to be used with `TS`
548: Output Parameters:
549: + fun - function evaluation function, for calling sequence see `TSSetI2Function()`
550: - ctx - context for residual evaluation
552: Level: advanced
554: Note:
555: `TSGetI2Function()` is normally used, but it calls this function internally because the user context is actually
556: associated with the `DM`.
558: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetI2Function()`, `TSGetI2Function()`
559: @*/
560: PetscErrorCode DMTSGetI2Function(DM dm, TSI2Function *fun, void **ctx)
561: {
562: DMTS tsdm;
564: PetscFunctionBegin;
566: PetscCall(DMGetDMTS(dm, &tsdm));
567: if (fun) *fun = tsdm->ops->i2function;
568: if (ctx) {
569: if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2functionctxcontainer, ctx));
570: else *ctx = NULL;
571: }
572: PetscFunctionReturn(PETSC_SUCCESS);
573: }
575: /*@C
576: DMTSSetI2Jacobian - set `TS` implicit Jacobian evaluation function for 2nd order systems
578: Not Collective
580: Input Parameters:
581: + dm - `DM` to be used with `TS`
582: . jac - Jacobian evaluation routine
583: - ctx - context for Jacobian evaluation
585: Level: advanced
587: Note:
588: `TSSetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
589: associated with the `DM`.
591: .seealso: [](ch_ts), `DM`, `TS`, `TSI2Jacobian`, `TSSetI2Jacobian()`
592: @*/
593: PetscErrorCode DMTSSetI2Jacobian(DM dm, TSI2Jacobian jac, void *ctx)
594: {
595: DMTS tsdm;
597: PetscFunctionBegin;
599: PetscCall(DMGetDMTSWrite(dm, &tsdm));
600: if (jac) tsdm->ops->i2jacobian = jac;
601: if (ctx) {
602: PetscContainer ctxcontainer;
603: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
604: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
605: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2jacobian ctx", (PetscObject)ctxcontainer));
606: tsdm->i2jacobianctxcontainer = ctxcontainer;
607: PetscCall(PetscContainerDestroy(&ctxcontainer));
608: }
609: PetscFunctionReturn(PETSC_SUCCESS);
610: }
612: /*@C
613: DMTSSetI2JacobianContextDestroy - set `TS` implicit Jacobian evaluation for 2nd order systems context destroy function
615: Not Collective
617: Input Parameters:
618: + dm - `DM` to be used with `TS`
619: - f - implicit Jacobian evaluation context destroy function
621: Level: advanced
623: .seealso: [](ch_ts), `DM`, `TS`, `TSSetI2JacobianContextDestroy()`, `DMTSSetI2Jacobian()`, `TSSetI2Jacobian()`
624: @*/
625: PetscErrorCode DMTSSetI2JacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
626: {
627: DMTS tsdm;
629: PetscFunctionBegin;
631: PetscCall(DMGetDMTSWrite(dm, &tsdm));
632: if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->i2jacobianctxcontainer, f));
633: PetscFunctionReturn(PETSC_SUCCESS);
634: }
636: PetscErrorCode DMTSUnsetI2JacobianContext_Internal(DM dm)
637: {
638: DMTS tsdm;
640: PetscFunctionBegin;
642: PetscCall(DMGetDMTSWrite(dm, &tsdm));
643: PetscCall(DMTSUnsetI2JacobianContext_DMTS(tsdm));
644: PetscFunctionReturn(PETSC_SUCCESS);
645: }
647: /*@C
648: DMTSGetI2Jacobian - get `TS` implicit Jacobian evaluation function for 2nd order systems
650: Not Collective
652: Input Parameter:
653: . dm - `DM` to be used with `TS`
655: Output Parameters:
656: + jac - Jacobian evaluation function, for calling sequence see `TSSetI2Jacobian()`
657: - ctx - context for Jacobian evaluation
659: Level: advanced
661: Note:
662: `TSGetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
663: associated with the `DM`.
665: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetI2Jacobian()`, `TSGetI2Jacobian()`
666: @*/
667: PetscErrorCode DMTSGetI2Jacobian(DM dm, TSI2Jacobian *jac, void **ctx)
668: {
669: DMTS tsdm;
671: PetscFunctionBegin;
673: PetscCall(DMGetDMTS(dm, &tsdm));
674: if (jac) *jac = tsdm->ops->i2jacobian;
675: if (ctx) {
676: if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2jacobianctxcontainer, ctx));
677: else *ctx = NULL;
678: }
679: PetscFunctionReturn(PETSC_SUCCESS);
680: }
682: /*@C
683: DMTSSetRHSFunction - set `TS` explicit residual evaluation function
685: Not Collective
687: Input Parameters:
688: + dm - `DM` to be used with `TS`
689: . func - RHS function evaluation routine
690: - ctx - context for residual evaluation
692: Level: advanced
694: Note:
695: `TSSetRHSFunction()` is normally used, but it calls this function internally because the user context is actually
696: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
697: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
699: .seealso: [](ch_ts), `DM`, `TS`, `TSRHSFunction`, `DMTSSetContext()`, `TSSetRHSFunction()`,
700: `DMTSSetJacobian()`
701: @*/
702: PetscErrorCode DMTSSetRHSFunction(DM dm, TSRHSFunction func, void *ctx)
703: {
704: DMTS tsdm;
706: PetscFunctionBegin;
708: PetscCall(DMGetDMTSWrite(dm, &tsdm));
709: if (func) tsdm->ops->rhsfunction = func;
710: if (ctx) {
711: PetscContainer ctxcontainer;
712: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
713: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
714: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", (PetscObject)ctxcontainer));
715: tsdm->rhsfunctionctxcontainer = ctxcontainer;
716: PetscCall(PetscContainerDestroy(&ctxcontainer));
717: }
718: PetscFunctionReturn(PETSC_SUCCESS);
719: }
721: /*@C
722: DMTSSetRHSFunctionContextDestroy - set `TS` explicit residual evaluation context destroy function
724: Not Collective
726: Input Parameters:
727: + dm - `DM` to be used with `TS`
728: - f - explicit evaluation context destroy function
730: Level: advanced
732: Note:
733: `TSSetRHSFunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
734: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
735: not.
737: Developer Notes:
738: If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
740: .seealso: [](ch_ts), `TSSetRHSFunctionContextDestroy()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
741: @*/
742: PetscErrorCode DMTSSetRHSFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
743: {
744: DMTS tsdm;
746: PetscFunctionBegin;
748: PetscCall(DMGetDMTSWrite(dm, &tsdm));
749: if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->rhsfunctionctxcontainer, f));
750: PetscFunctionReturn(PETSC_SUCCESS);
751: }
753: PetscErrorCode DMTSUnsetRHSFunctionContext_Internal(DM dm)
754: {
755: DMTS tsdm;
757: PetscFunctionBegin;
759: PetscCall(DMGetDMTSWrite(dm, &tsdm));
760: PetscCall(DMTSUnsetRHSFunctionContext_DMTS(tsdm));
761: tsdm->rhsfunctionctxcontainer = NULL;
762: PetscFunctionReturn(PETSC_SUCCESS);
763: }
765: /*@C
766: DMTSSetTransientVariable - sets function to transform from state to transient variables
768: Logically Collective
770: Input Parameters:
771: + dm - `DM` to be used with `TS`
772: . tvar - a function that transforms to transient variables
773: - ctx - a context for tvar
775: Level: advanced
777: Notes:
778: This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
779: can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to
780: well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is
781: C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
782: evaluated via the chain rule, as in
784: dF/dP + shift * dF/dCdot dC/dP.
786: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSetTransientVariable()`, `DMTSGetTransientVariable()`, `DMTSSetIFunction()`, `DMTSSetIJacobian()`
787: @*/
788: PetscErrorCode DMTSSetTransientVariable(DM dm, TSTransientVariable tvar, void *ctx)
789: {
790: DMTS dmts;
792: PetscFunctionBegin;
794: PetscCall(DMGetDMTSWrite(dm, &dmts));
795: dmts->ops->transientvar = tvar;
796: dmts->transientvarctx = ctx;
797: PetscFunctionReturn(PETSC_SUCCESS);
798: }
800: /*@C
801: DMTSGetTransientVariable - gets function to transform from state to transient variables set with `DMTSSetTransientVariable()`
803: Logically Collective
805: Input Parameter:
806: . dm - `DM` to be used with `TS`
808: Output Parameters:
809: + tvar - a function that transforms to transient variables
810: - ctx - a context for tvar
812: Level: advanced
814: .seealso: [](ch_ts), `DM`, `DMTSSetTransientVariable()`, `DMTSGetIFunction()`, `DMTSGetIJacobian()`
815: @*/
816: PetscErrorCode DMTSGetTransientVariable(DM dm, TSTransientVariable *tvar, void *ctx)
817: {
818: DMTS dmts;
820: PetscFunctionBegin;
822: PetscCall(DMGetDMTS(dm, &dmts));
823: if (tvar) *tvar = dmts->ops->transientvar;
824: if (ctx) *(void **)ctx = dmts->transientvarctx;
825: PetscFunctionReturn(PETSC_SUCCESS);
826: }
828: /*@C
829: DMTSGetSolutionFunction - gets the `TS` solution evaluation function
831: Not Collective
833: Input Parameter:
834: . dm - `DM` to be used with `TS`
836: Output Parameters:
837: + func - solution function evaluation function, for calling sequence see `TSSetSolution()`
838: - ctx - context for solution evaluation
840: Level: advanced
842: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSSetSolutionFunction()`
843: @*/
844: PetscErrorCode DMTSGetSolutionFunction(DM dm, TSSolutionFunction *func, void **ctx)
845: {
846: DMTS tsdm;
848: PetscFunctionBegin;
850: PetscCall(DMGetDMTS(dm, &tsdm));
851: if (func) *func = tsdm->ops->solution;
852: if (ctx) *ctx = tsdm->solutionctx;
853: PetscFunctionReturn(PETSC_SUCCESS);
854: }
856: /*@C
857: DMTSSetSolutionFunction - set `TS` solution evaluation function
859: Not Collective
861: Input Parameters:
862: + dm - `DM` to be used with `TS`
863: . func - solution function evaluation routine
864: - ctx - context for solution evaluation
866: Level: advanced
868: Note:
869: `TSSetSolutionFunction()` is normally used, but it calls this function internally because the user context is actually
870: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
871: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
873: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSGetSolutionFunction()`
874: @*/
875: PetscErrorCode DMTSSetSolutionFunction(DM dm, TSSolutionFunction func, void *ctx)
876: {
877: DMTS tsdm;
879: PetscFunctionBegin;
881: PetscCall(DMGetDMTSWrite(dm, &tsdm));
882: if (func) tsdm->ops->solution = func;
883: if (ctx) tsdm->solutionctx = ctx;
884: PetscFunctionReturn(PETSC_SUCCESS);
885: }
887: /*@C
888: DMTSSetForcingFunction - set `TS` forcing function evaluation function
890: Not Collective
892: Input Parameters:
893: + dm - `DM` to be used with `TS`
894: . func - forcing function evaluation routine
895: - ctx - context for solution evaluation
897: Level: advanced
899: Note:
900: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
901: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
902: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
904: .seealso: [](ch_ts), `DM`, `TS`, `TSForcingFunction`, `DMTSSetContext()`, `TSSetFunction()`,
905: `DMTSSetJacobian()`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
906: @*/
907: PetscErrorCode DMTSSetForcingFunction(DM dm, TSForcingFunction func, void *ctx)
908: {
909: DMTS tsdm;
911: PetscFunctionBegin;
913: PetscCall(DMGetDMTSWrite(dm, &tsdm));
914: if (func) tsdm->ops->forcing = func;
915: if (ctx) tsdm->forcingctx = ctx;
916: PetscFunctionReturn(PETSC_SUCCESS);
917: }
919: /*@C
920: DMTSGetForcingFunction - get `TS` forcing function evaluation function
922: Not Collective
924: Input Parameter:
925: . dm - `DM` to be used with `TS`
927: Output Parameters:
928: + f - forcing function evaluation function; see `TSForcingFunction` for details
929: - ctx - context for solution evaluation
931: Level: advanced
933: Note:
934: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
935: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
936: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
938: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `TSSetForcingFunction()`
939: @*/
940: PetscErrorCode DMTSGetForcingFunction(DM dm, TSForcingFunction *f, void **ctx)
941: {
942: DMTS tsdm;
944: PetscFunctionBegin;
946: PetscCall(DMGetDMTSWrite(dm, &tsdm));
947: if (f) *f = tsdm->ops->forcing;
948: if (ctx) *ctx = tsdm->forcingctx;
949: PetscFunctionReturn(PETSC_SUCCESS);
950: }
952: /*@C
953: DMTSGetRHSFunction - get `TS` explicit residual evaluation function
955: Not Collective
957: Input Parameter:
958: . dm - `DM` to be used with `TS`
960: Output Parameters:
961: + func - residual evaluation function, for calling sequence see `TSSetRHSFunction()`
962: - ctx - context for residual evaluation
964: Level: advanced
966: Note:
967: `TSGetFunction()` is normally used, but it calls this function internally because the user context is actually
968: associated with the DM.
970: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
971: @*/
972: PetscErrorCode DMTSGetRHSFunction(DM dm, TSRHSFunction *func, void **ctx)
973: {
974: DMTS tsdm;
976: PetscFunctionBegin;
978: PetscCall(DMGetDMTS(dm, &tsdm));
979: if (func) *func = tsdm->ops->rhsfunction;
980: if (ctx) {
981: if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsfunctionctxcontainer, ctx));
982: else *ctx = NULL;
983: }
984: PetscFunctionReturn(PETSC_SUCCESS);
985: }
987: /*@C
988: DMTSSetIJacobian - set `TS` Jacobian evaluation function
990: Not Collective
992: Input Parameters:
993: + dm - `DM` to be used with `TS`
994: . func - Jacobian evaluation routine
995: - ctx - context for residual evaluation
997: Level: advanced
999: Note:
1000: `TSSetJacobian()` is normally used, but it calls this function internally because the user context is actually
1001: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1002: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1004: .seealso: [](ch_ts), `TS`, `DM`, `TSIJacobian`, `DMTSSetContext()`, `TSSetRHSFunction()`,
1005: `DMTSGetJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()`
1006: @*/
1007: PetscErrorCode DMTSSetIJacobian(DM dm, TSIJacobian func, void *ctx)
1008: {
1009: DMTS tsdm;
1011: PetscFunctionBegin;
1013: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1014: if (func) tsdm->ops->ijacobian = func;
1015: if (ctx) {
1016: PetscContainer ctxcontainer;
1017: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1018: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1019: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ijacobian ctx", (PetscObject)ctxcontainer));
1020: tsdm->ijacobianctxcontainer = ctxcontainer;
1021: PetscCall(PetscContainerDestroy(&ctxcontainer));
1022: }
1023: PetscFunctionReturn(PETSC_SUCCESS);
1024: }
1026: /*@C
1027: DMTSSetIJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1029: Not Collective
1031: Input Parameters:
1032: + dm - `DM` to be used with `TS`
1033: - f - Jacobian evaluation context destroy function
1035: Level: advanced
1037: Note:
1038: `TSSetIJacobianContextDestroy()` is normally used, but it calls this function internally because the user context is actually
1039: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1040: not.
1042: Developer Notes:
1043: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1045: .seealso: [](ch_ts), `TSSetIJacobianContextDestroy()`, `TSSetI2JacobianContextDestroy()`, `DMTSSetIJacobian()`, `TSSetIJacobian()`
1046: @*/
1047: PetscErrorCode DMTSSetIJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1048: {
1049: DMTS tsdm;
1051: PetscFunctionBegin;
1053: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1054: if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->ijacobianctxcontainer, f));
1055: PetscFunctionReturn(PETSC_SUCCESS);
1056: }
1058: PetscErrorCode DMTSUnsetIJacobianContext_Internal(DM dm)
1059: {
1060: DMTS tsdm;
1062: PetscFunctionBegin;
1064: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1065: PetscCall(DMTSUnsetIJacobianContext_DMTS(tsdm));
1066: PetscFunctionReturn(PETSC_SUCCESS);
1067: }
1069: /*@C
1070: DMTSGetIJacobian - get `TS` Jacobian evaluation function
1072: Not Collective
1074: Input Parameter:
1075: . dm - `DM` to be used with `TS`
1077: Output Parameters:
1078: + func - Jacobian evaluation function, for calling sequence see `TSSetIJacobian()`
1079: - ctx - context for residual evaluation
1081: Level: advanced
1083: Note:
1084: `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1085: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1086: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1088: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1089: @*/
1090: PetscErrorCode DMTSGetIJacobian(DM dm, TSIJacobian *func, void **ctx)
1091: {
1092: DMTS tsdm;
1094: PetscFunctionBegin;
1096: PetscCall(DMGetDMTS(dm, &tsdm));
1097: if (func) *func = tsdm->ops->ijacobian;
1098: if (ctx) {
1099: if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ijacobianctxcontainer, ctx));
1100: else *ctx = NULL;
1101: }
1102: PetscFunctionReturn(PETSC_SUCCESS);
1103: }
1105: /*@C
1106: DMTSSetRHSJacobian - set `TS` Jacobian evaluation function
1108: Not Collective
1110: Input Parameters:
1111: + dm - `DM` to be used with `TS`
1112: . func - Jacobian evaluation routine
1113: - ctx - context for residual evaluation
1115: Level: advanced
1117: Note:
1118: `TSSetJacobian()` is normally used, but it calls this function internally because the user context is actually
1119: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1120: not.
1122: Developer Notes:
1123: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1125: .seealso: [](ch_ts), `TSRHSJacobian`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSGetJacobian()`, `TSSetRHSJacobian()`
1126: @*/
1127: PetscErrorCode DMTSSetRHSJacobian(DM dm, TSRHSJacobian func, void *ctx)
1128: {
1129: DMTS tsdm;
1131: PetscFunctionBegin;
1133: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1134: if (func) tsdm->ops->rhsjacobian = func;
1135: if (ctx) {
1136: PetscContainer ctxcontainer;
1137: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1138: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1139: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs jacobian ctx", (PetscObject)ctxcontainer));
1140: tsdm->rhsjacobianctxcontainer = ctxcontainer;
1141: PetscCall(PetscContainerDestroy(&ctxcontainer));
1142: }
1143: PetscFunctionReturn(PETSC_SUCCESS);
1144: }
1146: /*@C
1147: DMTSSetRHSJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1149: Not Collective
1151: Input Parameters:
1152: + dm - `DM` to be used with `TS`
1153: - f - Jacobian evaluation context destroy function
1155: Level: advanced
1157: Note:
1158: The user usually calls `TSSetRHSJacobianContextDestroy()` which calls this routine
1160: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobianContextDestroy()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1161: @*/
1162: PetscErrorCode DMTSSetRHSJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1163: {
1164: DMTS tsdm;
1166: PetscFunctionBegin;
1168: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1169: if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->rhsjacobianctxcontainer, f));
1170: PetscFunctionReturn(PETSC_SUCCESS);
1171: }
1173: PetscErrorCode DMTSUnsetRHSJacobianContext_Internal(DM dm)
1174: {
1175: DMTS tsdm;
1177: PetscFunctionBegin;
1179: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1180: PetscCall(DMTSUnsetRHSJacobianContext_DMTS(tsdm));
1181: PetscFunctionReturn(PETSC_SUCCESS);
1182: }
1184: /*@C
1185: DMTSGetRHSJacobian - get `TS` Jacobian evaluation function
1187: Not Collective
1189: Input Parameter:
1190: . dm - `DM` to be used with `TS`
1192: Output Parameters:
1193: + func - Jacobian evaluation function, for calling sequence see `TSSetRHSJacobian()`
1194: - ctx - context for residual evaluation
1196: Level: advanced
1198: Note:
1199: `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1200: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1201: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1203: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1204: @*/
1205: PetscErrorCode DMTSGetRHSJacobian(DM dm, TSRHSJacobian *func, void **ctx)
1206: {
1207: DMTS tsdm;
1209: PetscFunctionBegin;
1211: PetscCall(DMGetDMTS(dm, &tsdm));
1212: if (func) *func = tsdm->ops->rhsjacobian;
1213: if (ctx) {
1214: if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsjacobianctxcontainer, ctx));
1215: else *ctx = NULL;
1216: }
1217: PetscFunctionReturn(PETSC_SUCCESS);
1218: }
1220: /*@C
1221: DMTSSetIFunctionSerialize - sets functions used to view and load a IFunction context
1223: Not Collective
1225: Input Parameters:
1226: + dm - `DM` to be used with `TS`
1227: . view - viewer function
1228: - load - loading function
1230: Level: advanced
1232: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1233: @*/
1234: PetscErrorCode DMTSSetIFunctionSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1235: {
1236: DMTS tsdm;
1238: PetscFunctionBegin;
1240: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1241: tsdm->ops->ifunctionview = view;
1242: tsdm->ops->ifunctionload = load;
1243: PetscFunctionReturn(PETSC_SUCCESS);
1244: }
1246: /*@C
1247: DMTSSetIJacobianSerialize - sets functions used to view and load a IJacobian context
1249: Not Collective
1251: Input Parameters:
1252: + dm - `DM` to be used with `TS`
1253: . view - viewer function
1254: - load - loading function
1256: Level: advanced
1258: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1259: @*/
1260: PetscErrorCode DMTSSetIJacobianSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1261: {
1262: DMTS tsdm;
1264: PetscFunctionBegin;
1266: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1267: tsdm->ops->ijacobianview = view;
1268: tsdm->ops->ijacobianload = load;
1269: PetscFunctionReturn(PETSC_SUCCESS);
1270: }