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: `TSSetIFunction()` 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`
373: @*/
374: PetscErrorCode DMTSSetIFunction(DM dm, TSIFunction func, void *ctx)
375: {
376: DMTS tsdm;
378: PetscFunctionBegin;
380: PetscCall(DMGetDMTSWrite(dm, &tsdm));
381: if (func) tsdm->ops->ifunction = func;
382: if (ctx) {
383: PetscContainer ctxcontainer;
384: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
385: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
386: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ifunction ctx", (PetscObject)ctxcontainer));
387: tsdm->ifunctionctxcontainer = ctxcontainer;
388: PetscCall(PetscContainerDestroy(&ctxcontainer));
389: }
390: PetscFunctionReturn(PETSC_SUCCESS);
391: }
393: /*@C
394: DMTSSetIFunctionContextDestroy - set `TS` implicit evaluation context destroy function
396: Not Collective
398: Input Parameters:
399: + dm - `DM` to be used with `TS`
400: - f - implicit evaluation context destroy function
402: Level: advanced
404: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetIFunction()`, `TSSetIFunction()`
405: @*/
406: PetscErrorCode DMTSSetIFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
407: {
408: DMTS tsdm;
410: PetscFunctionBegin;
412: PetscCall(DMGetDMTSWrite(dm, &tsdm));
413: if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->ifunctionctxcontainer, f));
414: PetscFunctionReturn(PETSC_SUCCESS);
415: }
417: PetscErrorCode DMTSUnsetIFunctionContext_Internal(DM dm)
418: {
419: DMTS tsdm;
421: PetscFunctionBegin;
423: PetscCall(DMGetDMTSWrite(dm, &tsdm));
424: PetscCall(DMTSUnsetIFunctionContext_DMTS(tsdm));
425: PetscFunctionReturn(PETSC_SUCCESS);
426: }
428: /*@C
429: DMTSGetIFunction - get `TS` implicit residual evaluation function
431: Not Collective
433: Input Parameter:
434: . dm - `DM` to be used with `TS`
436: Output Parameters:
437: + func - function evaluation function, for calling sequence see `TSSetIFunction()`
438: - ctx - context for residual evaluation
440: Level: advanced
442: Note:
443: `TSGetIFunction()` is normally used, but it calls this function internally because the user context is actually
444: associated with the `DM`.
446: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetIFunction()`
447: @*/
448: PetscErrorCode DMTSGetIFunction(DM dm, TSIFunction *func, void **ctx)
449: {
450: DMTS tsdm;
452: PetscFunctionBegin;
454: PetscCall(DMGetDMTS(dm, &tsdm));
455: if (func) *func = tsdm->ops->ifunction;
456: if (ctx) {
457: if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ifunctionctxcontainer, ctx));
458: else *ctx = NULL;
459: }
460: PetscFunctionReturn(PETSC_SUCCESS);
461: }
463: /*@C
464: DMTSSetI2Function - set `TS` implicit function evaluation function for 2nd order systems
466: Not Collective
468: Input Parameters:
469: + dm - `DM` to be used with `TS`
470: . fun - function evaluation routine
471: - ctx - context for residual evaluation
473: Level: advanced
475: Note:
476: `TSSetI2Function()` is normally used, but it calls this function internally because the user context is actually
477: associated with the `DM`.
479: .seealso: [](ch_ts), `DM`, `TS`, `TSSetI2Function()`
480: @*/
481: PetscErrorCode DMTSSetI2Function(DM dm, TSI2Function fun, void *ctx)
482: {
483: DMTS tsdm;
485: PetscFunctionBegin;
487: PetscCall(DMGetDMTSWrite(dm, &tsdm));
488: if (fun) tsdm->ops->i2function = fun;
489: if (ctx) {
490: PetscContainer ctxcontainer;
491: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
492: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
493: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2function ctx", (PetscObject)ctxcontainer));
494: tsdm->i2functionctxcontainer = ctxcontainer;
495: PetscCall(PetscContainerDestroy(&ctxcontainer));
496: }
497: PetscFunctionReturn(PETSC_SUCCESS);
498: }
500: /*@C
501: DMTSSetI2FunctionContextDestroy - set `TS` implicit evaluation for 2nd order systems context destroy
503: Not Collective
505: Input Parameters:
506: + dm - `DM` to be used with `TS`
507: - f - implicit evaluation context destroy function
509: Level: advanced
511: Note:
512: `TSSetI2FunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
513: associated with the `DM`.
515: .seealso: [](ch_ts), `TSSetI2FunctionContextDestroy()`, `DMTSSetI2Function()`, `TSSetI2Function()`
516: @*/
517: PetscErrorCode DMTSSetI2FunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
518: {
519: DMTS tsdm;
521: PetscFunctionBegin;
523: PetscCall(DMGetDMTSWrite(dm, &tsdm));
524: if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->i2functionctxcontainer, f));
525: PetscFunctionReturn(PETSC_SUCCESS);
526: }
528: PetscErrorCode DMTSUnsetI2FunctionContext_Internal(DM dm)
529: {
530: DMTS tsdm;
532: PetscFunctionBegin;
534: PetscCall(DMGetDMTSWrite(dm, &tsdm));
535: PetscCall(DMTSUnsetI2FunctionContext_DMTS(tsdm));
536: PetscFunctionReturn(PETSC_SUCCESS);
537: }
539: /*@C
540: DMTSGetI2Function - get `TS` implicit residual evaluation function for 2nd order systems
542: Not Collective
544: Input Parameter:
545: . dm - `DM` to be used with `TS`
547: Output Parameters:
548: + fun - function evaluation function, for calling sequence see `TSSetI2Function()`
549: - ctx - context for residual evaluation
551: Level: advanced
553: Note:
554: `TSGetI2Function()` is normally used, but it calls this function internally because the user context is actually
555: associated with the `DM`.
557: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetI2Function()`, `TSGetI2Function()`
558: @*/
559: PetscErrorCode DMTSGetI2Function(DM dm, TSI2Function *fun, void **ctx)
560: {
561: DMTS tsdm;
563: PetscFunctionBegin;
565: PetscCall(DMGetDMTS(dm, &tsdm));
566: if (fun) *fun = tsdm->ops->i2function;
567: if (ctx) {
568: if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2functionctxcontainer, ctx));
569: else *ctx = NULL;
570: }
571: PetscFunctionReturn(PETSC_SUCCESS);
572: }
574: /*@C
575: DMTSSetI2Jacobian - set `TS` implicit Jacobian evaluation function for 2nd order systems
577: Not Collective
579: Input Parameters:
580: + dm - `DM` to be used with `TS`
581: . jac - Jacobian evaluation routine
582: - ctx - context for Jacobian evaluation
584: Level: advanced
586: Note:
587: `TSSetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
588: associated with the `DM`.
590: .seealso: [](ch_ts), `DM`, `TS`, `TSI2Jacobian`, `TSSetI2Jacobian()`
591: @*/
592: PetscErrorCode DMTSSetI2Jacobian(DM dm, TSI2Jacobian jac, void *ctx)
593: {
594: DMTS tsdm;
596: PetscFunctionBegin;
598: PetscCall(DMGetDMTSWrite(dm, &tsdm));
599: if (jac) tsdm->ops->i2jacobian = jac;
600: if (ctx) {
601: PetscContainer ctxcontainer;
602: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
603: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
604: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2jacobian ctx", (PetscObject)ctxcontainer));
605: tsdm->i2jacobianctxcontainer = ctxcontainer;
606: PetscCall(PetscContainerDestroy(&ctxcontainer));
607: }
608: PetscFunctionReturn(PETSC_SUCCESS);
609: }
611: /*@C
612: DMTSSetI2JacobianContextDestroy - set `TS` implicit Jacobian evaluation for 2nd order systems context destroy function
614: Not Collective
616: Input Parameters:
617: + dm - `DM` to be used with `TS`
618: - f - implicit Jacobian evaluation context destroy function
620: Level: advanced
622: .seealso: [](ch_ts), `DM`, `TS`, `TSSetI2JacobianContextDestroy()`, `DMTSSetI2Jacobian()`, `TSSetI2Jacobian()`
623: @*/
624: PetscErrorCode DMTSSetI2JacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
625: {
626: DMTS tsdm;
628: PetscFunctionBegin;
630: PetscCall(DMGetDMTSWrite(dm, &tsdm));
631: if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->i2jacobianctxcontainer, f));
632: PetscFunctionReturn(PETSC_SUCCESS);
633: }
635: PetscErrorCode DMTSUnsetI2JacobianContext_Internal(DM dm)
636: {
637: DMTS tsdm;
639: PetscFunctionBegin;
641: PetscCall(DMGetDMTSWrite(dm, &tsdm));
642: PetscCall(DMTSUnsetI2JacobianContext_DMTS(tsdm));
643: PetscFunctionReturn(PETSC_SUCCESS);
644: }
646: /*@C
647: DMTSGetI2Jacobian - get `TS` implicit Jacobian evaluation function for 2nd order systems
649: Not Collective
651: Input Parameter:
652: . dm - `DM` to be used with `TS`
654: Output Parameters:
655: + jac - Jacobian evaluation function, for calling sequence see `TSSetI2Jacobian()`
656: - ctx - context for Jacobian evaluation
658: Level: advanced
660: Note:
661: `TSGetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
662: associated with the `DM`.
664: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetI2Jacobian()`, `TSGetI2Jacobian()`
665: @*/
666: PetscErrorCode DMTSGetI2Jacobian(DM dm, TSI2Jacobian *jac, void **ctx)
667: {
668: DMTS tsdm;
670: PetscFunctionBegin;
672: PetscCall(DMGetDMTS(dm, &tsdm));
673: if (jac) *jac = tsdm->ops->i2jacobian;
674: if (ctx) {
675: if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2jacobianctxcontainer, ctx));
676: else *ctx = NULL;
677: }
678: PetscFunctionReturn(PETSC_SUCCESS);
679: }
681: /*@C
682: DMTSSetRHSFunction - set `TS` explicit residual evaluation function
684: Not Collective
686: Input Parameters:
687: + dm - `DM` to be used with `TS`
688: . func - RHS function evaluation routine
689: - ctx - context for residual evaluation
691: Level: advanced
693: Note:
694: `TSSetRHSFunction()` is normally used, but it calls this function internally because the user context is actually
695: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
696: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
698: .seealso: [](ch_ts), `DM`, `TS`, `TSRHSFunction`
699: @*/
700: PetscErrorCode DMTSSetRHSFunction(DM dm, TSRHSFunction func, void *ctx)
701: {
702: DMTS tsdm;
704: PetscFunctionBegin;
706: PetscCall(DMGetDMTSWrite(dm, &tsdm));
707: if (func) tsdm->ops->rhsfunction = func;
708: if (ctx) {
709: PetscContainer ctxcontainer;
710: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
711: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
712: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", (PetscObject)ctxcontainer));
713: tsdm->rhsfunctionctxcontainer = ctxcontainer;
714: PetscCall(PetscContainerDestroy(&ctxcontainer));
715: }
716: PetscFunctionReturn(PETSC_SUCCESS);
717: }
719: /*@C
720: DMTSSetRHSFunctionContextDestroy - set `TS` explicit residual evaluation context destroy function
722: Not Collective
724: Input Parameters:
725: + dm - `DM` to be used with `TS`
726: - f - explicit evaluation context destroy function
728: Level: advanced
730: Note:
731: `TSSetRHSFunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
732: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
733: not.
735: Developer Notes:
736: If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
738: .seealso: [](ch_ts), `TSSetRHSFunctionContextDestroy()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
739: @*/
740: PetscErrorCode DMTSSetRHSFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
741: {
742: DMTS tsdm;
744: PetscFunctionBegin;
746: PetscCall(DMGetDMTSWrite(dm, &tsdm));
747: if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->rhsfunctionctxcontainer, f));
748: PetscFunctionReturn(PETSC_SUCCESS);
749: }
751: PetscErrorCode DMTSUnsetRHSFunctionContext_Internal(DM dm)
752: {
753: DMTS tsdm;
755: PetscFunctionBegin;
757: PetscCall(DMGetDMTSWrite(dm, &tsdm));
758: PetscCall(DMTSUnsetRHSFunctionContext_DMTS(tsdm));
759: tsdm->rhsfunctionctxcontainer = NULL;
760: PetscFunctionReturn(PETSC_SUCCESS);
761: }
763: /*@C
764: DMTSSetTransientVariable - sets function to transform from state to transient variables
766: Logically Collective
768: Input Parameters:
769: + dm - `DM` to be used with `TS`
770: . tvar - a function that transforms to transient variables
771: - ctx - a context for tvar
773: Level: advanced
775: Notes:
776: This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
777: can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to
778: well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is
779: C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
780: evaluated via the chain rule, as in
782: dF/dP + shift * dF/dCdot dC/dP.
784: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSetTransientVariable()`, `DMTSGetTransientVariable()`, `DMTSSetIFunction()`, `DMTSSetIJacobian()`
785: @*/
786: PetscErrorCode DMTSSetTransientVariable(DM dm, TSTransientVariable tvar, void *ctx)
787: {
788: DMTS dmts;
790: PetscFunctionBegin;
792: PetscCall(DMGetDMTSWrite(dm, &dmts));
793: dmts->ops->transientvar = tvar;
794: dmts->transientvarctx = ctx;
795: PetscFunctionReturn(PETSC_SUCCESS);
796: }
798: /*@C
799: DMTSGetTransientVariable - gets function to transform from state to transient variables set with `DMTSSetTransientVariable()`
801: Logically Collective
803: Input Parameter:
804: . dm - `DM` to be used with `TS`
806: Output Parameters:
807: + tvar - a function that transforms to transient variables
808: - ctx - a context for tvar
810: Level: advanced
812: .seealso: [](ch_ts), `DM`, `DMTSSetTransientVariable()`, `DMTSGetIFunction()`, `DMTSGetIJacobian()`
813: @*/
814: PetscErrorCode DMTSGetTransientVariable(DM dm, TSTransientVariable *tvar, void *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: /*@C
827: DMTSGetSolutionFunction - gets the `TS` solution evaluation function
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 `TSSetSolution()`
836: - ctx - context for solution evaluation
838: Level: advanced
840: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetSolutionFunction()`
841: @*/
842: PetscErrorCode DMTSGetSolutionFunction(DM dm, TSSolutionFunction *func, void **ctx)
843: {
844: DMTS tsdm;
846: PetscFunctionBegin;
848: PetscCall(DMGetDMTS(dm, &tsdm));
849: if (func) *func = tsdm->ops->solution;
850: if (ctx) *ctx = tsdm->solutionctx;
851: PetscFunctionReturn(PETSC_SUCCESS);
852: }
854: /*@C
855: DMTSSetSolutionFunction - set `TS` solution evaluation function
857: Not Collective
859: Input Parameters:
860: + dm - `DM` to be used with `TS`
861: . func - solution function evaluation routine
862: - ctx - context for solution evaluation
864: Level: advanced
866: Note:
867: `TSSetSolutionFunction()` is normally used, but it calls this function internally because the user 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), `DM`, `TS`, `DMTSGetSolutionFunction()`
872: @*/
873: PetscErrorCode DMTSSetSolutionFunction(DM dm, TSSolutionFunction func, void *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: /*@C
886: DMTSSetForcingFunction - set `TS` forcing function evaluation function
888: Not Collective
890: Input Parameters:
891: + dm - `DM` to be used with `TS`
892: . func - forcing function evaluation routine
893: - ctx - context for solution evaluation
895: Level: advanced
897: Note:
898: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user 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), `DM`, `TS`, `TSForcingFunction`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
903: @*/
904: PetscErrorCode DMTSSetForcingFunction(DM dm, TSForcingFunction func, void *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: /*@C
917: DMTSGetForcingFunction - get `TS` forcing function evaluation function
919: Not Collective
921: Input Parameter:
922: . dm - `DM` to be used with `TS`
924: Output Parameters:
925: + f - forcing function evaluation function; see `TSForcingFunction` for details
926: - ctx - context for solution evaluation
928: Level: advanced
930: Note:
931: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user 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), `TS`, `DM`, `TSSetForcingFunction()`
936: @*/
937: PetscErrorCode DMTSGetForcingFunction(DM dm, TSForcingFunction *f, void **ctx)
938: {
939: DMTS tsdm;
941: PetscFunctionBegin;
943: PetscCall(DMGetDMTSWrite(dm, &tsdm));
944: if (f) *f = tsdm->ops->forcing;
945: if (ctx) *ctx = tsdm->forcingctx;
946: PetscFunctionReturn(PETSC_SUCCESS);
947: }
949: /*@C
950: DMTSGetRHSFunction - get `TS` explicit residual evaluation function
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 `TSSetRHSFunction()`
959: - ctx - context for residual evaluation
961: Level: advanced
963: Note:
964: `TSGetRHSFunction()` is normally used, but it calls this function internally because the user context is actually
965: associated with the DM.
967: .seealso: [](ch_ts), `DM`, `TS`
968: @*/
969: PetscErrorCode DMTSGetRHSFunction(DM dm, TSRHSFunction *func, void **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 *ctx = NULL;
980: }
981: PetscFunctionReturn(PETSC_SUCCESS);
982: }
984: /*@C
985: DMTSSetIJacobian - set `TS` Jacobian evaluation function
987: Not Collective
989: Input Parameters:
990: + dm - `DM` to be used with `TS`
991: . func - Jacobian evaluation routine
992: - ctx - context for residual evaluation
994: Level: advanced
996: Note:
997: `TSSetIJacobian()` is normally used, but it calls this function internally because the user 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), `TS`, `DM`, `TSIJacobian`, `DMTSGetIJacobian()`
1002: @*/
1003: PetscErrorCode DMTSSetIJacobian(DM dm, TSIJacobian func, void *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: /*@C
1023: DMTSSetIJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1025: Not Collective
1027: Input Parameters:
1028: + dm - `DM` to be used with `TS`
1029: - f - Jacobian evaluation context destroy function
1031: Level: advanced
1033: Note:
1034: `TSSetIJacobianContextDestroy()` is normally used, but it calls this function internally because the user 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), `TSSetIJacobianContextDestroy()`, `TSSetI2JacobianContextDestroy()`, `DMTSSetIJacobian()`, `TSSetIJacobian()`
1042: @*/
1043: PetscErrorCode DMTSSetIJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1044: {
1045: DMTS tsdm;
1047: PetscFunctionBegin;
1049: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1050: if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(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: /*@C
1066: DMTSGetIJacobian - get `TS` Jacobian evaluation function
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 `TSSetIJacobian()`
1075: - ctx - context for residual evaluation
1077: Level: advanced
1079: Note:
1080: `TSGetIJacobian()` is normally used, but it calls this function internally because the user 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), `DM`, `TS`, `DMTSSetIJacobian()`
1085: @*/
1086: PetscErrorCode DMTSGetIJacobian(DM dm, TSIJacobian *func, void **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 *ctx = NULL;
1097: }
1098: PetscFunctionReturn(PETSC_SUCCESS);
1099: }
1101: /*@C
1102: DMTSSetRHSJacobian - set `TS` Jacobian evaluation function
1104: Not Collective
1106: Input Parameters:
1107: + dm - `DM` to be used with `TS`
1108: . func - Jacobian evaluation routine
1109: - ctx - context for residual evaluation
1111: Level: advanced
1113: Note:
1114: `TSSetRHSJacobian()` is normally used, but it calls this function internally because the user 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), `TSRHSJacobian`, `DMTSGetRHSJacobian()`
1122: @*/
1123: PetscErrorCode DMTSSetRHSJacobian(DM dm, TSRHSJacobian func, void *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: /*@C
1143: DMTSSetRHSJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1145: Not Collective
1147: Input Parameters:
1148: + dm - `DM` to be used with `TS`
1149: - f - Jacobian evaluation context destroy function
1151: Level: advanced
1153: Note:
1154: The user usually calls `TSSetRHSJacobianContextDestroy()` which calls this routine
1156: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobianContextDestroy()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1157: @*/
1158: PetscErrorCode DMTSSetRHSJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1159: {
1160: DMTS tsdm;
1162: PetscFunctionBegin;
1164: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1165: if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(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: /*@C
1181: DMTSGetRHSJacobian - get `TS` Jacobian evaluation function
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 `TSSetRHSJacobian()`
1190: - ctx - context for residual evaluation
1192: Level: advanced
1194: Note:
1195: `TSGetRHSJacobian()` is normally used, but it calls this function internally because the user 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), `DM`, `TS`, `DMTSSetRHSJacobian()`
1200: @*/
1201: PetscErrorCode DMTSGetRHSJacobian(DM dm, TSRHSJacobian *func, void **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 *ctx = NULL;
1212: }
1213: PetscFunctionReturn(PETSC_SUCCESS);
1214: }
1216: /*@C
1217: DMTSSetIFunctionSerialize - sets functions used to view and load a IFunction 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: advanced
1228: .seealso: [](ch_ts), `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: /*@C
1243: DMTSSetIJacobianSerialize - sets functions used to view and load a IJacobian 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: advanced
1254: .seealso: [](ch_ts), `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: }