Actual source code: dmts.c

  1: #include <petsc/private/tsimpl.h>
  2: #include <petsc/private/dmimpl.h>

  4: static PetscErrorCode DMTSUnsetRHSFunctionContext_DMTS(DMTS tsdm)
  5: {
  6:   PetscFunctionBegin;
  7:   PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", NULL));
  8:   tsdm->rhsfunctionctxcontainer = NULL;
  9:   PetscFunctionReturn(PETSC_SUCCESS);
 10: }

 12: static PetscErrorCode DMTSUnsetRHSJacobianContext_DMTS(DMTS tsdm)
 13: {
 14:   PetscFunctionBegin;
 15:   PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs jacobian ctx", NULL));
 16:   tsdm->rhsjacobianctxcontainer = NULL;
 17:   PetscFunctionReturn(PETSC_SUCCESS);
 18: }

 20: static PetscErrorCode DMTSUnsetIFunctionContext_DMTS(DMTS tsdm)
 21: {
 22:   PetscFunctionBegin;
 23:   PetscCall(PetscObjectCompose((PetscObject)tsdm, "ifunction ctx", NULL));
 24:   tsdm->ifunctionctxcontainer = NULL;
 25:   PetscFunctionReturn(PETSC_SUCCESS);
 26: }

 28: static PetscErrorCode DMTSUnsetIJacobianContext_DMTS(DMTS tsdm)
 29: {
 30:   PetscFunctionBegin;
 31:   PetscCall(PetscObjectCompose((PetscObject)tsdm, "ijacobian ctx", NULL));
 32:   tsdm->ijacobianctxcontainer = NULL;
 33:   PetscFunctionReturn(PETSC_SUCCESS);
 34: }

 36: static PetscErrorCode DMTSUnsetI2FunctionContext_DMTS(DMTS tsdm)
 37: {
 38:   PetscFunctionBegin;
 39:   PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2function ctx", NULL));
 40:   tsdm->i2functionctxcontainer = NULL;
 41:   PetscFunctionReturn(PETSC_SUCCESS);
 42: }

 44: static PetscErrorCode DMTSUnsetI2JacobianContext_DMTS(DMTS tsdm)
 45: {
 46:   PetscFunctionBegin;
 47:   PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2jacobian ctx", NULL));
 48:   tsdm->i2jacobianctxcontainer = NULL;
 49:   PetscFunctionReturn(PETSC_SUCCESS);
 50: }

 52: static PetscErrorCode DMTSDestroy(DMTS *kdm)
 53: {
 54:   PetscFunctionBegin;
 55:   if (!*kdm) PetscFunctionReturn(PETSC_SUCCESS);
 57:   if (--((PetscObject)(*kdm))->refct > 0) {
 58:     *kdm = NULL;
 59:     PetscFunctionReturn(PETSC_SUCCESS);
 60:   }
 61:   PetscCall(DMTSUnsetRHSFunctionContext_DMTS(*kdm));
 62:   PetscCall(DMTSUnsetRHSJacobianContext_DMTS(*kdm));
 63:   PetscCall(DMTSUnsetIFunctionContext_DMTS(*kdm));
 64:   PetscCall(DMTSUnsetIJacobianContext_DMTS(*kdm));
 65:   PetscCall(DMTSUnsetI2FunctionContext_DMTS(*kdm));
 66:   PetscCall(DMTSUnsetI2JacobianContext_DMTS(*kdm));
 67:   PetscTryTypeMethod(*kdm, destroy);
 68:   PetscCall(PetscHeaderDestroy(kdm));
 69:   PetscFunctionReturn(PETSC_SUCCESS);
 70: }

 72: PetscErrorCode DMTSLoad(DMTS kdm, PetscViewer viewer)
 73: {
 74:   PetscFunctionBegin;
 75:   PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ifunction, 1, NULL, PETSC_FUNCTION));
 76:   PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ifunctionview, 1, NULL, PETSC_FUNCTION));
 77:   PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ifunctionload, 1, NULL, PETSC_FUNCTION));
 78:   if (kdm->ops->ifunctionload) {
 79:     void *ctx;

 81:     PetscCall(PetscContainerGetPointer(kdm->ifunctionctxcontainer, &ctx));
 82:     PetscCall((*kdm->ops->ifunctionload)(&ctx, viewer));
 83:   }
 84:   PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ijacobian, 1, NULL, PETSC_FUNCTION));
 85:   PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ijacobianview, 1, NULL, PETSC_FUNCTION));
 86:   PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->ijacobianload, 1, NULL, PETSC_FUNCTION));
 87:   if (kdm->ops->ijacobianload) {
 88:     void *ctx;

 90:     PetscCall(PetscContainerGetPointer(kdm->ijacobianctxcontainer, &ctx));
 91:     PetscCall((*kdm->ops->ijacobianload)(&ctx, viewer));
 92:   }
 93:   PetscFunctionReturn(PETSC_SUCCESS);
 94: }

 96: PetscErrorCode DMTSView(DMTS kdm, PetscViewer viewer)
 97: {
 98:   PetscBool isascii, isbinary;

100:   PetscFunctionBegin;
101:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
102:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
103:   if (isascii) {
104: #if defined(PETSC_SERIALIZE_FUNCTIONS)
105:     const char *fname;

107:     PetscCall(PetscFPTFind(kdm->ops->ifunction, &fname));
108:     if (fname) PetscCall(PetscViewerASCIIPrintf(viewer, "  IFunction used by TS: %s\n", fname));
109:     PetscCall(PetscFPTFind(kdm->ops->ijacobian, &fname));
110:     if (fname) PetscCall(PetscViewerASCIIPrintf(viewer, "  IJacobian function used by TS: %s\n", fname));
111: #endif
112:   } else if (isbinary) {
113:     struct {
114:       TSIFunction ifunction;
115:     } funcstruct;
116:     struct {
117:       PetscErrorCode (*ifunctionview)(void *, PetscViewer);
118:     } funcviewstruct;
119:     struct {
120:       PetscErrorCode (*ifunctionload)(void **, PetscViewer);
121:     } funcloadstruct;
122:     struct {
123:       TSIJacobian ijacobian;
124:     } jacstruct;
125:     struct {
126:       PetscErrorCode (*ijacobianview)(void *, PetscViewer);
127:     } jacviewstruct;
128:     struct {
129:       PetscErrorCode (*ijacobianload)(void **, PetscViewer);
130:     } jacloadstruct;

132:     funcstruct.ifunction         = kdm->ops->ifunction;
133:     funcviewstruct.ifunctionview = kdm->ops->ifunctionview;
134:     funcloadstruct.ifunctionload = kdm->ops->ifunctionload;
135:     PetscCall(PetscViewerBinaryWrite(viewer, &funcstruct, 1, PETSC_FUNCTION));
136:     PetscCall(PetscViewerBinaryWrite(viewer, &funcviewstruct, 1, PETSC_FUNCTION));
137:     PetscCall(PetscViewerBinaryWrite(viewer, &funcloadstruct, 1, PETSC_FUNCTION));
138:     if (kdm->ops->ifunctionview) {
139:       void *ctx;

141:       PetscCall(PetscContainerGetPointer(kdm->ifunctionctxcontainer, &ctx));
142:       PetscCall((*kdm->ops->ifunctionview)(ctx, viewer));
143:     }
144:     jacstruct.ijacobian         = kdm->ops->ijacobian;
145:     jacviewstruct.ijacobianview = kdm->ops->ijacobianview;
146:     jacloadstruct.ijacobianload = kdm->ops->ijacobianload;
147:     PetscCall(PetscViewerBinaryWrite(viewer, &jacstruct, 1, PETSC_FUNCTION));
148:     PetscCall(PetscViewerBinaryWrite(viewer, &jacviewstruct, 1, PETSC_FUNCTION));
149:     PetscCall(PetscViewerBinaryWrite(viewer, &jacloadstruct, 1, PETSC_FUNCTION));
150:     if (kdm->ops->ijacobianview) {
151:       void *ctx;

153:       PetscCall(PetscContainerGetPointer(kdm->ijacobianctxcontainer, &ctx));
154:       PetscCall((*kdm->ops->ijacobianview)(ctx, viewer));
155:     }
156:   }
157:   PetscFunctionReturn(PETSC_SUCCESS);
158: }

160: static PetscErrorCode DMTSCreate(MPI_Comm comm, DMTS *kdm)
161: {
162:   PetscFunctionBegin;
163:   PetscCall(TSInitializePackage());
164:   PetscCall(PetscHeaderCreate(*kdm, DMTS_CLASSID, "DMTS", "DMTS", "DMTS", comm, DMTSDestroy, DMTSView));
165:   PetscFunctionReturn(PETSC_SUCCESS);
166: }

168: /* Attaches the DMTS to the coarse level.
169:  * Under what conditions should we copy versus duplicate?
170:  */
171: static PetscErrorCode DMCoarsenHook_DMTS(DM dm, DM dmc, void *ctx)
172: {
173:   PetscFunctionBegin;
174:   PetscCall(DMCopyDMTS(dm, dmc));
175:   PetscFunctionReturn(PETSC_SUCCESS);
176: }

178: /* This could restrict auxiliary information to the coarse level.
179:  */
180: static PetscErrorCode DMRestrictHook_DMTS(DM dm, Mat Restrict, Vec rscale, Mat Inject, DM dmc, void *ctx)
181: {
182:   PetscFunctionBegin;
183:   PetscFunctionReturn(PETSC_SUCCESS);
184: }

186: static PetscErrorCode DMSubDomainHook_DMTS(DM dm, DM subdm, void *ctx)
187: {
188:   PetscFunctionBegin;
189:   PetscCall(DMCopyDMTS(dm, subdm));
190:   PetscFunctionReturn(PETSC_SUCCESS);
191: }

193: /* This could restrict auxiliary information to the coarse level.
194:  */
195: static PetscErrorCode DMSubDomainRestrictHook_DMTS(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, void *ctx)
196: {
197:   PetscFunctionBegin;
198:   PetscFunctionReturn(PETSC_SUCCESS);
199: }

201: /*@C
202:   DMTSCopy - copies the information in a `DMTS` to another `DMTS`

204:   Not Collective

206:   Input Parameters:
207: + kdm  - Original `DMTS`
208: - nkdm - `DMTS` to receive the data, should have been created with `DMTSCreate()`

210:   Level: developer

212: .seealso: [](ch_ts), `DMTSCreate()`, `DMTSDestroy()`
213: @*/
214: PetscErrorCode DMTSCopy(DMTS kdm, DMTS nkdm)
215: {
216:   PetscFunctionBegin;
219:   nkdm->ops->rhsfunction = kdm->ops->rhsfunction;
220:   nkdm->ops->rhsjacobian = kdm->ops->rhsjacobian;
221:   nkdm->ops->ifunction   = kdm->ops->ifunction;
222:   nkdm->ops->ijacobian   = kdm->ops->ijacobian;
223:   nkdm->ops->i2function  = kdm->ops->i2function;
224:   nkdm->ops->i2jacobian  = kdm->ops->i2jacobian;
225:   nkdm->ops->solution    = kdm->ops->solution;
226:   nkdm->ops->destroy     = kdm->ops->destroy;
227:   nkdm->ops->duplicate   = kdm->ops->duplicate;

229:   nkdm->solutionctx             = kdm->solutionctx;
230:   nkdm->rhsfunctionctxcontainer = kdm->rhsfunctionctxcontainer;
231:   nkdm->rhsjacobianctxcontainer = kdm->rhsjacobianctxcontainer;
232:   nkdm->ifunctionctxcontainer   = kdm->ifunctionctxcontainer;
233:   nkdm->ijacobianctxcontainer   = kdm->ijacobianctxcontainer;
234:   nkdm->i2functionctxcontainer  = kdm->i2functionctxcontainer;
235:   nkdm->i2jacobianctxcontainer  = kdm->i2jacobianctxcontainer;
236:   if (nkdm->rhsfunctionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "rhs function ctx", (PetscObject)nkdm->rhsfunctionctxcontainer));
237:   if (nkdm->rhsjacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "rhs jacobian ctx", (PetscObject)nkdm->rhsjacobianctxcontainer));
238:   if (nkdm->ifunctionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "ifunction ctx", (PetscObject)nkdm->ifunctionctxcontainer));
239:   if (nkdm->ijacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "ijacobian ctx", (PetscObject)nkdm->ijacobianctxcontainer));
240:   if (nkdm->i2functionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "i2function ctx", (PetscObject)nkdm->i2functionctxcontainer));
241:   if (nkdm->i2jacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "i2jacobian ctx", (PetscObject)nkdm->i2jacobianctxcontainer));

243:   nkdm->data = kdm->data;

245:   /*
246:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
247:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
248:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
249:   */

251:   /* implementation specific copy hooks */
252:   PetscTryTypeMethod(kdm, duplicate, nkdm);
253:   PetscFunctionReturn(PETSC_SUCCESS);
254: }

256: /*@C
257:   DMGetDMTS - get read-only private `DMTS` context from a `DM`

259:   Not Collective

261:   Input Parameter:
262: . dm - `DM` to be used with `TS`

264:   Output Parameter:
265: . tsdm - private `DMTS` context

267:   Level: developer

269:   Notes:
270:   Use `DMGetDMTSWrite()` if write access is needed. The `DMTSSetXXX()` API should be used wherever possible.

272: .seealso: [](ch_ts), `DMTS`, `DMGetDMTSWrite()`
273: @*/
274: PetscErrorCode DMGetDMTS(DM dm, DMTS *tsdm)
275: {
276:   PetscFunctionBegin;
278:   *tsdm = (DMTS)dm->dmts;
279:   if (!*tsdm) {
280:     PetscCall(PetscInfo(dm, "Creating new DMTS\n"));
281:     PetscCall(DMTSCreate(PetscObjectComm((PetscObject)dm), tsdm));
282:     dm->dmts            = (PetscObject)*tsdm;
283:     (*tsdm)->originaldm = dm;
284:     PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_DMTS, DMRestrictHook_DMTS, NULL));
285:     PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_DMTS, DMSubDomainRestrictHook_DMTS, NULL));
286:   }
287:   PetscFunctionReturn(PETSC_SUCCESS);
288: }

290: /*@C
291:   DMGetDMTSWrite - get write access to private `DMTS` context from a `DM`

293:   Not Collective

295:   Input Parameter:
296: . dm - `DM` to be used with `TS`

298:   Output Parameter:
299: . tsdm - private `DMTS` context

301:   Level: developer

303: .seealso: [](ch_ts), `DMTS`, `DMGetDMTS()`
304: @*/
305: PetscErrorCode DMGetDMTSWrite(DM dm, DMTS *tsdm)
306: {
307:   DMTS sdm;

309:   PetscFunctionBegin;
311:   PetscCall(DMGetDMTS(dm, &sdm));
312:   PetscCheck(sdm->originaldm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DMTS has a NULL originaldm");
313:   if (sdm->originaldm != dm) { /* Copy on write */
314:     DMTS oldsdm = sdm;
315:     PetscCall(PetscInfo(dm, "Copying DMTS due to write\n"));
316:     PetscCall(DMTSCreate(PetscObjectComm((PetscObject)dm), &sdm));
317:     PetscCall(DMTSCopy(oldsdm, sdm));
318:     PetscCall(DMTSDestroy((DMTS *)&dm->dmts));
319:     dm->dmts        = (PetscObject)sdm;
320:     sdm->originaldm = dm;
321:   }
322:   *tsdm = sdm;
323:   PetscFunctionReturn(PETSC_SUCCESS);
324: }

326: /*@C
327:   DMCopyDMTS - copies a `DM` context to a new `DM`

329:   Logically Collective

331:   Input Parameters:
332: + dmsrc  - `DM` to obtain context from
333: - dmdest - `DM` to add context to

335:   Level: developer

337:   Note:
338:   The context is copied by reference. This function does not ensure that a context exists.

340: .seealso: [](ch_ts), `DMTS`, `DMGetDMTS()`, `TSSetDM()`
341: @*/
342: PetscErrorCode DMCopyDMTS(DM dmsrc, DM dmdest)
343: {
344:   PetscFunctionBegin;
347:   PetscCall(DMTSDestroy((DMTS *)&dmdest->dmts));
348:   dmdest->dmts = dmsrc->dmts;
349:   PetscCall(PetscObjectReference(dmdest->dmts));
350:   PetscCall(DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMTS, DMRestrictHook_DMTS, NULL));
351:   PetscCall(DMSubDomainHookAdd(dmdest, DMSubDomainHook_DMTS, DMSubDomainRestrictHook_DMTS, NULL));
352:   PetscFunctionReturn(PETSC_SUCCESS);
353: }

355: /*@C
356:   DMTSSetIFunction - set `TS` implicit function evaluation function

358:   Not Collective

360:   Input Parameters:
361: + dm   - `DM` to be used with `TS`
362: . func - function evaluating f(t,u,u_t)
363: - ctx  - context for residual evaluation

365:   Level: advanced

367:   Note:
368:   `TSSetFunction()` is normally used, but it calls this function internally because the user context is actually
369:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
370:   not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.

372: .seealso: [](ch_ts), `TS`, `DM`, `TSIFunction`, `DMTSSetContext()`, `TSSetIFunction()`,
373: `DMTSSetJacobian()`
374: @*/
375: PetscErrorCode DMTSSetIFunction(DM dm, TSIFunction func, void *ctx)
376: {
377:   DMTS tsdm;

379:   PetscFunctionBegin;
381:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
382:   if (func) tsdm->ops->ifunction = func;
383:   if (ctx) {
384:     PetscContainer ctxcontainer;
385:     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
386:     PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
387:     PetscCall(PetscObjectCompose((PetscObject)tsdm, "ifunction ctx", (PetscObject)ctxcontainer));
388:     tsdm->ifunctionctxcontainer = ctxcontainer;
389:     PetscCall(PetscContainerDestroy(&ctxcontainer));
390:   }
391:   PetscFunctionReturn(PETSC_SUCCESS);
392: }

394: /*@C
395:   DMTSSetIFunctionContextDestroy - set `TS` implicit evaluation context destroy function

397:   Not Collective

399:   Input Parameters:
400: + dm - `DM` to be used with `TS`
401: - f  - implicit evaluation context destroy function

403:   Level: advanced

405: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetIFunction()`, `TSSetIFunction()`
406: @*/
407: PetscErrorCode DMTSSetIFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
408: {
409:   DMTS tsdm;

411:   PetscFunctionBegin;
413:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
414:   if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->ifunctionctxcontainer, f));
415:   PetscFunctionReturn(PETSC_SUCCESS);
416: }

418: PetscErrorCode DMTSUnsetIFunctionContext_Internal(DM dm)
419: {
420:   DMTS tsdm;

422:   PetscFunctionBegin;
424:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
425:   PetscCall(DMTSUnsetIFunctionContext_DMTS(tsdm));
426:   PetscFunctionReturn(PETSC_SUCCESS);
427: }

429: /*@C
430:   DMTSGetIFunction - get `TS` implicit residual evaluation function

432:   Not Collective

434:   Input Parameter:
435: . dm - `DM` to be used with `TS`

437:   Output Parameters:
438: + func - function evaluation function, for calling sequence see `TSSetIFunction()`
439: - ctx  - context for residual evaluation

441:   Level: advanced

443:   Note:
444:   `TSGetFunction()` is normally used, but it calls this function internally because the user context is actually
445:   associated with the `DM`.

447: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `DMTSSetFunction()`, `TSSetFunction()`
448: @*/
449: PetscErrorCode DMTSGetIFunction(DM dm, TSIFunction *func, void **ctx)
450: {
451:   DMTS tsdm;

453:   PetscFunctionBegin;
455:   PetscCall(DMGetDMTS(dm, &tsdm));
456:   if (func) *func = tsdm->ops->ifunction;
457:   if (ctx) {
458:     if (tsdm->ifunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ifunctionctxcontainer, ctx));
459:     else *ctx = NULL;
460:   }
461:   PetscFunctionReturn(PETSC_SUCCESS);
462: }

464: /*@C
465:   DMTSSetI2Function - set `TS` implicit function evaluation function for 2nd order systems

467:   Not Collective

469:   Input Parameters:
470: + dm  - `DM` to be used with `TS`
471: . fun - function evaluation routine
472: - ctx - context for residual evaluation

474:   Level: advanced

476:   Note:
477:   `TSSetI2Function()` is normally used, but it calls this function internally because the user context is actually
478:   associated with the `DM`.

480: .seealso: [](ch_ts), `DM`, `TS`, `TSSetI2Function()`
481: @*/
482: PetscErrorCode DMTSSetI2Function(DM dm, TSI2Function fun, void *ctx)
483: {
484:   DMTS tsdm;

486:   PetscFunctionBegin;
488:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
489:   if (fun) tsdm->ops->i2function = fun;
490:   if (ctx) {
491:     PetscContainer ctxcontainer;
492:     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
493:     PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
494:     PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2function ctx", (PetscObject)ctxcontainer));
495:     tsdm->i2functionctxcontainer = ctxcontainer;
496:     PetscCall(PetscContainerDestroy(&ctxcontainer));
497:   }
498:   PetscFunctionReturn(PETSC_SUCCESS);
499: }

501: /*@C
502:   DMTSSetI2FunctionContextDestroy - set `TS` implicit evaluation for 2nd order systems context destroy

504:   Not Collective

506:   Input Parameters:
507: + dm - `DM` to be used with `TS`
508: - f  - implicit evaluation context destroy function

510:   Level: advanced

512:   Note:
513:   `TSSetI2FunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
514:   associated with the `DM`.

516: .seealso: [](ch_ts), `TSSetI2FunctionContextDestroy()`, `DMTSSetI2Function()`, `TSSetI2Function()`
517: @*/
518: PetscErrorCode DMTSSetI2FunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
519: {
520:   DMTS tsdm;

522:   PetscFunctionBegin;
524:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
525:   if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->i2functionctxcontainer, f));
526:   PetscFunctionReturn(PETSC_SUCCESS);
527: }

529: PetscErrorCode DMTSUnsetI2FunctionContext_Internal(DM dm)
530: {
531:   DMTS tsdm;

533:   PetscFunctionBegin;
535:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
536:   PetscCall(DMTSUnsetI2FunctionContext_DMTS(tsdm));
537:   PetscFunctionReturn(PETSC_SUCCESS);
538: }

540: /*@C
541:   DMTSGetI2Function - get `TS` implicit residual evaluation function for 2nd order systems

543:   Not Collective

545:   Input Parameter:
546: . dm - `DM` to be used with `TS`

548:   Output Parameters:
549: + fun - function evaluation function, for calling sequence see `TSSetI2Function()`
550: - ctx - context for residual evaluation

552:   Level: advanced

554:   Note:
555:   `TSGetI2Function()` is normally used, but it calls this function internally because the user context is actually
556:   associated with the `DM`.

558: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetI2Function()`, `TSGetI2Function()`
559: @*/
560: PetscErrorCode DMTSGetI2Function(DM dm, TSI2Function *fun, void **ctx)
561: {
562:   DMTS tsdm;

564:   PetscFunctionBegin;
566:   PetscCall(DMGetDMTS(dm, &tsdm));
567:   if (fun) *fun = tsdm->ops->i2function;
568:   if (ctx) {
569:     if (tsdm->i2functionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2functionctxcontainer, ctx));
570:     else *ctx = NULL;
571:   }
572:   PetscFunctionReturn(PETSC_SUCCESS);
573: }

575: /*@C
576:   DMTSSetI2Jacobian - set `TS` implicit Jacobian evaluation function for 2nd order systems

578:   Not Collective

580:   Input Parameters:
581: + dm  - `DM` to be used with `TS`
582: . jac - Jacobian evaluation routine
583: - ctx - context for Jacobian evaluation

585:   Level: advanced

587:   Note:
588:   `TSSetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
589:   associated with the `DM`.

591: .seealso: [](ch_ts), `DM`, `TS`, `TSI2Jacobian`, `TSSetI2Jacobian()`
592: @*/
593: PetscErrorCode DMTSSetI2Jacobian(DM dm, TSI2Jacobian jac, void *ctx)
594: {
595:   DMTS tsdm;

597:   PetscFunctionBegin;
599:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
600:   if (jac) tsdm->ops->i2jacobian = jac;
601:   if (ctx) {
602:     PetscContainer ctxcontainer;
603:     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
604:     PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
605:     PetscCall(PetscObjectCompose((PetscObject)tsdm, "i2jacobian ctx", (PetscObject)ctxcontainer));
606:     tsdm->i2jacobianctxcontainer = ctxcontainer;
607:     PetscCall(PetscContainerDestroy(&ctxcontainer));
608:   }
609:   PetscFunctionReturn(PETSC_SUCCESS);
610: }

612: /*@C
613:   DMTSSetI2JacobianContextDestroy - set `TS` implicit Jacobian evaluation for 2nd order systems context destroy function

615:   Not Collective

617:   Input Parameters:
618: + dm - `DM` to be used with `TS`
619: - f  - implicit Jacobian evaluation context destroy function

621:   Level: advanced

623: .seealso: [](ch_ts), `DM`, `TS`, `TSSetI2JacobianContextDestroy()`, `DMTSSetI2Jacobian()`, `TSSetI2Jacobian()`
624: @*/
625: PetscErrorCode DMTSSetI2JacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
626: {
627:   DMTS tsdm;

629:   PetscFunctionBegin;
631:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
632:   if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->i2jacobianctxcontainer, f));
633:   PetscFunctionReturn(PETSC_SUCCESS);
634: }

636: PetscErrorCode DMTSUnsetI2JacobianContext_Internal(DM dm)
637: {
638:   DMTS tsdm;

640:   PetscFunctionBegin;
642:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
643:   PetscCall(DMTSUnsetI2JacobianContext_DMTS(tsdm));
644:   PetscFunctionReturn(PETSC_SUCCESS);
645: }

647: /*@C
648:   DMTSGetI2Jacobian - get `TS` implicit Jacobian evaluation function for 2nd order systems

650:   Not Collective

652:   Input Parameter:
653: . dm - `DM` to be used with `TS`

655:   Output Parameters:
656: + jac - Jacobian evaluation function,  for calling sequence see `TSSetI2Jacobian()`
657: - ctx - context for Jacobian evaluation

659:   Level: advanced

661:   Note:
662:   `TSGetI2Jacobian()` is normally used, but it calls this function internally because the user context is actually
663:   associated with the `DM`.

665: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetI2Jacobian()`, `TSGetI2Jacobian()`
666: @*/
667: PetscErrorCode DMTSGetI2Jacobian(DM dm, TSI2Jacobian *jac, void **ctx)
668: {
669:   DMTS tsdm;

671:   PetscFunctionBegin;
673:   PetscCall(DMGetDMTS(dm, &tsdm));
674:   if (jac) *jac = tsdm->ops->i2jacobian;
675:   if (ctx) {
676:     if (tsdm->i2jacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->i2jacobianctxcontainer, ctx));
677:     else *ctx = NULL;
678:   }
679:   PetscFunctionReturn(PETSC_SUCCESS);
680: }

682: /*@C
683:   DMTSSetRHSFunction - set `TS` explicit residual evaluation function

685:   Not Collective

687:   Input Parameters:
688: + dm   - `DM` to be used with `TS`
689: . func - RHS function evaluation routine
690: - ctx  - context for residual evaluation

692:   Level: advanced

694:   Note:
695:   `TSSetRHSFunction()` is normally used, but it calls this function internally because the user context is actually
696:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
697:   not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.

699: .seealso: [](ch_ts), `DM`, `TS`, `TSRHSFunction`, `DMTSSetContext()`, `TSSetRHSFunction()`,
700: `DMTSSetJacobian()`
701: @*/
702: PetscErrorCode DMTSSetRHSFunction(DM dm, TSRHSFunction func, void *ctx)
703: {
704:   DMTS tsdm;

706:   PetscFunctionBegin;
708:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
709:   if (func) tsdm->ops->rhsfunction = func;
710:   if (ctx) {
711:     PetscContainer ctxcontainer;
712:     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
713:     PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
714:     PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs function ctx", (PetscObject)ctxcontainer));
715:     tsdm->rhsfunctionctxcontainer = ctxcontainer;
716:     PetscCall(PetscContainerDestroy(&ctxcontainer));
717:   }
718:   PetscFunctionReturn(PETSC_SUCCESS);
719: }

721: /*@C
722:   DMTSSetRHSFunctionContextDestroy - set `TS` explicit residual evaluation context destroy function

724:   Not Collective

726:   Input Parameters:
727: + dm - `DM` to be used with `TS`
728: - f  - explicit evaluation context destroy function

730:   Level: advanced

732:   Note:
733:   `TSSetRHSFunctionContextDestroy()` is normally used, but it calls this function internally because the user context is actually
734:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
735:   not.

737:   Developer Notes:
738:   If `DM` took a more central role at some later date, this could become the primary method of setting the residual.

740: .seealso: [](ch_ts), `TSSetRHSFunctionContextDestroy()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
741: @*/
742: PetscErrorCode DMTSSetRHSFunctionContextDestroy(DM dm, PetscErrorCode (*f)(void *))
743: {
744:   DMTS tsdm;

746:   PetscFunctionBegin;
748:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
749:   if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->rhsfunctionctxcontainer, f));
750:   PetscFunctionReturn(PETSC_SUCCESS);
751: }

753: PetscErrorCode DMTSUnsetRHSFunctionContext_Internal(DM dm)
754: {
755:   DMTS tsdm;

757:   PetscFunctionBegin;
759:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
760:   PetscCall(DMTSUnsetRHSFunctionContext_DMTS(tsdm));
761:   tsdm->rhsfunctionctxcontainer = NULL;
762:   PetscFunctionReturn(PETSC_SUCCESS);
763: }

765: /*@C
766:   DMTSSetTransientVariable - sets function to transform from state to transient variables

768:   Logically Collective

770:   Input Parameters:
771: + dm   - `DM` to be used with `TS`
772: . tvar - a function that transforms to transient variables
773: - ctx  - a context for tvar

775:   Level: advanced

777:   Notes:
778:   This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`)
779:   can be conservative.  In this context, primitive variables P are used to model the state (e.g., because they lead to
780:   well-conditioned formulations even in limiting cases such as low-Mach or zero porosity).  The transient variable is
781:   C(P), specified by calling this function.  An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
782:   evaluated via the chain rule, as in

784:   dF/dP + shift * dF/dCdot dC/dP.

786: .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSetTransientVariable()`, `DMTSGetTransientVariable()`, `DMTSSetIFunction()`, `DMTSSetIJacobian()`
787: @*/
788: PetscErrorCode DMTSSetTransientVariable(DM dm, TSTransientVariable tvar, void *ctx)
789: {
790:   DMTS dmts;

792:   PetscFunctionBegin;
794:   PetscCall(DMGetDMTSWrite(dm, &dmts));
795:   dmts->ops->transientvar = tvar;
796:   dmts->transientvarctx   = ctx;
797:   PetscFunctionReturn(PETSC_SUCCESS);
798: }

800: /*@C
801:   DMTSGetTransientVariable - gets function to transform from state to transient variables set with `DMTSSetTransientVariable()`

803:   Logically Collective

805:   Input Parameter:
806: . dm - `DM` to be used with `TS`

808:   Output Parameters:
809: + tvar - a function that transforms to transient variables
810: - ctx  - a context for tvar

812:   Level: advanced

814: .seealso: [](ch_ts), `DM`, `DMTSSetTransientVariable()`, `DMTSGetIFunction()`, `DMTSGetIJacobian()`
815: @*/
816: PetscErrorCode DMTSGetTransientVariable(DM dm, TSTransientVariable *tvar, void *ctx)
817: {
818:   DMTS dmts;

820:   PetscFunctionBegin;
822:   PetscCall(DMGetDMTS(dm, &dmts));
823:   if (tvar) *tvar = dmts->ops->transientvar;
824:   if (ctx) *(void **)ctx = dmts->transientvarctx;
825:   PetscFunctionReturn(PETSC_SUCCESS);
826: }

828: /*@C
829:   DMTSGetSolutionFunction - gets the `TS` solution evaluation function

831:   Not Collective

833:   Input Parameter:
834: . dm - `DM` to be used with `TS`

836:   Output Parameters:
837: + func - solution function evaluation function, for calling sequence see `TSSetSolution()`
838: - ctx  - context for solution evaluation

840:   Level: advanced

842: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSSetSolutionFunction()`
843: @*/
844: PetscErrorCode DMTSGetSolutionFunction(DM dm, TSSolutionFunction *func, void **ctx)
845: {
846:   DMTS tsdm;

848:   PetscFunctionBegin;
850:   PetscCall(DMGetDMTS(dm, &tsdm));
851:   if (func) *func = tsdm->ops->solution;
852:   if (ctx) *ctx = tsdm->solutionctx;
853:   PetscFunctionReturn(PETSC_SUCCESS);
854: }

856: /*@C
857:   DMTSSetSolutionFunction - set `TS` solution evaluation function

859:   Not Collective

861:   Input Parameters:
862: + dm   - `DM` to be used with `TS`
863: . func - solution function evaluation routine
864: - ctx  - context for solution evaluation

866:   Level: advanced

868:   Note:
869:   `TSSetSolutionFunction()` is normally used, but it calls this function internally because the user context is actually
870:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
871:   not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.

873: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `DMTSGetSolutionFunction()`
874: @*/
875: PetscErrorCode DMTSSetSolutionFunction(DM dm, TSSolutionFunction func, void *ctx)
876: {
877:   DMTS tsdm;

879:   PetscFunctionBegin;
881:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
882:   if (func) tsdm->ops->solution = func;
883:   if (ctx) tsdm->solutionctx = ctx;
884:   PetscFunctionReturn(PETSC_SUCCESS);
885: }

887: /*@C
888:   DMTSSetForcingFunction - set `TS` forcing function evaluation function

890:   Not Collective

892:   Input Parameters:
893: + dm   - `DM` to be used with `TS`
894: . func - forcing function evaluation routine
895: - ctx  - context for solution evaluation

897:   Level: advanced

899:   Note:
900:   `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
901:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
902:   not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.

904: .seealso: [](ch_ts), `DM`, `TS`, `TSForcingFunction`, `DMTSSetContext()`, `TSSetFunction()`,
905: `DMTSSetJacobian()`, `TSSetForcingFunction()`, `DMTSGetForcingFunction()`
906: @*/
907: PetscErrorCode DMTSSetForcingFunction(DM dm, TSForcingFunction func, void *ctx)
908: {
909:   DMTS tsdm;

911:   PetscFunctionBegin;
913:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
914:   if (func) tsdm->ops->forcing = func;
915:   if (ctx) tsdm->forcingctx = ctx;
916:   PetscFunctionReturn(PETSC_SUCCESS);
917: }

919: /*@C
920:   DMTSGetForcingFunction - get `TS` forcing function evaluation function

922:   Not Collective

924:   Input Parameter:
925: . dm - `DM` to be used with `TS`

927:   Output Parameters:
928: + f   - forcing function evaluation function; see `TSForcingFunction` for details
929: - ctx - context for solution evaluation

931:   Level: advanced

933:   Note:
934:   `TSSetForcingFunction()` is normally used, but it calls this function internally because the user context is actually
935:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
936:   not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.

938: .seealso: [](ch_ts), `TS`, `DM`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`, `TSSetForcingFunction()`
939: @*/
940: PetscErrorCode DMTSGetForcingFunction(DM dm, TSForcingFunction *f, void **ctx)
941: {
942:   DMTS tsdm;

944:   PetscFunctionBegin;
946:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
947:   if (f) *f = tsdm->ops->forcing;
948:   if (ctx) *ctx = tsdm->forcingctx;
949:   PetscFunctionReturn(PETSC_SUCCESS);
950: }

952: /*@C
953:   DMTSGetRHSFunction - get `TS` explicit residual evaluation function

955:   Not Collective

957:   Input Parameter:
958: . dm - `DM` to be used with `TS`

960:   Output Parameters:
961: + func - residual evaluation function, for calling sequence see `TSSetRHSFunction()`
962: - ctx  - context for residual evaluation

964:   Level: advanced

966:   Note:
967:   `TSGetFunction()` is normally used, but it calls this function internally because the user context is actually
968:   associated with the DM.

970: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `DMTSSetRHSFunction()`, `TSSetRHSFunction()`
971: @*/
972: PetscErrorCode DMTSGetRHSFunction(DM dm, TSRHSFunction *func, void **ctx)
973: {
974:   DMTS tsdm;

976:   PetscFunctionBegin;
978:   PetscCall(DMGetDMTS(dm, &tsdm));
979:   if (func) *func = tsdm->ops->rhsfunction;
980:   if (ctx) {
981:     if (tsdm->rhsfunctionctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsfunctionctxcontainer, ctx));
982:     else *ctx = NULL;
983:   }
984:   PetscFunctionReturn(PETSC_SUCCESS);
985: }

987: /*@C
988:   DMTSSetIJacobian - set `TS` Jacobian evaluation function

990:   Not Collective

992:   Input Parameters:
993: + dm   - `DM` to be used with `TS`
994: . func - Jacobian evaluation routine
995: - ctx  - context for residual evaluation

997:   Level: advanced

999:   Note:
1000:   `TSSetJacobian()` is normally used, but it calls this function internally because the user context is actually
1001:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
1002:   not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.

1004: .seealso: [](ch_ts), `TS`, `DM`, `TSIJacobian`, `DMTSSetContext()`, `TSSetRHSFunction()`,
1005: `DMTSGetJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()`
1006: @*/
1007: PetscErrorCode DMTSSetIJacobian(DM dm, TSIJacobian func, void *ctx)
1008: {
1009:   DMTS tsdm;

1011:   PetscFunctionBegin;
1013:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
1014:   if (func) tsdm->ops->ijacobian = func;
1015:   if (ctx) {
1016:     PetscContainer ctxcontainer;
1017:     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1018:     PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1019:     PetscCall(PetscObjectCompose((PetscObject)tsdm, "ijacobian ctx", (PetscObject)ctxcontainer));
1020:     tsdm->ijacobianctxcontainer = ctxcontainer;
1021:     PetscCall(PetscContainerDestroy(&ctxcontainer));
1022:   }
1023:   PetscFunctionReturn(PETSC_SUCCESS);
1024: }

1026: /*@C
1027:   DMTSSetIJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function

1029:   Not Collective

1031:   Input Parameters:
1032: + dm - `DM` to be used with `TS`
1033: - f  - Jacobian evaluation context destroy function

1035:   Level: advanced

1037:   Note:
1038:   `TSSetIJacobianContextDestroy()` is normally used, but it calls this function internally because the user context is actually
1039:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
1040:   not.

1042:   Developer Notes:
1043:   If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.

1045: .seealso: [](ch_ts), `TSSetIJacobianContextDestroy()`, `TSSetI2JacobianContextDestroy()`, `DMTSSetIJacobian()`, `TSSetIJacobian()`
1046: @*/
1047: PetscErrorCode DMTSSetIJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1048: {
1049:   DMTS tsdm;

1051:   PetscFunctionBegin;
1053:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
1054:   if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->ijacobianctxcontainer, f));
1055:   PetscFunctionReturn(PETSC_SUCCESS);
1056: }

1058: PetscErrorCode DMTSUnsetIJacobianContext_Internal(DM dm)
1059: {
1060:   DMTS tsdm;

1062:   PetscFunctionBegin;
1064:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
1065:   PetscCall(DMTSUnsetIJacobianContext_DMTS(tsdm));
1066:   PetscFunctionReturn(PETSC_SUCCESS);
1067: }

1069: /*@C
1070:   DMTSGetIJacobian - get `TS` Jacobian evaluation function

1072:   Not Collective

1074:   Input Parameter:
1075: . dm - `DM` to be used with `TS`

1077:   Output Parameters:
1078: + func - Jacobian evaluation function, for calling sequence see `TSSetIJacobian()`
1079: - ctx  - context for residual evaluation

1081:   Level: advanced

1083:   Note:
1084:   `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1085:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
1086:   not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.

1088: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1089: @*/
1090: PetscErrorCode DMTSGetIJacobian(DM dm, TSIJacobian *func, void **ctx)
1091: {
1092:   DMTS tsdm;

1094:   PetscFunctionBegin;
1096:   PetscCall(DMGetDMTS(dm, &tsdm));
1097:   if (func) *func = tsdm->ops->ijacobian;
1098:   if (ctx) {
1099:     if (tsdm->ijacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->ijacobianctxcontainer, ctx));
1100:     else *ctx = NULL;
1101:   }
1102:   PetscFunctionReturn(PETSC_SUCCESS);
1103: }

1105: /*@C
1106:   DMTSSetRHSJacobian - set `TS` Jacobian evaluation function

1108:   Not Collective

1110:   Input Parameters:
1111: + dm   - `DM` to be used with `TS`
1112: . func - Jacobian evaluation routine
1113: - ctx  - context for residual evaluation

1115:   Level: advanced

1117:   Note:
1118:   `TSSetJacobian()` is normally used, but it calls this function internally because the user context is actually
1119:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
1120:   not.

1122:   Developer Notes:
1123:   If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.

1125: .seealso: [](ch_ts), `TSRHSJacobian`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSGetJacobian()`, `TSSetRHSJacobian()`
1126: @*/
1127: PetscErrorCode DMTSSetRHSJacobian(DM dm, TSRHSJacobian func, void *ctx)
1128: {
1129:   DMTS tsdm;

1131:   PetscFunctionBegin;
1133:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
1134:   if (func) tsdm->ops->rhsjacobian = func;
1135:   if (ctx) {
1136:     PetscContainer ctxcontainer;
1137:     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)tsdm), &ctxcontainer));
1138:     PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
1139:     PetscCall(PetscObjectCompose((PetscObject)tsdm, "rhs jacobian ctx", (PetscObject)ctxcontainer));
1140:     tsdm->rhsjacobianctxcontainer = ctxcontainer;
1141:     PetscCall(PetscContainerDestroy(&ctxcontainer));
1142:   }
1143:   PetscFunctionReturn(PETSC_SUCCESS);
1144: }

1146: /*@C
1147:   DMTSSetRHSJacobianContextDestroy - set `TS` Jacobian evaluation context destroy function

1149:   Not Collective

1151:   Input Parameters:
1152: + dm - `DM` to be used with `TS`
1153: - f  - Jacobian evaluation context destroy function

1155:   Level: advanced

1157:   Note:
1158:   The user usually calls `TSSetRHSJacobianContextDestroy()` which calls this routine

1160: .seealso: [](ch_ts), `TS`, `TSSetRHSJacobianContextDestroy()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1161: @*/
1162: PetscErrorCode DMTSSetRHSJacobianContextDestroy(DM dm, PetscErrorCode (*f)(void *))
1163: {
1164:   DMTS tsdm;

1166:   PetscFunctionBegin;
1168:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
1169:   if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerSetUserDestroy(tsdm->rhsjacobianctxcontainer, f));
1170:   PetscFunctionReturn(PETSC_SUCCESS);
1171: }

1173: PetscErrorCode DMTSUnsetRHSJacobianContext_Internal(DM dm)
1174: {
1175:   DMTS tsdm;

1177:   PetscFunctionBegin;
1179:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
1180:   PetscCall(DMTSUnsetRHSJacobianContext_DMTS(tsdm));
1181:   PetscFunctionReturn(PETSC_SUCCESS);
1182: }

1184: /*@C
1185:   DMTSGetRHSJacobian - get `TS` Jacobian evaluation function

1187:   Not Collective

1189:   Input Parameter:
1190: . dm - `DM` to be used with `TS`

1192:   Output Parameters:
1193: + func - Jacobian evaluation function, for calling sequence see `TSSetRHSJacobian()`
1194: - ctx  - context for residual evaluation

1196:   Level: advanced

1198:   Note:
1199:   `TSGetJacobian()` is normally used, but it calls this function internally because the user context is actually
1200:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
1201:   not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.

1203: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetRHSFunction()`, `DMTSSetRHSJacobian()`, `TSSetRHSJacobian()`
1204: @*/
1205: PetscErrorCode DMTSGetRHSJacobian(DM dm, TSRHSJacobian *func, void **ctx)
1206: {
1207:   DMTS tsdm;

1209:   PetscFunctionBegin;
1211:   PetscCall(DMGetDMTS(dm, &tsdm));
1212:   if (func) *func = tsdm->ops->rhsjacobian;
1213:   if (ctx) {
1214:     if (tsdm->rhsjacobianctxcontainer) PetscCall(PetscContainerGetPointer(tsdm->rhsjacobianctxcontainer, ctx));
1215:     else *ctx = NULL;
1216:   }
1217:   PetscFunctionReturn(PETSC_SUCCESS);
1218: }

1220: /*@C
1221:   DMTSSetIFunctionSerialize - sets functions used to view and load a IFunction context

1223:   Not Collective

1225:   Input Parameters:
1226: + dm   - `DM` to be used with `TS`
1227: . view - viewer function
1228: - load - loading function

1230:   Level: advanced

1232: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1233: @*/
1234: PetscErrorCode DMTSSetIFunctionSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1235: {
1236:   DMTS tsdm;

1238:   PetscFunctionBegin;
1240:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
1241:   tsdm->ops->ifunctionview = view;
1242:   tsdm->ops->ifunctionload = load;
1243:   PetscFunctionReturn(PETSC_SUCCESS);
1244: }

1246: /*@C
1247:   DMTSSetIJacobianSerialize - sets functions used to view and load a IJacobian context

1249:   Not Collective

1251:   Input Parameters:
1252: + dm   - `DM` to be used with `TS`
1253: . view - viewer function
1254: - load - loading function

1256:   Level: advanced

1258: .seealso: [](ch_ts), `DM`, `TS`, `DMTSSetContext()`, `TSSetFunction()`, `DMTSSetJacobian()`
1259: @*/
1260: PetscErrorCode DMTSSetIJacobianSerialize(DM dm, PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*load)(void **, PetscViewer))
1261: {
1262:   DMTS tsdm;

1264:   PetscFunctionBegin;
1266:   PetscCall(DMGetDMTSWrite(dm, &tsdm));
1267:   tsdm->ops->ijacobianview = view;
1268:   tsdm->ops->ijacobianload = load;
1269:   PetscFunctionReturn(PETSC_SUCCESS);
1270: }