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: PetscCtx 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: PetscCtx 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 isbinary;
100: PetscFunctionBegin;
101: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
102: if (isbinary) {
103: struct {
104: TSIFunctionFn *ifunction;
105: } funcstruct;
106: struct {
107: PetscErrorCode (*ifunctionview)(void *, PetscViewer);
108: } funcviewstruct;
109: struct {
110: PetscErrorCode (*ifunctionload)(void **, PetscViewer);
111: } funcloadstruct;
112: struct {
113: TSIJacobianFn *ijacobian;
114: } jacstruct;
115: struct {
116: PetscErrorCode (*ijacobianview)(void *, PetscViewer);
117: } jacviewstruct;
118: struct {
119: PetscErrorCode (*ijacobianload)(void **, PetscViewer);
120: } jacloadstruct;
122: funcstruct.ifunction = kdm->ops->ifunction;
123: funcviewstruct.ifunctionview = kdm->ops->ifunctionview;
124: funcloadstruct.ifunctionload = kdm->ops->ifunctionload;
125: PetscCall(PetscViewerBinaryWrite(viewer, &funcstruct, 1, PETSC_FUNCTION));
126: PetscCall(PetscViewerBinaryWrite(viewer, &funcviewstruct, 1, PETSC_FUNCTION));
127: PetscCall(PetscViewerBinaryWrite(viewer, &funcloadstruct, 1, PETSC_FUNCTION));
128: if (kdm->ops->ifunctionview) {
129: PetscCtx ctx;
131: PetscCall(PetscContainerGetPointer(kdm->ifunctionctxcontainer, &ctx));
132: PetscCall((*kdm->ops->ifunctionview)(ctx, viewer));
133: }
134: jacstruct.ijacobian = kdm->ops->ijacobian;
135: jacviewstruct.ijacobianview = kdm->ops->ijacobianview;
136: jacloadstruct.ijacobianload = kdm->ops->ijacobianload;
137: PetscCall(PetscViewerBinaryWrite(viewer, &jacstruct, 1, PETSC_FUNCTION));
138: PetscCall(PetscViewerBinaryWrite(viewer, &jacviewstruct, 1, PETSC_FUNCTION));
139: PetscCall(PetscViewerBinaryWrite(viewer, &jacloadstruct, 1, PETSC_FUNCTION));
140: if (kdm->ops->ijacobianview) {
141: PetscCtx ctx;
143: PetscCall(PetscContainerGetPointer(kdm->ijacobianctxcontainer, &ctx));
144: PetscCall((*kdm->ops->ijacobianview)(ctx, viewer));
145: }
146: }
147: PetscFunctionReturn(PETSC_SUCCESS);
148: }
150: static PetscErrorCode DMTSCreate(MPI_Comm comm, DMTS *kdm)
151: {
152: PetscFunctionBegin;
153: PetscCall(TSInitializePackage());
154: PetscCall(PetscHeaderCreate(*kdm, DMTS_CLASSID, "DMTS", "DMTS", "DMTS", comm, DMTSDestroy, DMTSView));
155: PetscFunctionReturn(PETSC_SUCCESS);
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, PetscCtx ctx)
162: {
163: PetscFunctionBegin;
164: PetscCall(DMCopyDMTS(dm, dmc));
165: PetscFunctionReturn(PETSC_SUCCESS);
166: }
168: /* This could restrict auxiliary information to the coarse level.
169: */
170: static PetscErrorCode DMRestrictHook_DMTS(DM dm, Mat Restrict, Vec rscale, Mat Inject, DM dmc, PetscCtx ctx)
171: {
172: PetscFunctionBegin;
173: PetscFunctionReturn(PETSC_SUCCESS);
174: }
176: static PetscErrorCode DMSubDomainHook_DMTS(DM dm, DM subdm, PetscCtx ctx)
177: {
178: PetscFunctionBegin;
179: PetscCall(DMCopyDMTS(dm, subdm));
180: PetscFunctionReturn(PETSC_SUCCESS);
181: }
183: /* This could restrict auxiliary information to the coarse level.
184: */
185: static PetscErrorCode DMSubDomainRestrictHook_DMTS(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, PetscCtx ctx)
186: {
187: PetscFunctionBegin;
188: PetscFunctionReturn(PETSC_SUCCESS);
189: }
191: /*@
192: DMTSCopy - copies the information in a `DMTS` to another `DMTS`
194: Not Collective
196: Input Parameters:
197: + kdm - Original `DMTS`
198: - nkdm - `DMTS` to receive the data, should have been created with `DMTSCreate()`
200: Level: developer
202: .seealso: [](ch_ts), `DMTSCreate()`, `DMTSDestroy()`
203: @*/
204: PetscErrorCode DMTSCopy(DMTS kdm, DMTS nkdm)
205: {
206: PetscFunctionBegin;
209: nkdm->ops->rhsfunction = kdm->ops->rhsfunction;
210: nkdm->ops->rhsjacobian = kdm->ops->rhsjacobian;
211: nkdm->ops->ifunction = kdm->ops->ifunction;
212: nkdm->ops->ijacobian = kdm->ops->ijacobian;
213: nkdm->ops->i2function = kdm->ops->i2function;
214: nkdm->ops->i2jacobian = kdm->ops->i2jacobian;
215: nkdm->ops->solution = kdm->ops->solution;
216: nkdm->ops->destroy = kdm->ops->destroy;
217: nkdm->ops->duplicate = kdm->ops->duplicate;
219: nkdm->solutionctx = kdm->solutionctx;
220: nkdm->rhsfunctionctxcontainer = kdm->rhsfunctionctxcontainer;
221: nkdm->rhsjacobianctxcontainer = kdm->rhsjacobianctxcontainer;
222: nkdm->ifunctionctxcontainer = kdm->ifunctionctxcontainer;
223: nkdm->ijacobianctxcontainer = kdm->ijacobianctxcontainer;
224: nkdm->i2functionctxcontainer = kdm->i2functionctxcontainer;
225: nkdm->i2jacobianctxcontainer = kdm->i2jacobianctxcontainer;
226: if (nkdm->rhsfunctionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "rhs function ctx", (PetscObject)nkdm->rhsfunctionctxcontainer));
227: if (nkdm->rhsjacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "rhs jacobian ctx", (PetscObject)nkdm->rhsjacobianctxcontainer));
228: if (nkdm->ifunctionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "ifunction ctx", (PetscObject)nkdm->ifunctionctxcontainer));
229: if (nkdm->ijacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "ijacobian ctx", (PetscObject)nkdm->ijacobianctxcontainer));
230: if (nkdm->i2functionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "i2function ctx", (PetscObject)nkdm->i2functionctxcontainer));
231: if (nkdm->i2jacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "i2jacobian ctx", (PetscObject)nkdm->i2jacobianctxcontainer));
233: nkdm->data = kdm->data;
235: /*
236: nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
237: nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
238: nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
239: */
241: /* implementation specific copy hooks */
242: PetscTryTypeMethod(kdm, duplicate, nkdm);
243: PetscFunctionReturn(PETSC_SUCCESS);
244: }
246: /*@
247: DMGetDMTS - get read-only private `DMTS` context from a `DM`
249: Not Collective
251: Input Parameter:
252: . dm - `DM` to be used with `TS`
254: Output Parameter:
255: . tsdm - private `DMTS` context
257: Level: developer
259: Notes:
260: Use `DMGetDMTSWrite()` if write access is needed. The `DMTSSetXXX()` API should be used wherever possible.
262: .seealso: [](ch_ts), `DMTS`, `DMGetDMTSWrite()`
263: @*/
264: PetscErrorCode DMGetDMTS(DM dm, DMTS *tsdm)
265: {
266: PetscFunctionBegin;
268: *tsdm = (DMTS)dm->dmts;
269: if (!*tsdm) {
270: PetscCall(PetscInfo(dm, "Creating new DMTS\n"));
271: PetscCall(DMTSCreate(PetscObjectComm((PetscObject)dm), tsdm));
272: dm->dmts = (PetscObject)*tsdm;
273: (*tsdm)->originaldm = dm;
274: PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_DMTS, DMRestrictHook_DMTS, NULL));
275: PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_DMTS, DMSubDomainRestrictHook_DMTS, NULL));
276: }
277: PetscFunctionReturn(PETSC_SUCCESS);
278: }
280: /*@
281: DMGetDMTSWrite - get write access to private `DMTS` context from a `DM`
283: Not Collective
285: Input Parameter:
286: . dm - `DM` to be used with `TS`
288: Output Parameter:
289: . tsdm - private `DMTS` context
291: Level: developer
293: .seealso: [](ch_ts), `DMTS`, `DMGetDMTS()`
294: @*/
295: PetscErrorCode DMGetDMTSWrite(DM dm, DMTS *tsdm)
296: {
297: DMTS sdm;
299: PetscFunctionBegin;
301: PetscCall(DMGetDMTS(dm, &sdm));
302: PetscCheck(sdm->originaldm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DMTS has a NULL originaldm");
303: if (sdm->originaldm != dm) { /* Copy on write */
304: DMTS oldsdm = sdm;
305: PetscCall(PetscInfo(dm, "Copying DMTS due to write\n"));
306: PetscCall(DMTSCreate(PetscObjectComm((PetscObject)dm), &sdm));
307: PetscCall(DMTSCopy(oldsdm, sdm));
308: PetscCall(DMTSDestroy((DMTS *)&dm->dmts));
309: dm->dmts = (PetscObject)sdm;
310: sdm->originaldm = dm;
311: }
312: *tsdm = sdm;
313: PetscFunctionReturn(PETSC_SUCCESS);
314: }
316: /*@
317: DMCopyDMTS - copies a `DMTS` context to a new `DM`
319: Logically Collective
321: Input Parameters:
322: + dmsrc - `DM` to obtain context from
323: - dmdest - `DM` to add context to
325: Level: developer
327: Note:
328: The context is copied by reference. This function does not ensure that a context exists.
330: .seealso: [](ch_ts), `DMTS`, `DMGetDMTS()`, `TSSetDM()`
331: @*/
332: PetscErrorCode DMCopyDMTS(DM dmsrc, DM dmdest)
333: {
334: PetscFunctionBegin;
337: PetscCall(DMTSDestroy((DMTS *)&dmdest->dmts));
338: dmdest->dmts = dmsrc->dmts;
339: PetscCall(PetscObjectReference(dmdest->dmts));
340: PetscCall(DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMTS, DMRestrictHook_DMTS, NULL));
341: PetscCall(DMSubDomainHookAdd(dmdest, DMSubDomainHook_DMTS, DMSubDomainRestrictHook_DMTS, NULL));
342: PetscFunctionReturn(PETSC_SUCCESS);
343: }
345: /*@
346: DMTSSetIFunction - set `TS` implicit function evaluation function into a `DMTS`
348: Not Collective
350: Input Parameters:
351: + dm - `DM` to be used with `TS`
352: . func - function evaluating f(t,u,u_t)
353: - ctx - context for residual evaluation
355: Level: developer
357: Note:
358: `TSSetIFunction()` is normally used, but it calls this function internally because the application context is actually
359: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
360: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
362: .seealso: [](ch_ts), `DMTS`, `TS`, `DM`, `TSIFunctionFn`
363: @*/
364: PetscErrorCode DMTSSetIFunction(DM dm, TSIFunctionFn *func, PetscCtx ctx)
365: {
366: DMTS tsdm;
368: PetscFunctionBegin;
370: PetscCall(DMGetDMTSWrite(dm, &tsdm));
371: if (func) tsdm->ops->ifunction = func;
372: if (ctx) {
373: PetscContainer ctxcontainer;
374: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
375: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
376: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ifunction ctx", (PetscObject)ctxcontainer));
377: tsdm->ifunctionctxcontainer = ctxcontainer;
378: PetscCall(PetscContainerDestroy(&ctxcontainer));
379: }
380: PetscFunctionReturn(PETSC_SUCCESS);
381: }
383: /*@
384: DMTSSetIFunctionContextDestroy - set `TS` implicit evaluation context destroy function into a `DMTS`
386: Not Collective
388: Input Parameters:
389: + dm - `DM` to be used with `TS`
390: - f - implicit evaluation context destroy function, see `PetscCtxDestroyFn` for its calling sequence
392: Level: developer
394: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `DMTSSetIFunction()`, `TSSetIFunction()`, `PetscCtxDestroyFn`
395: @*/
396: PetscErrorCode DMTSSetIFunctionContextDestroy(DM dm, PetscCtxDestroyFn *f)
397: {
398: DMTS tsdm;
400: PetscFunctionBegin;
402: PetscCall(DMGetDMTSWrite(dm, &tsdm));
403: if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerSetCtxDestroy(tsdm->ifunctionctxcontainer, f));
404: PetscFunctionReturn(PETSC_SUCCESS);
405: }
407: PetscErrorCode DMTSUnsetIFunctionContext_Internal(DM dm)
408: {
409: DMTS tsdm;
411: PetscFunctionBegin;
413: PetscCall(DMGetDMTSWrite(dm, &tsdm));
414: PetscCall(DMTSUnsetIFunctionContext_DMTS(tsdm));
415: PetscFunctionReturn(PETSC_SUCCESS);
416: }
418: /*@
419: DMTSGetIFunction - get `TS` implicit residual evaluation function from a `DMTS`
421: Not Collective
423: Input Parameter:
424: . dm - `DM` to be used with `TS`
426: Output Parameters:
427: + func - function evaluation function, for calling sequence see `TSIFunctionFn`
428: - ctx - context for residual evaluation
430: Level: developer
432: Note:
433: `TSGetIFunction()` is normally used, but it calls this function internally because the application context is actually
434: associated with the `DM`.
436: .seealso: [](ch_ts), `DMTS`, `TS`, `DM`, `DMTSSetIFunction()`, `TSIFunctionFn`
437: @*/
438: PetscErrorCode DMTSGetIFunction(DM dm, TSIFunctionFn **func, PetscCtxRt ctx)
439: {
440: DMTS tsdm;
442: PetscFunctionBegin;
444: PetscCall(DMGetDMTS(dm, &tsdm));
445: if (func) *func = tsdm->ops->ifunction;
446: if (ctx) {
447: if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ifunctionctxcontainer, ctx));
448: else *(void **)ctx = NULL;
449: }
450: PetscFunctionReturn(PETSC_SUCCESS);
451: }
453: /*@
454: DMTSSetI2Function - set `TS` implicit function evaluation function for 2nd order systems into a `TSDM`
456: Not Collective
458: Input Parameters:
459: + dm - `DM` to be used with `TS`
460: . fun - function evaluation routine
461: - ctx - context for residual evaluation
463: Level: developer
465: Note:
466: `TSSetI2Function()` is normally used, but it calls this function internally because the application context is actually
467: associated with the `DM`.
469: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `TSSetI2Function()`
470: @*/
471: PetscErrorCode DMTSSetI2Function(DM dm, TSI2FunctionFn *fun, PetscCtx ctx)
472: {
473: DMTS tsdm;
475: PetscFunctionBegin;
477: PetscCall(DMGetDMTSWrite(dm, &tsdm));
478: if (fun) tsdm->ops->i2function = fun;
479: if (ctx) {
480: PetscContainer ctxcontainer;
481: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
482: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
483: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2function ctx", (PetscObject)ctxcontainer));
484: tsdm->i2functionctxcontainer = ctxcontainer;
485: PetscCall(PetscContainerDestroy(&ctxcontainer));
486: }
487: PetscFunctionReturn(PETSC_SUCCESS);
488: }
490: /*@
491: DMTSSetI2FunctionContextDestroy - set `TS` implicit evaluation for 2nd order systems context destroy into a `DMTS`
493: Not Collective
495: Input Parameters:
496: + dm - `DM` to be used with `TS`
497: - f - implicit evaluation context destroy function, see `PetscCtxDestroyFn` for its calling sequence
499: Level: developer
501: Note:
502: `TSSetI2FunctionContextDestroy()` is normally used, but it calls this function internally because the application context is actually
503: associated with the `DM`.
505: .seealso: [](ch_ts), `DMTS`, `TSSetI2FunctionContextDestroy()`, `DMTSSetI2Function()`, `TSSetI2Function()`
506: @*/
507: PetscErrorCode DMTSSetI2FunctionContextDestroy(DM dm, PetscCtxDestroyFn *f)
508: {
509: DMTS tsdm;
511: PetscFunctionBegin;
513: PetscCall(DMGetDMTSWrite(dm, &tsdm));
514: if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerSetCtxDestroy(tsdm->i2functionctxcontainer, f));
515: PetscFunctionReturn(PETSC_SUCCESS);
516: }
518: PetscErrorCode DMTSUnsetI2FunctionContext_Internal(DM dm)
519: {
520: DMTS tsdm;
522: PetscFunctionBegin;
524: PetscCall(DMGetDMTSWrite(dm, &tsdm));
525: PetscCall(DMTSUnsetI2FunctionContext_DMTS(tsdm));
526: PetscFunctionReturn(PETSC_SUCCESS);
527: }
529: /*@
530: DMTSGetI2Function - get `TS` implicit residual evaluation function for 2nd order systems from a `DMTS`
532: Not Collective
534: Input Parameter:
535: . dm - `DM` to be used with `TS`
537: Output Parameters:
538: + fun - function evaluation function, for calling sequence see `TSSetI2Function()`
539: - ctx - context for residual evaluation
541: Level: developer
543: Note:
544: `TSGetI2Function()` is normally used, but it calls this function internally because the application context is actually
545: associated with the `DM`.
547: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `DMTSSetI2Function()`, `TSGetI2Function()`
548: @*/
549: PetscErrorCode DMTSGetI2Function(DM dm, TSI2FunctionFn **fun, PetscCtxRt ctx)
550: {
551: DMTS tsdm;
553: PetscFunctionBegin;
555: PetscCall(DMGetDMTS(dm, &tsdm));
556: if (fun) *fun = tsdm->ops->i2function;
557: if (ctx) {
558: if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2functionctxcontainer, ctx));
559: else *(void **)ctx = NULL;
560: }
561: PetscFunctionReturn(PETSC_SUCCESS);
562: }
564: /*@
565: DMTSSetI2Jacobian - set `TS` implicit Jacobian evaluation function for 2nd order systems from a `DMTS`
567: Not Collective
569: Input Parameters:
570: + dm - `DM` to be used with `TS`
571: . jac - Jacobian evaluation routine
572: - ctx - context for Jacobian evaluation
574: Level: developer
576: Note:
577: `TSSetI2Jacobian()` is normally used, but it calls this function internally because the application context is actually
578: associated with the `DM`.
580: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `TSI2JacobianFn`, `TSSetI2Jacobian()`
581: @*/
582: PetscErrorCode DMTSSetI2Jacobian(DM dm, TSI2JacobianFn *jac, PetscCtx ctx)
583: {
584: DMTS tsdm;
586: PetscFunctionBegin;
588: PetscCall(DMGetDMTSWrite(dm, &tsdm));
589: if (jac) tsdm->ops->i2jacobian = jac;
590: if (ctx) {
591: PetscContainer ctxcontainer;
592: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
593: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
594: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2jacobian ctx", (PetscObject)ctxcontainer));
595: tsdm->i2jacobianctxcontainer = ctxcontainer;
596: PetscCall(PetscContainerDestroy(&ctxcontainer));
597: }
598: PetscFunctionReturn(PETSC_SUCCESS);
599: }
601: /*@
602: DMTSSetI2JacobianContextDestroy - set `TS` implicit Jacobian evaluation for 2nd order systems context destroy function into a `DMTS`
604: Not Collective
606: Input Parameters:
607: + dm - `DM` to be used with `TS`
608: - f - implicit Jacobian evaluation context destroy function, see `PetscCtxDestroyFn` for its calling sequence
610: Level: developer
612: Note:
613: Normally `TSSetI2JacobianContextDestroy()` is used
615: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `TSSetI2JacobianContextDestroy()`, `DMTSSetI2Jacobian()`, `TSSetI2Jacobian()`
616: @*/
617: PetscErrorCode DMTSSetI2JacobianContextDestroy(DM dm, PetscCtxDestroyFn *f)
618: {
619: DMTS tsdm;
621: PetscFunctionBegin;
623: PetscCall(DMGetDMTSWrite(dm, &tsdm));
624: if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerSetCtxDestroy(tsdm->i2jacobianctxcontainer, f));
625: PetscFunctionReturn(PETSC_SUCCESS);
626: }
628: PetscErrorCode DMTSUnsetI2JacobianContext_Internal(DM dm)
629: {
630: DMTS tsdm;
632: PetscFunctionBegin;
634: PetscCall(DMGetDMTSWrite(dm, &tsdm));
635: PetscCall(DMTSUnsetI2JacobianContext_DMTS(tsdm));
636: PetscFunctionReturn(PETSC_SUCCESS);
637: }
639: /*@
640: DMTSGetI2Jacobian - get `TS` implicit Jacobian evaluation function for 2nd order systems from a `DMTS`
642: Not Collective
644: Input Parameter:
645: . dm - `DM` to be used with `TS`
647: Output Parameters:
648: + jac - Jacobian evaluation function, for calling sequence see `TSI2JacobianFn`
649: - ctx - context for Jacobian evaluation
651: Level: developer
653: Note:
654: `TSGetI2Jacobian()` is normally used, but it calls this function internally because the application context is actually
655: associated with the `DM`.
657: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `DMTSSetI2Jacobian()`, `TSGetI2Jacobian()`, `TSI2JacobianFn`
658: @*/
659: PetscErrorCode DMTSGetI2Jacobian(DM dm, TSI2JacobianFn **jac, PetscCtxRt ctx)
660: {
661: DMTS tsdm;
663: PetscFunctionBegin;
665: PetscCall(DMGetDMTS(dm, &tsdm));
666: if (jac) *jac = tsdm->ops->i2jacobian;
667: if (ctx) {
668: if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2jacobianctxcontainer, ctx));
669: else *(void **)ctx = NULL;
670: }
671: PetscFunctionReturn(PETSC_SUCCESS);
672: }
674: /*@
675: DMTSSetRHSFunction - set `TS` explicit residual evaluation function into a `DMTS`
677: Not Collective
679: Input Parameters:
680: + dm - `DM` to be used with `TS`
681: . func - RHS function evaluation routine, see `TSRHSFunctionFn` for the calling sequence
682: - ctx - context for residual evaluation
684: Level: developer
686: Note:
687: `TSSetRHSFunction()` is normally used, but it calls this function internally because the application context is actually
688: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
689: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
691: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `TSRHSFunctionFn`
692: @*/
693: PetscErrorCode DMTSSetRHSFunction(DM dm, TSRHSFunctionFn *func, PetscCtx ctx)
694: {
695: DMTS tsdm;
697: PetscFunctionBegin;
699: PetscCall(DMGetDMTSWrite(dm, &tsdm));
700: if (func) tsdm->ops->rhsfunction = func;
701: if (ctx) {
702: PetscContainer ctxcontainer;
703: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
704: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
705: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", (PetscObject)ctxcontainer));
706: tsdm->rhsfunctionctxcontainer = ctxcontainer;
707: PetscCall(PetscContainerDestroy(&ctxcontainer));
708: }
709: PetscFunctionReturn(PETSC_SUCCESS);
710: }
712: /*@
713: DMTSSetRHSFunctionContextDestroy - set `TS` explicit residual evaluation context destroy function into a `DMTS`
715: Not Collective
717: Input Parameters:
718: + dm - `DM` to be used with `TS`
719: - f - explicit evaluation context destroy function, see `PetscCtxDestroyFn` for its calling sequence
721: Level: developer
723: Note:
724: `TSSetRHSFunctionContextDestroy()` is normally used, but it calls this function internally because the application context is actually
725: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
726: not.
728: Developer Notes:
729: If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
731: .seealso: [](ch_ts), `DMTS`, `TSSetRHSFunctionContextDestroy()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
732: @*/
733: PetscErrorCode DMTSSetRHSFunctionContextDestroy(DM dm, PetscCtxDestroyFn *f)
734: {
735: DMTS tsdm;
737: PetscFunctionBegin;
739: PetscCall(DMGetDMTSWrite(dm, &tsdm));
740: if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerSetCtxDestroy(tsdm->rhsfunctionctxcontainer, f));
741: PetscFunctionReturn(PETSC_SUCCESS);
742: }
744: PetscErrorCode DMTSUnsetRHSFunctionContext_Internal(DM dm)
745: {
746: DMTS tsdm;
748: PetscFunctionBegin;
750: PetscCall(DMGetDMTSWrite(dm, &tsdm));
751: PetscCall(DMTSUnsetRHSFunctionContext_DMTS(tsdm));
752: tsdm->rhsfunctionctxcontainer = NULL;
753: PetscFunctionReturn(PETSC_SUCCESS);
754: }
756: /*@
757: DMTSSetTransientVariable - sets function to transform from state to transient variables into a `DMTS`
759: Logically Collective
761: Input Parameters:
762: + dm - `DM` to be used with `TS`
763: . tvar - a function that transforms to transient variables, see `TSTransientVariableFn` for the calling sequence
764: - ctx - a context for tvar
766: Level: developer
768: Notes:
769: Normally `TSSetTransientVariable()` is used
771: This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
772: can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to
773: well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is
774: C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
775: evaluated via the chain rule, as in
777: $$
778: dF/dP + shift dF/dCdot dC/dP.
779: $$
781: .seealso: [](ch_ts), `DMTS`, `TS`, `TSBDF`, `TSSetTransientVariable()`, `DMTSGetTransientVariable()`, `DMTSSetIFunction()`, `DMTSSetIJacobian()`, `TSTransientVariableFn`
782: @*/
783: PetscErrorCode DMTSSetTransientVariable(DM dm, TSTransientVariableFn *tvar, PetscCtx ctx)
784: {
785: DMTS dmts;
787: PetscFunctionBegin;
789: PetscCall(DMGetDMTSWrite(dm, &dmts));
790: dmts->ops->transientvar = tvar;
791: dmts->transientvarctx = ctx;
792: PetscFunctionReturn(PETSC_SUCCESS);
793: }
795: /*@
796: DMTSGetTransientVariable - gets function to transform from state to transient variables set with `DMTSSetTransientVariable()` from a `TSDM`
798: Logically Collective
800: Input Parameter:
801: . dm - `DM` to be used with `TS`
803: Output Parameters:
804: + tvar - a function that transforms to transient variables, see `TSTransientVariableFn` for the calling sequence
805: - ctx - a context for tvar
807: Level: developer
809: Note:
810: Normally `TSSetTransientVariable()` is used
812: .seealso: [](ch_ts), `DMTS`, `DM`, `DMTSSetTransientVariable()`, `DMTSGetIFunction()`, `DMTSGetIJacobian()`, `TSTransientVariableFn`
813: @*/
814: PetscErrorCode DMTSGetTransientVariable(DM dm, TSTransientVariableFn **tvar, PetscCtx ctx)
815: {
816: DMTS dmts;
818: PetscFunctionBegin;
820: PetscCall(DMGetDMTS(dm, &dmts));
821: if (tvar) *tvar = dmts->ops->transientvar;
822: if (ctx) *(void **)ctx = dmts->transientvarctx;
823: PetscFunctionReturn(PETSC_SUCCESS);
824: }
826: /*@
827: DMTSGetSolutionFunction - gets the `TS` solution evaluation function from a `DMTS`
829: Not Collective
831: Input Parameter:
832: . dm - `DM` to be used with `TS`
834: Output Parameters:
835: + func - solution function evaluation function, for calling sequence see `TSSolutionFn`
836: - ctx - context for solution evaluation
838: Level: developer
840: .seealso: [](ch_ts), `DMTS`, `TS`, `DM`, `DMTSSetSolutionFunction()`, `TSSolutionFn`
841: @*/
842: PetscErrorCode DMTSGetSolutionFunction(DM dm, TSSolutionFn **func, PetscCtxRt ctx)
843: {
844: DMTS tsdm;
846: PetscFunctionBegin;
848: PetscCall(DMGetDMTS(dm, &tsdm));
849: if (func) *func = tsdm->ops->solution;
850: if (ctx) *(void **)ctx = tsdm->solutionctx;
851: PetscFunctionReturn(PETSC_SUCCESS);
852: }
854: /*@
855: DMTSSetSolutionFunction - set `TS` solution evaluation function into a `DMTS`
857: Not Collective
859: Input Parameters:
860: + dm - `DM` to be used with `TS`
861: . func - solution function evaluation routine, for calling sequence see `TSSolutionFn`
862: - ctx - context for solution evaluation
864: Level: developer
866: Note:
867: `TSSetSolutionFunction()` is normally used, but it calls this function internally because the application context is actually
868: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
869: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
871: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `DMTSGetSolutionFunction()`, `TSSolutionFn`
872: @*/
873: PetscErrorCode DMTSSetSolutionFunction(DM dm, TSSolutionFn *func, PetscCtx ctx)
874: {
875: DMTS tsdm;
877: PetscFunctionBegin;
879: PetscCall(DMGetDMTSWrite(dm, &tsdm));
880: if (func) tsdm->ops->solution = func;
881: if (ctx) tsdm->solutionctx = ctx;
882: PetscFunctionReturn(PETSC_SUCCESS);
883: }
885: /*@
886: DMTSSetForcingFunction - set `TS` forcing function evaluation function into a `DMTS`
888: Not Collective
890: Input Parameters:
891: + dm - `DM` to be used with `TS`
892: . func - forcing function evaluation routine, for calling sequence see `TSForcingFn`
893: - ctx - context for solution evaluation
895: Level: developer
897: Note:
898: `TSSetForcingFunction()` is normally used, but it calls this function internally because the application context is actually
899: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
900: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
902: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `TSForcingFn`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
903: @*/
904: PetscErrorCode DMTSSetForcingFunction(DM dm, TSForcingFn *func, PetscCtx ctx)
905: {
906: DMTS tsdm;
908: PetscFunctionBegin;
910: PetscCall(DMGetDMTSWrite(dm, &tsdm));
911: if (func) tsdm->ops->forcing = func;
912: if (ctx) tsdm->forcingctx = ctx;
913: PetscFunctionReturn(PETSC_SUCCESS);
914: }
916: /*@
917: DMTSGetForcingFunction - get `TS` forcing function evaluation function from a `DMTS`
919: Not Collective
921: Input Parameter:
922: . dm - `DM` to be used with `TS`
924: Output Parameters:
925: + f - forcing function evaluation function; see `TSForcingFn` for the calling sequence
926: - ctx - context for solution evaluation
928: Level: developer
930: Note:
931: `TSSetForcingFunction()` is normally used, but it calls this function internally because the application context is actually
932: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
933: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
935: .seealso: [](ch_ts), `DMTS`, `TS`, `DM`, `TSSetForcingFunction()`, `TSForcingFn`
936: @*/
937: PetscErrorCode DMTSGetForcingFunction(DM dm, TSForcingFn **f, PetscCtxRt ctx)
938: {
939: DMTS tsdm;
941: PetscFunctionBegin;
943: PetscCall(DMGetDMTSWrite(dm, &tsdm));
944: if (f) *f = tsdm->ops->forcing;
945: if (ctx) *(void **)ctx = tsdm->forcingctx;
946: PetscFunctionReturn(PETSC_SUCCESS);
947: }
949: /*@
950: DMTSGetRHSFunction - get `TS` explicit residual evaluation function from a `DMTS`
952: Not Collective
954: Input Parameter:
955: . dm - `DM` to be used with `TS`
957: Output Parameters:
958: + func - residual evaluation function, for calling sequence see `TSRHSFunctionFn`
959: - ctx - context for residual evaluation
961: Level: developer
963: Note:
964: `TSGetRHSFunction()` is normally used, but it calls this function internally because the application context is actually
965: associated with the DM.
967: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `TSRHSFunctionFn`, `TSGetRHSFunction()`
968: @*/
969: PetscErrorCode DMTSGetRHSFunction(DM dm, TSRHSFunctionFn **func, PetscCtxRt ctx)
970: {
971: DMTS tsdm;
973: PetscFunctionBegin;
975: PetscCall(DMGetDMTS(dm, &tsdm));
976: if (func) *func = tsdm->ops->rhsfunction;
977: if (ctx) {
978: if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsfunctionctxcontainer, ctx));
979: else *(void **)ctx = NULL;
980: }
981: PetscFunctionReturn(PETSC_SUCCESS);
982: }
984: /*@
985: DMTSSetIJacobian - set `TS` Jacobian evaluation function into a `DMTS`
987: Not Collective
989: Input Parameters:
990: + dm - `DM` to be used with `TS`
991: . func - Jacobian evaluation routine, see `TSIJacobianFn` for the calling sequence
992: - ctx - context for residual evaluation
994: Level: developer
996: Note:
997: `TSSetIJacobian()` is normally used, but it calls this function internally because the application context is actually
998: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
999: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1001: .seealso: [](ch_ts), `DMTS`, `TS`, `DM`, `TSIJacobianFn`, `DMTSGetIJacobian()`, `TSSetIJacobian()`
1002: @*/
1003: PetscErrorCode DMTSSetIJacobian(DM dm, TSIJacobianFn *func, PetscCtx ctx)
1004: {
1005: DMTS tsdm;
1007: PetscFunctionBegin;
1009: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1010: if (func) tsdm->ops->ijacobian = func;
1011: if (ctx) {
1012: PetscContainer ctxcontainer;
1013: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1014: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1015: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ijacobian ctx", (PetscObject)ctxcontainer));
1016: tsdm->ijacobianctxcontainer = ctxcontainer;
1017: PetscCall(PetscContainerDestroy(&ctxcontainer));
1018: }
1019: PetscFunctionReturn(PETSC_SUCCESS);
1020: }
1022: /*@
1023: DMTSSetIJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function into a `DMTS`
1025: Not Collective
1027: Input Parameters:
1028: + dm - `DM` to be used with `TS`
1029: - f - Jacobian evaluation context destroy function, see `PetscCtxDestroyFn` for its calling sequence
1031: Level: developer
1033: Note:
1034: `TSSetIJacobianContextDestroy()` is normally used, but it calls this function internally because the application context is actually
1035: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1036: not.
1038: Developer Notes:
1039: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1041: .seealso: [](ch_ts), `DMTS`, `TSSetIJacobianContextDestroy()`, `TSSetI2JacobianContextDestroy()`, `DMTSSetIJacobian()`, `TSSetIJacobian()`
1042: @*/
1043: PetscErrorCode DMTSSetIJacobianContextDestroy(DM dm, PetscCtxDestroyFn *f)
1044: {
1045: DMTS tsdm;
1047: PetscFunctionBegin;
1049: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1050: if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerSetCtxDestroy(tsdm->ijacobianctxcontainer, f));
1051: PetscFunctionReturn(PETSC_SUCCESS);
1052: }
1054: PetscErrorCode DMTSUnsetIJacobianContext_Internal(DM dm)
1055: {
1056: DMTS tsdm;
1058: PetscFunctionBegin;
1060: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1061: PetscCall(DMTSUnsetIJacobianContext_DMTS(tsdm));
1062: PetscFunctionReturn(PETSC_SUCCESS);
1063: }
1065: /*@
1066: DMTSGetIJacobian - get `TS` Jacobian evaluation function from a `DMTS`
1068: Not Collective
1070: Input Parameter:
1071: . dm - `DM` to be used with `TS`
1073: Output Parameters:
1074: + func - Jacobian evaluation function, for calling sequence see `TSIJacobianFn`
1075: - ctx - context for residual evaluation
1077: Level: developer
1079: Note:
1080: `TSGetIJacobian()` is normally used, but it calls this function internally because the application context is actually
1081: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1082: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1084: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `DMTSSetIJacobian()`, `TSIJacobianFn`
1085: @*/
1086: PetscErrorCode DMTSGetIJacobian(DM dm, TSIJacobianFn **func, PetscCtxRt ctx)
1087: {
1088: DMTS tsdm;
1090: PetscFunctionBegin;
1092: PetscCall(DMGetDMTS(dm, &tsdm));
1093: if (func) *func = tsdm->ops->ijacobian;
1094: if (ctx) {
1095: if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ijacobianctxcontainer, ctx));
1096: else *(void **)ctx = NULL;
1097: }
1098: PetscFunctionReturn(PETSC_SUCCESS);
1099: }
1101: /*@
1102: DMTSSetRHSJacobian - set `TS` Jacobian evaluation function into a `DMTS`
1104: Not Collective
1106: Input Parameters:
1107: + dm - `DM` to be used with `TS`
1108: . func - Jacobian evaluation routine, for calling sequence see `TSIJacobianFn`
1109: - ctx - context for residual evaluation
1111: Level: developer
1113: Note:
1114: `TSSetRHSJacobian()` is normally used, but it calls this function internally because the application context is actually
1115: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1116: not.
1118: Developer Notes:
1119: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1121: .seealso: [](ch_ts), `DMTS`, `TSRHSJacobianFn`, `DMTSGetRHSJacobian()`, `TSSetRHSJacobian()`
1122: @*/
1123: PetscErrorCode DMTSSetRHSJacobian(DM dm, TSRHSJacobianFn *func, PetscCtx ctx)
1124: {
1125: DMTS tsdm;
1127: PetscFunctionBegin;
1129: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1130: if (func) tsdm->ops->rhsjacobian = func;
1131: if (ctx) {
1132: PetscContainer ctxcontainer;
1133: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1134: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1135: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs jacobian ctx", (PetscObject)ctxcontainer));
1136: tsdm->rhsjacobianctxcontainer = ctxcontainer;
1137: PetscCall(PetscContainerDestroy(&ctxcontainer));
1138: }
1139: PetscFunctionReturn(PETSC_SUCCESS);
1140: }
1142: /*@
1143: DMTSSetRHSJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function from a `DMTS`
1145: Not Collective
1147: Input Parameters:
1148: + dm - `DM` to be used with `TS`
1149: - f - Jacobian evaluation context destroy function, see `PetscCtxDestroyFn` for its calling sequence
1151: Level: developer
1153: Note:
1154: The user usually calls `TSSetRHSJacobianContextDestroy()` which calls this routine
1156: .seealso: [](ch_ts), `DMTS`, `TS`, `TSSetRHSJacobianContextDestroy()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1157: @*/
1158: PetscErrorCode DMTSSetRHSJacobianContextDestroy(DM dm, PetscCtxDestroyFn *f)
1159: {
1160: DMTS tsdm;
1162: PetscFunctionBegin;
1164: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1165: if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerSetCtxDestroy(tsdm->rhsjacobianctxcontainer, f));
1166: PetscFunctionReturn(PETSC_SUCCESS);
1167: }
1169: PetscErrorCode DMTSUnsetRHSJacobianContext_Internal(DM dm)
1170: {
1171: DMTS tsdm;
1173: PetscFunctionBegin;
1175: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1176: PetscCall(DMTSUnsetRHSJacobianContext_DMTS(tsdm));
1177: PetscFunctionReturn(PETSC_SUCCESS);
1178: }
1180: /*@
1181: DMTSGetRHSJacobian - get `TS` Jacobian evaluation function from a `DMTS`
1183: Not Collective
1185: Input Parameter:
1186: . dm - `DM` to be used with `TS`
1188: Output Parameters:
1189: + func - Jacobian evaluation function, for calling sequence see `TSRHSJacobianFn`
1190: - ctx - context for residual evaluation
1192: Level: developer
1194: Note:
1195: `TSGetRHSJacobian()` is normally used, but it calls this function internally because the application context is actually
1196: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1197: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1199: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`, `DMTSSetRHSJacobian()`, `TSRHSJacobianFn`
1200: @*/
1201: PetscErrorCode DMTSGetRHSJacobian(DM dm, TSRHSJacobianFn **func, PetscCtxRt ctx)
1202: {
1203: DMTS tsdm;
1205: PetscFunctionBegin;
1207: PetscCall(DMGetDMTS(dm, &tsdm));
1208: if (func) *func = tsdm->ops->rhsjacobian;
1209: if (ctx) {
1210: if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsjacobianctxcontainer, ctx));
1211: else *(void **)ctx = NULL;
1212: }
1213: PetscFunctionReturn(PETSC_SUCCESS);
1214: }
1216: /*@
1217: DMTSSetIFunctionSerialize - sets functions used to view and load a `TSIFunctionFn` context
1219: Not Collective
1221: Input Parameters:
1222: + dm - `DM` to be used with `TS`
1223: . view - viewer function
1224: - load - loading function
1226: Level: developer
1228: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`
1229: @*/
1230: PetscErrorCode DMTSSetIFunctionSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1231: {
1232: DMTS tsdm;
1234: PetscFunctionBegin;
1236: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1237: tsdm->ops->ifunctionview = view;
1238: tsdm->ops->ifunctionload = load;
1239: PetscFunctionReturn(PETSC_SUCCESS);
1240: }
1242: /*@
1243: DMTSSetIJacobianSerialize - sets functions used to view and load a `TSIJacobianFn` context
1245: Not Collective
1247: Input Parameters:
1248: + dm - `DM` to be used with `TS`
1249: . view - viewer function
1250: - load - loading function
1252: Level: developer
1254: .seealso: [](ch_ts), `DMTS`, `DM`, `TS`
1255: @*/
1256: PetscErrorCode DMTSSetIJacobianSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1257: {
1258: DMTS tsdm;
1260: PetscFunctionBegin;
1262: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1263: tsdm->ops->ijacobianview = view;
1264: tsdm->ops->ijacobianload = load;
1265: PetscFunctionReturn(PETSC_SUCCESS);
1266: }