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: Calling sequence of `func`:
366: $ PetscErrorCode func(TS ts, PetscReal t, Vec u, Vec u_t, Vec F,void *ctx);
367: + ts - the `TS` context obtained from `TSCreate()`
368: . t - time at step/stage being solved
369: . u - state vector
370: . u_t - time derivative of state vector
371: . F - function vector
372: - ctx - [optional] user-defined context for matrix evaluation routine
374: Level: advanced
376: Note:
377: `TSSetFunction()` is normally used, but it calls this function internally because the user context is actually
378: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
379: not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
381: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetIFunction()`, `DMTSSetJacobian()`
382: @*/
383: PetscErrorCode DMTSSetIFunction(DM dm, TSIFunction func, void *ctx)
384: {
385: DMTS tsdm;
387: PetscFunctionBegin;
389: PetscCall(DMGetDMTSWrite(dm, &tsdm));
390: if (func) tsdm->ops->ifunction = func;
391: if (ctx) {
392: PetscContainer ctxcontainer;
393: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
394: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
395: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ifunction ctx", (PetscObject)ctxcontainer));
396: tsdm->ifunctionctxcontainer = ctxcontainer;
397: PetscCall(PetscContainerDestroy(&ctxcontainer));
398: }
399: PetscFunctionReturn(PETSC_SUCCESS);
400: }
402: /*@C
403: DMTSSetIFunctionContextDestroy - set `TS` implicit evaluation context destroy function
405: Not Collective
407: Input Parameters:
408: + dm - `DM` to be used with `TS`
409: - f - implicit evaluation context destroy function
411: Level: advanced
413: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetIFunction()`, `TSSetIFunction()`
414: @*/
415: PetscErrorCode DMTSSetIFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
416: {
417: DMTS tsdm;
419: PetscFunctionBegin;
421: PetscCall(DMGetDMTSWrite(dm, &tsdm));
422: if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->ifunctionctxcontainer, f));
423: PetscFunctionReturn(PETSC_SUCCESS);
424: }
426: PetscErrorCode DMTSUnsetIFunctionContext_Internal(DM dm)
427: {
428: DMTS tsdm;
430: PetscFunctionBegin;
432: PetscCall(DMGetDMTSWrite(dm, &tsdm));
433: PetscCall(DMTSUnsetIFunctionContext_DMTS(tsdm));
434: PetscFunctionReturn(PETSC_SUCCESS);
435: }
437: /*@C
438: DMTSGetIFunction - get `TS` implicit residual evaluation function
440: Not Collective
442: Input Parameter:
443: . dm - `DM` to be used with `TS`
445: Output Parameters:
446: + func - function evaluation function, for calling sequence see `TSSetIFunction()`
447: - ctx - context for residual evaluation
449: Level: advanced
451: Note:
452: `TSGetFunction()` is normally used, but it calls this function internally because the user context is actually
453: associated with the `DM`.
455: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `DMTSSetFunction()`, `TSSetFunction()`
456: @*/
457: PetscErrorCode DMTSGetIFunction(DM dm, TSIFunction *func, void **ctx)
458: {
459: DMTS tsdm;
461: PetscFunctionBegin;
463: PetscCall(DMGetDMTS(dm, &tsdm));
464: if (func) *func = tsdm->ops->ifunction;
465: if (ctx) {
466: if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ifunctionctxcontainer, ctx));
467: else *ctx = NULL;
468: }
469: PetscFunctionReturn(PETSC_SUCCESS);
470: }
472: /*@C
473: DMTSSetI2Function - set `TS` implicit function evaluation function for 2nd order systems
475: Not Collective
477: Input Parameters:
478: + dm - `DM` to be used with `TS`
479: . fun - function evaluation routine
480: - ctx - context for residual evaluation
482: Calling sequence of `fun`:
483: $ PetscErrorCode fun(TS ts, PetscReal t, Vec U, Vec U_t, Vec U_tt, Vec F,void *ctx);
484: + ts - the `TS` context obtained from `TSCreate()`
485: . t - time at step/stage being solved
486: . U - state vector
487: . U_t - time derivative of state vector
488: . U_tt - second time derivative of state vector
489: . F - function vector
490: - ctx - [optional] user-defined context for matrix evaluation routine (may be `NULL`)
492: Level: advanced
494: Note:
495: `TSSetI2Function()` is normally used, but it calls this function internally because the user context is actually
496: associated with the `DM`.
498: .seealso: [](ch_ts), `DM`, `TS`, `TSSetI2Function()`
499: @*/
500: PetscErrorCode DMTSSetI2Function(DM dm, TSI2Function fun, void *ctx)
501: {
502: DMTS tsdm;
504: PetscFunctionBegin;
506: PetscCall(DMGetDMTSWrite(dm, &tsdm));
507: if (fun) tsdm->ops->i2function = fun;
508: if (ctx) {
509: PetscContainer ctxcontainer;
510: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
511: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
512: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2function ctx", (PetscObject)ctxcontainer));
513: tsdm->i2functionctxcontainer = ctxcontainer;
514: PetscCall(PetscContainerDestroy(&ctxcontainer));
515: }
516: PetscFunctionReturn(PETSC_SUCCESS);
517: }
519: /*@C
520: DMTSSetI2FunctionContextDestroy - set `TS` implicit evaluation for 2nd order systems context destroy
522: Not Collective
524: Input Parameters:
525: + dm - `DM` to be used with `TS`
526: - f - implicit evaluation context destroy function
528: Level: advanced
530: Note:
531: `TSSetI2FunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
532: associated with the `DM`.
534: .seealso: [](ch_ts), `TSSetI2FunctionContextDestroy()`, `DMTSSetI2Function()`, `TSSetI2Function()`
535: @*/
536: PetscErrorCode DMTSSetI2FunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
537: {
538: DMTS tsdm;
540: PetscFunctionBegin;
542: PetscCall(DMGetDMTSWrite(dm, &tsdm));
543: if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->i2functionctxcontainer, f));
544: PetscFunctionReturn(PETSC_SUCCESS);
545: }
547: PetscErrorCode DMTSUnsetI2FunctionContext_Internal(DM dm)
548: {
549: DMTS tsdm;
551: PetscFunctionBegin;
553: PetscCall(DMGetDMTSWrite(dm, &tsdm));
554: PetscCall(DMTSUnsetI2FunctionContext_DMTS(tsdm));
555: PetscFunctionReturn(PETSC_SUCCESS);
556: }
558: /*@C
559: DMTSGetI2Function - get `TS` implicit residual evaluation function for 2nd order systems
561: Not Collective
563: Input Parameter:
564: . dm - `DM` to be used with `TS`
566: Output Parameters:
567: + fun - function evaluation function, for calling sequence see `TSSetI2Function()`
568: - ctx - context for residual evaluation
570: Level: advanced
572: Note:
573: `TSGetI2Function()` is normally used, but it calls this function internally because the user context is actually
574: associated with the `DM`.
576: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetI2Function()`, `TSGetI2Function()`
577: @*/
578: PetscErrorCode DMTSGetI2Function(DM dm, TSI2Function *fun, void **ctx)
579: {
580: DMTS tsdm;
582: PetscFunctionBegin;
584: PetscCall(DMGetDMTS(dm, &tsdm));
585: if (fun) *fun = tsdm->ops->i2function;
586: if (ctx) {
587: if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2functionctxcontainer, ctx));
588: else *ctx = NULL;
589: }
590: PetscFunctionReturn(PETSC_SUCCESS);
591: }
593: /*@C
594: DMTSSetI2Jacobian - set `TS` implicit Jacobian evaluation function for 2nd order systems
596: Not Collective
598: Input Parameters:
599: + dm - `DM` to be used with `TS`
600: . fun - Jacobian evaluation routine
601: - ctx - context for Jacobian evaluation
603: Calling sequence of `jac`:
604: $ PetscErrorCode jac(TS ts, PetscReal t, Vec U, Vec U_t, Vec U_tt, PetscReal v, PetscReal a, Mat J, Mat P, void *ctx)
605: + ts - the `TS` context obtained from `TSCreate()`
606: . t - time at step/stage being solved
607: . U - state vector
608: . U_t - time derivative of state vector
609: . U_tt - second time derivative of state vector
610: . v - shift for U_t
611: . a - shift for U_tt
612: . J - Jacobian of G(U) = F(t,U,W+v*U,W'+a*U), equivalent to dF/dU + v*dF/dU_t + a*dF/dU_tt
613: . P - preconditioning matrix for J, may be same as `J`
614: - ctx - [optional] user-defined context for matrix evaluation routine
616: Level: advanced
618: Note:
619: `TSSetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
620: associated with the `DM`.
622: .seealso: [](ch_ts), `DM`, `TS`, `TSSetI2Jacobian()`
623: @*/
624: PetscErrorCode DMTSSetI2Jacobian(DM dm, TSI2Jacobian jac, void *ctx)
625: {
626: DMTS tsdm;
628: PetscFunctionBegin;
630: PetscCall(DMGetDMTSWrite(dm, &tsdm));
631: if (jac) tsdm->ops->i2jacobian = jac;
632: if (ctx) {
633: PetscContainer ctxcontainer;
634: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
635: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
636: PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2jacobian ctx", (PetscObject)ctxcontainer));
637: tsdm->i2jacobianctxcontainer = ctxcontainer;
638: PetscCall(PetscContainerDestroy(&ctxcontainer));
639: }
640: PetscFunctionReturn(PETSC_SUCCESS);
641: }
643: /*@C
644: DMTSSetI2JacobianContextDestroy - set `TS` implicit Jacobian evaluation for 2nd order systems context destroy function
646: Not Collective
648: Input Parameters:
649: + dm - `DM` to be used with `TS`
650: - f - implicit Jacobian evaluation context destroy function
652: Level: advanced
654: .seealso: [](ch_ts), `DM`, `TS`, `TSSetI2JacobianContextDestroy()`, `DMTSSetI2Jacobian()`, `TSSetI2Jacobian()`
655: @*/
656: PetscErrorCode DMTSSetI2JacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
657: {
658: DMTS tsdm;
660: PetscFunctionBegin;
662: PetscCall(DMGetDMTSWrite(dm, &tsdm));
663: if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->i2jacobianctxcontainer, f));
664: PetscFunctionReturn(PETSC_SUCCESS);
665: }
667: PetscErrorCode DMTSUnsetI2JacobianContext_Internal(DM dm)
668: {
669: DMTS tsdm;
671: PetscFunctionBegin;
673: PetscCall(DMGetDMTSWrite(dm, &tsdm));
674: PetscCall(DMTSUnsetI2JacobianContext_DMTS(tsdm));
675: PetscFunctionReturn(PETSC_SUCCESS);
676: }
678: /*@C
679: DMTSGetI2Jacobian - get `TS` implicit Jacobian evaluation function for 2nd order systems
681: Not Collective
683: Input Parameter:
684: . dm - `DM` to be used with `TS`
686: Output Parameters:
687: + jac - Jacobian evaluation function, for calling sequence see `TSSetI2Jacobian()`
688: - ctx - context for Jacobian evaluation
690: Level: advanced
692: Note:
693: `TSGetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
694: associated with the `DM`.
696: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetI2Jacobian()`, `TSGetI2Jacobian()`
697: @*/
698: PetscErrorCode DMTSGetI2Jacobian(DM dm, TSI2Jacobian *jac, void **ctx)
699: {
700: DMTS tsdm;
702: PetscFunctionBegin;
704: PetscCall(DMGetDMTS(dm, &tsdm));
705: if (jac) *jac = tsdm->ops->i2jacobian;
706: if (ctx) {
707: if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2jacobianctxcontainer, ctx));
708: else *ctx = NULL;
709: }
710: PetscFunctionReturn(PETSC_SUCCESS);
711: }
713: /*@C
714: DMTSSetRHSFunction - set `TS` explicit residual evaluation function
716: Not Collective
718: Input Parameters:
719: + dm - `DM` to be used with `TS`
720: . func - RHS function evaluation routine
721: - ctx - context for residual evaluation
723: Calling sequence of `func`:
724: $ PetscErrorCode func(TS ts, PetscReal t, Vec u, Vec F, void *ctx);
725: + ts - timestep context
726: . t - current timestep
727: . u - input vector
728: . F - function vector
729: - ctx - [optional] user-defined function context
731: Level: advanced
733: Note:
734: `TSSetRHSFunction()` is normally used, but it calls this function internally because the user context is actually
735: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
736: not. 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), `DM`, `TS`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSSetJacobian()`
739: @*/
740: PetscErrorCode DMTSSetRHSFunction(DM dm, TSRHSFunction func, void *ctx)
741: {
742: DMTS tsdm;
744: PetscFunctionBegin;
746: PetscCall(DMGetDMTSWrite(dm, &tsdm));
747: if (func) tsdm->ops->rhsfunction = func;
748: if (ctx) {
749: PetscContainer ctxcontainer;
750: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
751: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
752: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", (PetscObject)ctxcontainer));
753: tsdm->rhsfunctionctxcontainer = ctxcontainer;
754: PetscCall(PetscContainerDestroy(&ctxcontainer));
755: }
756: PetscFunctionReturn(PETSC_SUCCESS);
757: }
759: /*@C
760: DMTSSetRHSFunctionContextDestroy - set `TS` explicit residual evaluation context destroy function
762: Not Collective
764: Input Parameters:
765: + dm - `DM` to be used with `TS`
766: - f - explicit evaluation context destroy function
768: Level: advanced
770: Note:
771: `TSSetRHSFunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
772: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
773: not.
775: Developer Note:
776: If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
778: .seealso: [](ch_ts), `TSSetRHSFunctionContextDestroy()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
779: @*/
780: PetscErrorCode DMTSSetRHSFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
781: {
782: DMTS tsdm;
784: PetscFunctionBegin;
786: PetscCall(DMGetDMTSWrite(dm, &tsdm));
787: if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->rhsfunctionctxcontainer, f));
788: PetscFunctionReturn(PETSC_SUCCESS);
789: }
791: PetscErrorCode DMTSUnsetRHSFunctionContext_Internal(DM dm)
792: {
793: DMTS tsdm;
795: PetscFunctionBegin;
797: PetscCall(DMGetDMTSWrite(dm, &tsdm));
798: PetscCall(DMTSUnsetRHSFunctionContext_DMTS(tsdm));
799: tsdm->rhsfunctionctxcontainer = NULL;
800: PetscFunctionReturn(PETSC_SUCCESS);
801: }
803: /*@C
804: DMTSSetTransientVariable - sets function to transform from state to transient variables
806: Logically Collective
808: Input Parameters:
809: + dm - `DM` to be used with `TS`
810: . tvar - a function that transforms to transient variables
811: - ctx - a context for tvar
813: Calling sequence of `tvar`:
814: $ PetscErrorCode tvar(TS ts, Vec p, Vec c, void *ctx);
815: + ts - timestep context
816: . p - input vector (primitive form)
817: . c - output vector, transient variables (conservative form)
818: - ctx - [optional] user-defined function context
820: Level: advanced
822: Notes:
823: This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
824: can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to
825: well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is
826: C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
827: evaluated via the chain rule, as in
829: dF/dP + shift * dF/dCdot dC/dP.
831: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSetTransientVariable()`, `DMTSGetTransientVariable()`, `DMTSSetIFunction()`, `DMTSSetIJacobian()`
832: @*/
833: PetscErrorCode DMTSSetTransientVariable(DM dm, TSTransientVariable tvar, void *ctx)
834: {
835: DMTS dmts;
837: PetscFunctionBegin;
839: PetscCall(DMGetDMTSWrite(dm, &dmts));
840: dmts->ops->transientvar = tvar;
841: dmts->transientvarctx = ctx;
842: PetscFunctionReturn(PETSC_SUCCESS);
843: }
845: /*@C
846: DMTSGetTransientVariable - gets function to transform from state to transient variables set with `DMTSSetTransientVariable()`
848: Logically Collective
850: Input Parameter:
851: . dm - `DM` to be used with `TS`
853: Output Parameters:
854: + tvar - a function that transforms to transient variables
855: - ctx - a context for tvar
857: Level: advanced
859: .seealso: [](ch_ts), `DM`, `DMTSSetTransientVariable()`, `DMTSGetIFunction()`, `DMTSGetIJacobian()`
860: @*/
861: PetscErrorCode DMTSGetTransientVariable(DM dm, TSTransientVariable *tvar, void *ctx)
862: {
863: DMTS dmts;
865: PetscFunctionBegin;
867: PetscCall(DMGetDMTS(dm, &dmts));
868: if (tvar) *tvar = dmts->ops->transientvar;
869: if (ctx) *(void **)ctx = dmts->transientvarctx;
870: PetscFunctionReturn(PETSC_SUCCESS);
871: }
873: /*@C
874: DMTSGetSolutionFunction - gets the `TS` solution evaluation function
876: Not Collective
878: Input Parameter:
879: . dm - `DM` to be used with `TS`
881: Output Parameters:
882: + func - solution function evaluation function, for calling sequence see `TSSetSolution()`
883: - ctx - context for solution evaluation
885: Level: advanced
887: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSSetSolutionFunction()`
888: @*/
889: PetscErrorCode DMTSGetSolutionFunction(DM dm, TSSolutionFunction *func, void **ctx)
890: {
891: DMTS tsdm;
893: PetscFunctionBegin;
895: PetscCall(DMGetDMTS(dm, &tsdm));
896: if (func) *func = tsdm->ops->solution;
897: if (ctx) *ctx = tsdm->solutionctx;
898: PetscFunctionReturn(PETSC_SUCCESS);
899: }
901: /*@C
902: DMTSSetSolutionFunction - set `TS` solution evaluation function
904: Not Collective
906: Input Parameters:
907: + dm - `DM` to be used with `TS`
908: . func - solution function evaluation routine
909: - ctx - context for solution evaluation
911: Calling sequence of `f`:
912: $ PetscErrorCode f(TS ts, PetscReal t, Vec u, void *ctx);
913: + ts - timestep context
914: . t - current timestep
915: . u - output vector
916: - ctx - [optional] user-defined function context
918: Level: advanced
920: Note:
921: `TSSetSolutionFunction()` is normally used, but it calls this function internally because the user context is actually
922: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
923: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
925: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSGetSolutionFunction()`
926: @*/
927: PetscErrorCode DMTSSetSolutionFunction(DM dm, TSSolutionFunction func, void *ctx)
928: {
929: DMTS tsdm;
931: PetscFunctionBegin;
933: PetscCall(DMGetDMTSWrite(dm, &tsdm));
934: if (func) tsdm->ops->solution = func;
935: if (ctx) tsdm->solutionctx = ctx;
936: PetscFunctionReturn(PETSC_SUCCESS);
937: }
939: /*@C
940: DMTSSetForcingFunction - set `TS` forcing function evaluation function
942: Not Collective
944: Input Parameters:
945: + dm - `DM` to be used with `TS`
946: . func - forcing function evaluation routine
947: - ctx - context for solution evaluation
949: Calling sequence of `func`:
950: $ PetscErrorCode func (TS ts, PetscReal t, Vec f,void *ctx)
951: + ts - timestep context
952: . t - current timestep
953: . f - output vector
954: - ctx - [optional] user-defined function context
956: Level: advanced
958: Note:
959: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
960: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
961: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
963: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
964: @*/
965: PetscErrorCode DMTSSetForcingFunction(DM dm, TSForcingFunction func, void *ctx)
966: {
967: DMTS tsdm;
969: PetscFunctionBegin;
971: PetscCall(DMGetDMTSWrite(dm, &tsdm));
972: if (func) tsdm->ops->forcing = func;
973: if (ctx) tsdm->forcingctx = ctx;
974: PetscFunctionReturn(PETSC_SUCCESS);
975: }
977: /*@C
978: DMTSGetForcingFunction - get `TS` forcing function evaluation function
980: Not Collective
982: Input Parameter:
983: . dm - `DM` to be used with `TS`
985: Output Parameters:
986: + f - forcing function evaluation function; see `TSForcingFunction` for details
987: - ctx - context for solution evaluation
989: Level: advanced
991: Note:
992: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
993: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
994: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
996: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
997: @*/
998: PetscErrorCode DMTSGetForcingFunction(DM dm, TSForcingFunction *f, void **ctx)
999: {
1000: DMTS tsdm;
1002: PetscFunctionBegin;
1004: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1005: if (f) *f = tsdm->ops->forcing;
1006: if (ctx) *ctx = tsdm->forcingctx;
1007: PetscFunctionReturn(PETSC_SUCCESS);
1008: }
1010: /*@C
1011: DMTSGetRHSFunction - get `TS` explicit residual evaluation function
1013: Not Collective
1015: Input Parameter:
1016: . dm - `DM` to be used with `TS`
1018: Output Parameters:
1019: + func - residual evaluation function, for calling sequence see `TSSetRHSFunction()`
1020: - ctx - context for residual evaluation
1022: Level: advanced
1024: Note:
1025: `TSGetFunction()` is normally used, but it calls this function internally because the user context is actually
1026: associated with the DM.
1028: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
1029: @*/
1030: PetscErrorCode DMTSGetRHSFunction(DM dm, TSRHSFunction *func, void **ctx)
1031: {
1032: DMTS tsdm;
1034: PetscFunctionBegin;
1036: PetscCall(DMGetDMTS(dm, &tsdm));
1037: if (func) *func = tsdm->ops->rhsfunction;
1038: if (ctx) {
1039: if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsfunctionctxcontainer, ctx));
1040: else *ctx = NULL;
1041: }
1042: PetscFunctionReturn(PETSC_SUCCESS);
1043: }
1045: /*@C
1046: DMTSSetIJacobian - set `TS` Jacobian evaluation function
1048: Not Collective
1050: Input Parameters:
1051: + dm - `DM` to be used with `TS`
1052: . func - Jacobian evaluation routine
1053: - ctx - context for residual evaluation
1055: Calling sequence of `f`:
1056: $ PetscErrorCode f(TS ts, PetscReal t, Vec U, Vec U_t, PetscReal a, Mat Amat, Mat Pmat, void *ctx);
1057: + ts - the `TS` context obtained from `TSCreate()`
1058: . t - time at step/stage being solved
1059: . U - state vector
1060: . U_t - time derivative of state vector
1061: . a - shift
1062: . Amat - (approximate) Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
1063: . Pmat - matrix used for constructing preconditioner, usually the same as Amat
1064: - ctx - [optional] user-defined context for matrix evaluation routine
1066: Level: advanced
1068: Note:
1069: `TSSetJacobian()` is normally used, but it calls this function internally because the user context is actually
1070: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1071: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1073: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSGetJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()`
1074: @*/
1075: PetscErrorCode DMTSSetIJacobian(DM dm, TSIJacobian func, void *ctx)
1076: {
1077: DMTS tsdm;
1079: PetscFunctionBegin;
1081: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1082: if (func) tsdm->ops->ijacobian = func;
1083: if (ctx) {
1084: PetscContainer ctxcontainer;
1085: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1086: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1087: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ijacobian ctx", (PetscObject)ctxcontainer));
1088: tsdm->ijacobianctxcontainer = ctxcontainer;
1089: PetscCall(PetscContainerDestroy(&ctxcontainer));
1090: }
1091: PetscFunctionReturn(PETSC_SUCCESS);
1092: }
1094: /*@C
1095: DMTSSetIJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1097: Not Collective
1099: Input Parameters:
1100: + dm - `DM` to be used with `TS`
1101: - f - Jacobian evaluation context destroy function
1103: Level: advanced
1105: Note:
1106: `TSSetIJacobianContextDestroy()` is normally used, but it calls this function internally because the user context is actually
1107: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1108: not.
1110: Developer Note:
1111: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1113: .seealso: [](ch_ts), `TSSetIJacobianContextDestroy()`, `TSSetI2JacobianContextDestroy()`, `DMTSSetIJacobian()`, `TSSetIJacobian()`
1114: @*/
1115: PetscErrorCode DMTSSetIJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1116: {
1117: DMTS tsdm;
1119: PetscFunctionBegin;
1121: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1122: if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->ijacobianctxcontainer, f));
1123: PetscFunctionReturn(PETSC_SUCCESS);
1124: }
1126: PetscErrorCode DMTSUnsetIJacobianContext_Internal(DM dm)
1127: {
1128: DMTS tsdm;
1130: PetscFunctionBegin;
1132: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1133: PetscCall(DMTSUnsetIJacobianContext_DMTS(tsdm));
1134: PetscFunctionReturn(PETSC_SUCCESS);
1135: }
1137: /*@C
1138: DMTSGetIJacobian - get `TS` Jacobian evaluation function
1140: Not Collective
1142: Input Parameter:
1143: . dm - `DM` to be used with `TS`
1145: Output Parameters:
1146: + func - Jacobian evaluation function, for calling sequence see `TSSetIJacobian()`
1147: - ctx - context for residual evaluation
1149: Level: advanced
1151: Note:
1152: `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1153: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1154: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1156: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1157: @*/
1158: PetscErrorCode DMTSGetIJacobian(DM dm, TSIJacobian *func, void **ctx)
1159: {
1160: DMTS tsdm;
1162: PetscFunctionBegin;
1164: PetscCall(DMGetDMTS(dm, &tsdm));
1165: if (func) *func = tsdm->ops->ijacobian;
1166: if (ctx) {
1167: if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ijacobianctxcontainer, ctx));
1168: else *ctx = NULL;
1169: }
1170: PetscFunctionReturn(PETSC_SUCCESS);
1171: }
1173: /*@C
1174: DMTSSetRHSJacobian - set `TS` Jacobian evaluation function
1176: Not Collective
1178: Input Parameters:
1179: + dm - `DM` to be used with `TS`
1180: . func - Jacobian evaluation routine
1181: - ctx - context for residual evaluation
1183: Calling sequence of `func`:
1184: $ PetscErrorCode func(TS ts, PetscReal t, Vec u, Mat A, Mat B, void *ctx);
1185: + ts - the `TS` context obtained from `TSCreate()`
1186: . t - current timestep
1187: . u - input vector
1188: . Amat - (approximate) Jacobian matrix
1189: . Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
1190: - ctx - [optional] user-defined context for matrix evaluation routine
1192: Level: advanced
1194: Note:
1195: `TSSetJacobian()` 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.
1199: Developer Note:
1200: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1202: .seealso: [](ch_ts), `DMTSSetContext()`, `TSSetFunction()`, `DMTSGetJacobian()`, `TSSetRHSJacobian()`
1203: @*/
1204: PetscErrorCode DMTSSetRHSJacobian(DM dm, TSRHSJacobian func, void *ctx)
1205: {
1206: DMTS tsdm;
1208: PetscFunctionBegin;
1210: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1211: if (func) tsdm->ops->rhsjacobian = func;
1212: if (ctx) {
1213: PetscContainer ctxcontainer;
1214: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1215: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1216: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs jacobian ctx", (PetscObject)ctxcontainer));
1217: tsdm->rhsjacobianctxcontainer = ctxcontainer;
1218: PetscCall(PetscContainerDestroy(&ctxcontainer));
1219: }
1220: PetscFunctionReturn(PETSC_SUCCESS);
1221: }
1223: /*@C
1224: DMTSSetRHSJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1226: Not Collective
1228: Input Parameters:
1229: + dm - `DM` to be used with `TS`
1230: - f - Jacobian evaluation context destroy function
1232: Level: advanced
1234: Note:
1235: The user usually calls `TSSetRHSJacobianContextDestroy()` which calls this routine
1237: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobianContextDestroy()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1238: @*/
1239: PetscErrorCode DMTSSetRHSJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1240: {
1241: DMTS tsdm;
1243: PetscFunctionBegin;
1245: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1246: if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->rhsjacobianctxcontainer, f));
1247: PetscFunctionReturn(PETSC_SUCCESS);
1248: }
1250: PetscErrorCode DMTSUnsetRHSJacobianContext_Internal(DM dm)
1251: {
1252: DMTS tsdm;
1254: PetscFunctionBegin;
1256: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1257: PetscCall(DMTSUnsetRHSJacobianContext_DMTS(tsdm));
1258: PetscFunctionReturn(PETSC_SUCCESS);
1259: }
1261: /*@C
1262: DMTSGetRHSJacobian - get `TS` Jacobian evaluation function
1264: Not Collective
1266: Input Parameter:
1267: . dm - `DM` to be used with `TS`
1269: Output Parameters:
1270: + func - Jacobian evaluation function, for calling sequence see `TSSetRHSJacobian()`
1271: - ctx - context for residual evaluation
1273: Level: advanced
1275: Note:
1276: `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1277: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1278: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1280: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1281: @*/
1282: PetscErrorCode DMTSGetRHSJacobian(DM dm, TSRHSJacobian *func, void **ctx)
1283: {
1284: DMTS tsdm;
1286: PetscFunctionBegin;
1288: PetscCall(DMGetDMTS(dm, &tsdm));
1289: if (func) *func = tsdm->ops->rhsjacobian;
1290: if (ctx) {
1291: if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsjacobianctxcontainer, ctx));
1292: else *ctx = NULL;
1293: }
1294: PetscFunctionReturn(PETSC_SUCCESS);
1295: }
1297: /*@C
1298: DMTSSetIFunctionSerialize - sets functions used to view and load a IFunction context
1300: Not Collective
1302: Input Parameters:
1303: + dm - `DM` to be used with `TS`
1304: . view - viewer function
1305: - load - loading function
1307: Level: advanced
1309: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1310: @*/
1311: PetscErrorCode DMTSSetIFunctionSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1312: {
1313: DMTS tsdm;
1315: PetscFunctionBegin;
1317: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1318: tsdm->ops->ifunctionview = view;
1319: tsdm->ops->ifunctionload = load;
1320: PetscFunctionReturn(PETSC_SUCCESS);
1321: }
1323: /*@C
1324: DMTSSetIJacobianSerialize - sets functions used to view and load a IJacobian context
1326: Not Collective
1328: Input Parameters:
1329: + dm - `DM` to be used with `TS`
1330: . view - viewer function
1331: - load - loading function
1333: Level: advanced
1335: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1336: @*/
1337: PetscErrorCode DMTSSetIJacobianSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1338: {
1339: DMTS tsdm;
1341: PetscFunctionBegin;
1343: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1344: tsdm->ops->ijacobianview = view;
1345: tsdm->ops->ijacobianload = load;
1346: PetscFunctionReturn(PETSC_SUCCESS);
1347: }