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: [](chapter_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: [](chapter_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: [](chapter_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: [](chapter_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,ctx);
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: [](chapter_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: [](chapter_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, see `TSSetIFunction()` for calling sequence
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: [](chapter_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,ctx);
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: [](chapter_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: [](chapter_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, see `TSSetI2Function()` for calling sequence
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: [](chapter_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);
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: [](chapter_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: [](chapter_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, see `TSSetI2Jacobian()` for calling sequence
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: [](chapter_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);
726: + ts - timestep context
727: . t - current timestep
728: . u - input vector
729: . F - function vector
730: - ctx - [optional] user-defined function context
732: Level: advanced
734: Note:
735: `TSSetRHSFunction()` is normally used, but it calls this function internally because the user context is actually
736: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
737: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
739: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSSetJacobian()`
740: @*/
741: PetscErrorCode DMTSSetRHSFunction(DM dm, TSRHSFunction func, void *ctx)
742: {
743: DMTS tsdm;
745: PetscFunctionBegin;
747: PetscCall(DMGetDMTSWrite(dm, &tsdm));
748: if (func) tsdm->ops->rhsfunction = func;
749: if (ctx) {
750: PetscContainer ctxcontainer;
751: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
752: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
753: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", (PetscObject)ctxcontainer));
754: tsdm->rhsfunctionctxcontainer = ctxcontainer;
755: PetscCall(PetscContainerDestroy(&ctxcontainer));
756: }
757: PetscFunctionReturn(PETSC_SUCCESS);
758: }
760: /*@C
761: DMTSSetRHSFunctionContextDestroy - set `TS` explicit residual evaluation context destroy function
763: Not Collective
765: Input Parameters:
766: + dm - `DM` to be used with `TS`
767: - f - explicit evaluation context destroy function
769: Level: advanced
771: Note:
772: `TSSetRHSFunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
773: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
774: not.
776: Developer Note:
777: If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
779: .seealso: [](chapter_ts), `TSSetRHSFunctionContextDestroy()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
780: @*/
781: PetscErrorCode DMTSSetRHSFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
782: {
783: DMTS tsdm;
785: PetscFunctionBegin;
787: PetscCall(DMGetDMTSWrite(dm, &tsdm));
788: if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->rhsfunctionctxcontainer, f));
789: PetscFunctionReturn(PETSC_SUCCESS);
790: }
792: PetscErrorCode DMTSUnsetRHSFunctionContext_Internal(DM dm)
793: {
794: DMTS tsdm;
796: PetscFunctionBegin;
798: PetscCall(DMGetDMTSWrite(dm, &tsdm));
799: PetscCall(DMTSUnsetRHSFunctionContext_DMTS(tsdm));
800: tsdm->rhsfunctionctxcontainer = NULL;
801: PetscFunctionReturn(PETSC_SUCCESS);
802: }
804: /*@C
805: DMTSSetTransientVariable - sets function to transform from state to transient variables
807: Logically Collective
809: Input Parameters:
810: + dm - `DM` to be used with `TS`
811: . tvar - a function that transforms to transient variables
812: - ctx - a context for tvar
814: Calling sequence of tvar:
815: $ PetscErrorCode tvar(TS ts,Vec p,Vec c,void *ctx);
817: + ts - timestep context
818: . p - input vector (primitive form)
819: . c - output vector, transient variables (conservative form)
820: - ctx - [optional] user-defined function context
822: Level: advanced
824: Notes:
825: This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
826: can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to
827: well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is
828: C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
829: evaluated via the chain rule, as in
831: dF/dP + shift * dF/dCdot dC/dP.
833: .seealso: [](chapter_ts), `TS`, `TSBDF`, `TSSetTransientVariable()`, `DMTSGetTransientVariable()`, `DMTSSetIFunction()`, `DMTSSetIJacobian()`
834: @*/
835: PetscErrorCode DMTSSetTransientVariable(DM dm, TSTransientVariable tvar, void *ctx)
836: {
837: DMTS dmts;
839: PetscFunctionBegin;
841: PetscCall(DMGetDMTSWrite(dm, &dmts));
842: dmts->ops->transientvar = tvar;
843: dmts->transientvarctx = ctx;
844: PetscFunctionReturn(PETSC_SUCCESS);
845: }
847: /*@C
848: DMTSGetTransientVariable - gets function to transform from state to transient variables set with `DMTSSetTransientVariable()`
850: Logically Collective
852: Input Parameter:
853: . dm - `DM` to be used with `TS`
855: Output Parameters:
856: + tvar - a function that transforms to transient variables
857: - ctx - a context for tvar
859: Level: advanced
861: .seealso: [](chapter_ts), `DM`, `DMTSSetTransientVariable()`, `DMTSGetIFunction()`, `DMTSGetIJacobian()`
862: @*/
863: PetscErrorCode DMTSGetTransientVariable(DM dm, TSTransientVariable *tvar, void *ctx)
864: {
865: DMTS dmts;
867: PetscFunctionBegin;
869: PetscCall(DMGetDMTS(dm, &dmts));
870: if (tvar) *tvar = dmts->ops->transientvar;
871: if (ctx) *(void **)ctx = dmts->transientvarctx;
872: PetscFunctionReturn(PETSC_SUCCESS);
873: }
875: /*@C
876: DMTSGetSolutionFunction - gets the `TS` solution evaluation function
878: Not Collective
880: Input Parameter:
881: . dm - `DM` to be used with `TS`
883: Output Parameters:
884: + func - solution function evaluation function, see `TSSetSolution()` for calling sequence
885: - ctx - context for solution evaluation
887: Level: advanced
889: .seealso: [](chapter_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSSetSolutionFunction()`
890: @*/
891: PetscErrorCode DMTSGetSolutionFunction(DM dm, TSSolutionFunction *func, void **ctx)
892: {
893: DMTS tsdm;
895: PetscFunctionBegin;
897: PetscCall(DMGetDMTS(dm, &tsdm));
898: if (func) *func = tsdm->ops->solution;
899: if (ctx) *ctx = tsdm->solutionctx;
900: PetscFunctionReturn(PETSC_SUCCESS);
901: }
903: /*@C
904: DMTSSetSolutionFunction - set `TS` solution evaluation function
906: Not Collective
908: Input Parameters:
909: + dm - `DM` to be used with `TS`
910: . func - solution function evaluation routine
911: - ctx - context for solution evaluation
913: Calling sequence of f:
914: $ PetscErrorCode f(TS ts,PetscReal t,Vec u,void *ctx);
916: + ts - timestep context
917: . t - current timestep
918: . u - output vector
919: - ctx - [optional] user-defined function context
921: Level: advanced
923: Note:
924: `TSSetSolutionFunction()` is normally used, but it calls this function internally because the user context is actually
925: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
926: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
928: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSGetSolutionFunction()`
929: @*/
930: PetscErrorCode DMTSSetSolutionFunction(DM dm, TSSolutionFunction func, void *ctx)
931: {
932: DMTS tsdm;
934: PetscFunctionBegin;
936: PetscCall(DMGetDMTSWrite(dm, &tsdm));
937: if (func) tsdm->ops->solution = func;
938: if (ctx) tsdm->solutionctx = ctx;
939: PetscFunctionReturn(PETSC_SUCCESS);
940: }
942: /*@C
943: DMTSSetForcingFunction - set `TS` forcing function evaluation function
945: Not Collective
947: Input Parameters:
948: + dm - `DM` to be used with `TS`
949: . f - forcing function evaluation routine
950: - ctx - context for solution evaluation
952: Calling sequence of func:
953: $ PetscErrorCode func (TS ts,PetscReal t,Vec f,void *ctx);
955: + ts - timestep context
956: . t - current timestep
957: . f - output vector
958: - ctx - [optional] user-defined function context
960: Level: advanced
962: Note:
963: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
964: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
965: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
967: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
968: @*/
969: PetscErrorCode DMTSSetForcingFunction(DM dm, TSForcingFunction f, void *ctx)
970: {
971: DMTS tsdm;
973: PetscFunctionBegin;
975: PetscCall(DMGetDMTSWrite(dm, &tsdm));
976: if (f) tsdm->ops->forcing = f;
977: if (ctx) tsdm->forcingctx = ctx;
978: PetscFunctionReturn(PETSC_SUCCESS);
979: }
981: /*@C
982: DMTSGetForcingFunction - get `TS` forcing function evaluation function
984: Not Collective
986: Input Parameter:
987: . dm - `DM` to be used with `TS`
989: Output Parameters:
990: + f - forcing function evaluation function; see `TSForcingFunction` for details
991: - ctx - context for solution evaluation
993: Level: advanced
995: Note:
996: `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
997: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
998: not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
1000: .seealso: [](chapter_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
1001: @*/
1002: PetscErrorCode DMTSGetForcingFunction(DM dm, TSForcingFunction *f, void **ctx)
1003: {
1004: DMTS tsdm;
1006: PetscFunctionBegin;
1008: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1009: if (f) *f = tsdm->ops->forcing;
1010: if (ctx) *ctx = tsdm->forcingctx;
1011: PetscFunctionReturn(PETSC_SUCCESS);
1012: }
1014: /*@C
1015: DMTSGetRHSFunction - get `TS` explicit residual evaluation function
1017: Not Collective
1019: Input Parameter:
1020: . dm - `DM` to be used with `TS`
1022: Output Parameters:
1023: + func - residual evaluation function, see `TSSetRHSFunction()` for calling sequence
1024: - ctx - context for residual evaluation
1026: Level: advanced
1028: Note:
1029: `TSGetFunction()` is normally used, but it calls this function internally because the user context is actually
1030: associated with the DM.
1032: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
1033: @*/
1034: PetscErrorCode DMTSGetRHSFunction(DM dm, TSRHSFunction *func, void **ctx)
1035: {
1036: DMTS tsdm;
1038: PetscFunctionBegin;
1040: PetscCall(DMGetDMTS(dm, &tsdm));
1041: if (func) *func = tsdm->ops->rhsfunction;
1042: if (ctx) {
1043: if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsfunctionctxcontainer, ctx));
1044: else *ctx = NULL;
1045: }
1046: PetscFunctionReturn(PETSC_SUCCESS);
1047: }
1049: /*@C
1050: DMTSSetIJacobian - set `TS` Jacobian evaluation function
1052: Not Collective
1054: Input Parameters:
1055: + dm - `DM` to be used with `TS`
1056: . func - Jacobian evaluation routine
1057: - ctx - context for residual evaluation
1059: Calling sequence of f:
1060: $ PetscErrorCode f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat Amat,Mat Pmat,void *ctx);
1062: + t - time at step/stage being solved
1063: . U - state vector
1064: . U_t - time derivative of state vector
1065: . a - shift
1066: . Amat - (approximate) Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
1067: . Pmat - matrix used for constructing preconditioner, usually the same as Amat
1068: - ctx - [optional] user-defined context for matrix evaluation routine
1070: Level: advanced
1072: Note:
1073: `TSSetJacobian()` is normally used, but it calls this function internally because the user context is actually
1074: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1075: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1077: .seealso: [](chapter_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSGetJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()`
1078: @*/
1079: PetscErrorCode DMTSSetIJacobian(DM dm, TSIJacobian func, void *ctx)
1080: {
1081: DMTS tsdm;
1083: PetscFunctionBegin;
1085: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1086: if (func) tsdm->ops->ijacobian = func;
1087: if (ctx) {
1088: PetscContainer ctxcontainer;
1089: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1090: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1091: PetscCall(PetscObjectCompose((PetscObject)tsdm, "ijacobian ctx", (PetscObject)ctxcontainer));
1092: tsdm->ijacobianctxcontainer = ctxcontainer;
1093: PetscCall(PetscContainerDestroy(&ctxcontainer));
1094: }
1095: PetscFunctionReturn(PETSC_SUCCESS);
1096: }
1098: /*@C
1099: DMTSSetIJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1101: Not Collective
1103: Input Parameters:
1104: + dm - `DM` to be used with `TS`
1105: - f - Jacobian evaluation context destroy function
1107: Level: advanced
1109: Note:
1110: `TSSetIJacobianContextDestroy()` is normally used, but it calls this function internally because the user context is actually
1111: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1112: not.
1114: Developer Note:
1115: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1117: .seealso: [](chapter_ts), `TSSetIJacobianContextDestroy()`, `TSSetI2JacobianContextDestroy()`, `DMTSSetIJacobian()`, `TSSetIJacobian()`
1118: @*/
1119: PetscErrorCode DMTSSetIJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1120: {
1121: DMTS tsdm;
1123: PetscFunctionBegin;
1125: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1126: if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->ijacobianctxcontainer, f));
1127: PetscFunctionReturn(PETSC_SUCCESS);
1128: }
1130: PetscErrorCode DMTSUnsetIJacobianContext_Internal(DM dm)
1131: {
1132: DMTS tsdm;
1134: PetscFunctionBegin;
1136: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1137: PetscCall(DMTSUnsetIJacobianContext_DMTS(tsdm));
1138: PetscFunctionReturn(PETSC_SUCCESS);
1139: }
1141: /*@C
1142: DMTSGetIJacobian - get `TS` Jacobian evaluation function
1144: Not Collective
1146: Input Parameter:
1147: . dm - `DM` to be used with `TS`
1149: Output Parameters:
1150: + func - Jacobian evaluation function, see `TSSetIJacobian()` for calling sequence
1151: - ctx - context for residual evaluation
1153: Level: advanced
1155: Note:
1156: `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1157: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1158: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1160: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1161: @*/
1162: PetscErrorCode DMTSGetIJacobian(DM dm, TSIJacobian *func, void **ctx)
1163: {
1164: DMTS tsdm;
1166: PetscFunctionBegin;
1168: PetscCall(DMGetDMTS(dm, &tsdm));
1169: if (func) *func = tsdm->ops->ijacobian;
1170: if (ctx) {
1171: if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ijacobianctxcontainer, ctx));
1172: else *ctx = NULL;
1173: }
1174: PetscFunctionReturn(PETSC_SUCCESS);
1175: }
1177: /*@C
1178: DMTSSetRHSJacobian - set `TS` Jacobian evaluation function
1180: Not Collective
1182: Input Parameters:
1183: + dm - `DM` to be used with `TS`
1184: . func - Jacobian evaluation routine
1185: - ctx - context for residual evaluation
1187: Calling sequence of func:
1188: $ PetscErrorCode func(TS ts,PetscReal t,Vec u,Mat A,Mat B,void *ctx);
1190: + t - current timestep
1191: . u - input vector
1192: . Amat - (approximate) Jacobian matrix
1193: . Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
1194: - ctx - [optional] user-defined context for matrix evaluation routine
1196: Level: advanced
1198: Note:
1199: `TSSetJacobian()` is normally used, but it calls this function internally because the user context is actually
1200: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1201: not.
1203: Developer Note:
1204: If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1206: .seealso: [](chapter_ts), `DMTSSetContext()`, `TSSetFunction()`, `DMTSGetJacobian()`, `TSSetRHSJacobian()`
1207: @*/
1208: PetscErrorCode DMTSSetRHSJacobian(DM dm, TSRHSJacobian func, void *ctx)
1209: {
1210: DMTS tsdm;
1212: PetscFunctionBegin;
1214: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1215: if (func) tsdm->ops->rhsjacobian = func;
1216: if (ctx) {
1217: PetscContainer ctxcontainer;
1218: PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1219: PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1220: PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs jacobian ctx", (PetscObject)ctxcontainer));
1221: tsdm->rhsjacobianctxcontainer = ctxcontainer;
1222: PetscCall(PetscContainerDestroy(&ctxcontainer));
1223: }
1224: PetscFunctionReturn(PETSC_SUCCESS);
1225: }
1227: /*@C
1228: DMTSSetRHSJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function
1230: Not Collective
1232: Input Parameters:
1233: + dm - `DM` to be used with `TS`
1234: - f - Jacobian evaluation context destroy function
1236: Level: advanced
1238: Note:
1239: The user usually calls `TSSetRHSJacobianContextDestroy()` which calls this routine
1241: .seealso: [](chapter_ts), `TS`, `TSSetRHSJacobianContextDestroy()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1242: @*/
1243: PetscErrorCode DMTSSetRHSJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1244: {
1245: DMTS tsdm;
1247: PetscFunctionBegin;
1249: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1250: if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->rhsjacobianctxcontainer, f));
1251: PetscFunctionReturn(PETSC_SUCCESS);
1252: }
1254: PetscErrorCode DMTSUnsetRHSJacobianContext_Internal(DM dm)
1255: {
1256: DMTS tsdm;
1258: PetscFunctionBegin;
1260: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1261: PetscCall(DMTSUnsetRHSJacobianContext_DMTS(tsdm));
1262: PetscFunctionReturn(PETSC_SUCCESS);
1263: }
1265: /*@C
1266: DMTSGetRHSJacobian - get `TS` Jacobian evaluation function
1268: Not Collective
1270: Input Parameter:
1271: . dm - `DM` to be used with `TS`
1273: Output Parameters:
1274: + func - Jacobian evaluation function, see `TSSetRHSJacobian()` for calling sequence
1275: - ctx - context for residual evaluation
1277: Level: advanced
1279: Note:
1280: `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1281: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
1282: not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
1284: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1285: @*/
1286: PetscErrorCode DMTSGetRHSJacobian(DM dm, TSRHSJacobian *func, void **ctx)
1287: {
1288: DMTS tsdm;
1290: PetscFunctionBegin;
1292: PetscCall(DMGetDMTS(dm, &tsdm));
1293: if (func) *func = tsdm->ops->rhsjacobian;
1294: if (ctx) {
1295: if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsjacobianctxcontainer, ctx));
1296: else *ctx = NULL;
1297: }
1298: PetscFunctionReturn(PETSC_SUCCESS);
1299: }
1301: /*@C
1302: DMTSSetIFunctionSerialize - sets functions used to view and load a IFunction context
1304: Not Collective
1306: Input Parameters:
1307: + dm - `DM` to be used with `TS`
1308: . view - viewer function
1309: - load - loading function
1311: Level: advanced
1313: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1314: @*/
1315: PetscErrorCode DMTSSetIFunctionSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1316: {
1317: DMTS tsdm;
1319: PetscFunctionBegin;
1321: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1322: tsdm->ops->ifunctionview = view;
1323: tsdm->ops->ifunctionload = load;
1324: PetscFunctionReturn(PETSC_SUCCESS);
1325: }
1327: /*@C
1328: DMTSSetIJacobianSerialize - sets functions used to view and load a IJacobian context
1330: Not Collective
1332: Input Parameters:
1333: + dm - `DM` to be used with `TS`
1334: . view - viewer function
1335: - load - loading function
1337: Level: advanced
1339: .seealso: [](chapter_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1340: @*/
1341: PetscErrorCode DMTSSetIJacobianSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1342: {
1343: DMTS tsdm;
1345: PetscFunctionBegin;
1347: PetscCall(DMGetDMTSWrite(dm, &tsdm));
1348: tsdm->ops->ijacobianview = view;
1349: tsdm->ops->ijacobianload = load;
1350: PetscFunctionReturn(PETSC_SUCCESS);
1351: }