xref: /petsc/src/ts/trajectory/interface/traj.c (revision dfef5ea798a36ccc664ca1bbe435d183ec21e5c1)
1 #include <petsc/private/tsimpl.h> /*I "petscts.h"  I*/
2 #include <petsc/private/tshistoryimpl.h>
3 #include <petscdm.h>
4 
5 PetscFunctionList TSTrajectoryList              = NULL;
6 PetscBool         TSTrajectoryRegisterAllCalled = PETSC_FALSE;
7 PetscClassId      TSTRAJECTORY_CLASSID;
8 PetscLogEvent     TSTrajectory_Set, TSTrajectory_Get, TSTrajectory_GetVecs, TSTrajectory_SetUp;
9 
10 /*@C
11   TSTrajectoryRegister - Adds a way of storing trajectories to the `TS` package
12 
13   Not Collective
14 
15   Input Parameters:
16 + sname    - the name of a new user-defined creation routine
17 - function - the creation routine itself
18 
19   Level: developer
20 
21   Note:
22   `TSTrajectoryRegister()` may be called multiple times to add several user-defined tses.
23 
24 .seealso: [](ch_ts), `TSTrajectoryRegisterAll()`
25 @*/
26 PetscErrorCode TSTrajectoryRegister(const char sname[], PetscErrorCode (*function)(TSTrajectory, TS))
27 {
28   PetscFunctionBegin;
29   PetscCall(PetscFunctionListAdd(&TSTrajectoryList, sname, function));
30   PetscFunctionReturn(PETSC_SUCCESS);
31 }
32 
33 /*@
34   TSTrajectorySet - Sets a vector of state in the trajectory object
35 
36   Collective
37 
38   Input Parameters:
39 + tj      - the trajectory object
40 . ts      - the time stepper object (optional)
41 . stepnum - the step number
42 . time    - the current time
43 - X       - the current solution
44 
45   Level: developer
46 
47   Note:
48   Usually one does not call this routine, it is called automatically during `TSSolve()`
49 
50 .seealso: [](ch_ts), `TSTrajectorySetUp()`, `TSTrajectoryDestroy()`, `TSTrajectorySetType()`, `TSTrajectorySetVariableNames()`, `TSGetTrajectory()`, `TSTrajectoryGet()`, `TSTrajectoryGetVecs()`
51 @*/
52 PetscErrorCode TSTrajectorySet(TSTrajectory tj, TS ts, PetscInt stepnum, PetscReal time, Vec X)
53 {
54   PetscFunctionBegin;
55   if (!tj) PetscFunctionReturn(PETSC_SUCCESS);
56   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
57   if (ts) PetscValidHeaderSpecific(ts, TS_CLASSID, 2);
58   PetscValidLogicalCollectiveInt(tj, stepnum, 3);
59   PetscValidLogicalCollectiveReal(tj, time, 4);
60   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
61   PetscCheck(tj->setupcalled, PetscObjectComm((PetscObject)tj), PETSC_ERR_ORDER, "TSTrajectorySetUp should be called first");
62   if (tj->monitor) PetscCall(PetscViewerASCIIPrintf(tj->monitor, "TSTrajectorySet: stepnum %" PetscInt_FMT ", time %g (stages %" PetscInt_FMT ")\n", stepnum, (double)time, (PetscInt)!tj->solution_only));
63   PetscCall(PetscLogEventBegin(TSTrajectory_Set, tj, ts, 0, 0));
64   PetscUseTypeMethod(tj, set, ts, stepnum, time, X);
65   PetscCall(PetscLogEventEnd(TSTrajectory_Set, tj, ts, 0, 0));
66   if (tj->usehistory) PetscCall(TSHistoryUpdate(tj->tsh, stepnum, time));
67   if (tj->lag.caching) tj->lag.Udotcached.time = PETSC_MIN_REAL;
68   PetscFunctionReturn(PETSC_SUCCESS);
69 }
70 
71 /*@
72   TSTrajectoryGetNumSteps - Return the number of steps registered in the `TSTrajectory` via `TSTrajectorySet()`.
73 
74   Not Collective.
75 
76   Input Parameter:
77 . tj - the trajectory object
78 
79   Output Parameter:
80 . steps - the number of steps
81 
82   Level: developer
83 
84 .seealso: [](ch_ts), `TS`, `TSTrajectorySet()`
85 @*/
86 PetscErrorCode TSTrajectoryGetNumSteps(TSTrajectory tj, PetscInt *steps)
87 {
88   PetscFunctionBegin;
89   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
90   PetscAssertPointer(steps, 2);
91   PetscCall(TSHistoryGetNumSteps(tj->tsh, steps));
92   PetscFunctionReturn(PETSC_SUCCESS);
93 }
94 
95 /*@
96   TSTrajectoryGet - Updates the solution vector of a time stepper object by querying the `TSTrajectory`
97 
98   Collective
99 
100   Input Parameters:
101 + tj      - the trajectory object
102 . ts      - the time stepper object
103 - stepnum - the step number
104 
105   Output Parameter:
106 . time - the time associated with the step number
107 
108   Level: developer
109 
110   Note:
111   Usually one does not call this routine, it is called automatically during `TSSolve()`
112 
113 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSTrajectorySetUp()`, `TSTrajectoryDestroy()`, `TSTrajectorySetType()`, `TSTrajectorySetVariableNames()`, `TSGetTrajectory()`, `TSTrajectorySet()`, `TSTrajectoryGetVecs()`, `TSGetSolution()`
114 @*/
115 PetscErrorCode TSTrajectoryGet(TSTrajectory tj, TS ts, PetscInt stepnum, PetscReal *time)
116 {
117   PetscFunctionBegin;
118   PetscCheck(tj, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TS solver did not save trajectory");
119   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
120   PetscValidHeaderSpecific(ts, TS_CLASSID, 2);
121   PetscValidLogicalCollectiveInt(tj, stepnum, 3);
122   PetscAssertPointer(time, 4);
123   PetscCheck(tj->setupcalled, PetscObjectComm((PetscObject)tj), PETSC_ERR_ORDER, "TSTrajectorySetUp should be called first");
124   PetscCheck(stepnum >= 0, PetscObjectComm((PetscObject)tj), PETSC_ERR_PLIB, "Requesting negative step number");
125   if (tj->monitor) {
126     PetscCall(PetscViewerASCIIPrintf(tj->monitor, "TSTrajectoryGet: stepnum %" PetscInt_FMT ", stages %" PetscInt_FMT "\n", stepnum, (PetscInt)!tj->solution_only));
127     PetscCall(PetscViewerFlush(tj->monitor));
128   }
129   PetscCall(PetscLogEventBegin(TSTrajectory_Get, tj, ts, 0, 0));
130   PetscUseTypeMethod(tj, get, ts, stepnum, time);
131   PetscCall(PetscLogEventEnd(TSTrajectory_Get, tj, ts, 0, 0));
132   PetscFunctionReturn(PETSC_SUCCESS);
133 }
134 
135 /*@
136   TSTrajectoryGetVecs - Reconstructs the vector of state and its time derivative using information from the `TSTrajectory` and, possibly, from the `TS`
137 
138   Collective
139 
140   Input Parameters:
141 + tj      - the trajectory object
142 . ts      - the time stepper object (optional)
143 - stepnum - the requested step number
144 
145   Output Parameters:
146 + time - On input time for the step if step number is `PETSC_DECIDE`, on output the time associated with the step number
147 . U    - state vector (can be `NULL`)
148 - Udot - time derivative of state vector (can be `NULL`)
149 
150   Level: developer
151 
152   Notes:
153   If the step number is `PETSC_DECIDE`, the time argument is used to inquire the trajectory.
154   If the requested time does not match any in the trajectory, Lagrangian interpolations are returned.
155 
156 .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSTrajectorySetUp()`, `TSTrajectoryDestroy()`, `TSTrajectorySetType()`, `TSTrajectorySetVariableNames()`, `TSGetTrajectory()`, `TSTrajectorySet()`, `TSTrajectoryGet()`
157 @*/
158 PetscErrorCode TSTrajectoryGetVecs(TSTrajectory tj, TS ts, PetscInt stepnum, PetscReal *time, Vec U, Vec Udot)
159 {
160   PetscFunctionBegin;
161   PetscCheck(tj, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TS solver did not save trajectory");
162   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
163   if (ts) PetscValidHeaderSpecific(ts, TS_CLASSID, 2);
164   PetscValidLogicalCollectiveInt(tj, stepnum, 3);
165   PetscAssertPointer(time, 4);
166   if (U) PetscValidHeaderSpecific(U, VEC_CLASSID, 5);
167   if (Udot) PetscValidHeaderSpecific(Udot, VEC_CLASSID, 6);
168   if (!U && !Udot) PetscFunctionReturn(PETSC_SUCCESS);
169   PetscCheck(tj->setupcalled, PetscObjectComm((PetscObject)tj), PETSC_ERR_ORDER, "TSTrajectorySetUp should be called first");
170   PetscCall(PetscLogEventBegin(TSTrajectory_GetVecs, tj, ts, 0, 0));
171   if (tj->monitor) {
172     PetscInt pU, pUdot;
173     pU    = U ? 1 : 0;
174     pUdot = Udot ? 1 : 0;
175     PetscCall(PetscViewerASCIIPrintf(tj->monitor, "Requested by GetVecs %" PetscInt_FMT " %" PetscInt_FMT ": stepnum %" PetscInt_FMT ", time %g\n", pU, pUdot, stepnum, (double)*time));
176     PetscCall(PetscViewerFlush(tj->monitor));
177   }
178   if (U && tj->lag.caching) {
179     PetscObjectId    id;
180     PetscObjectState state;
181 
182     PetscCall(PetscObjectStateGet((PetscObject)U, &state));
183     PetscCall(PetscObjectGetId((PetscObject)U, &id));
184     if (stepnum == PETSC_DECIDE) {
185       if (id == tj->lag.Ucached.id && *time == tj->lag.Ucached.time && state == tj->lag.Ucached.state) U = NULL;
186     } else {
187       if (id == tj->lag.Ucached.id && stepnum == tj->lag.Ucached.step && state == tj->lag.Ucached.state) U = NULL;
188     }
189     if (tj->monitor && !U) {
190       PetscCall(PetscViewerASCIIPushTab(tj->monitor));
191       PetscCall(PetscViewerASCIIPrintf(tj->monitor, "State vector cached\n"));
192       PetscCall(PetscViewerASCIIPopTab(tj->monitor));
193       PetscCall(PetscViewerFlush(tj->monitor));
194     }
195   }
196   if (Udot && tj->lag.caching) {
197     PetscObjectId    id;
198     PetscObjectState state;
199 
200     PetscCall(PetscObjectStateGet((PetscObject)Udot, &state));
201     PetscCall(PetscObjectGetId((PetscObject)Udot, &id));
202     if (stepnum == PETSC_DECIDE) {
203       if (id == tj->lag.Udotcached.id && *time == tj->lag.Udotcached.time && state == tj->lag.Udotcached.state) Udot = NULL;
204     } else {
205       if (id == tj->lag.Udotcached.id && stepnum == tj->lag.Udotcached.step && state == tj->lag.Udotcached.state) Udot = NULL;
206     }
207     if (tj->monitor && !Udot) {
208       PetscCall(PetscViewerASCIIPushTab(tj->monitor));
209       PetscCall(PetscViewerASCIIPrintf(tj->monitor, "Derivative vector cached\n"));
210       PetscCall(PetscViewerASCIIPopTab(tj->monitor));
211       PetscCall(PetscViewerFlush(tj->monitor));
212     }
213   }
214   if (!U && !Udot) {
215     PetscCall(PetscLogEventEnd(TSTrajectory_GetVecs, tj, ts, 0, 0));
216     PetscFunctionReturn(PETSC_SUCCESS);
217   }
218 
219   if (stepnum == PETSC_DECIDE || Udot) { /* reverse search for requested time in TSHistory */
220     if (tj->monitor) PetscCall(PetscViewerASCIIPushTab(tj->monitor));
221     /* cached states will be updated in the function */
222     PetscCall(TSTrajectoryReconstruct_Private(tj, ts, *time, U, Udot));
223     if (tj->monitor) {
224       PetscCall(PetscViewerASCIIPopTab(tj->monitor));
225       PetscCall(PetscViewerFlush(tj->monitor));
226     }
227   } else if (U) { /* we were asked to load from stepnum, use TSTrajectoryGet */
228     TS  fakets = ts;
229     Vec U2;
230 
231     /* use a fake TS if ts is missing */
232     if (!ts) {
233       PetscCall(PetscObjectQuery((PetscObject)tj, "__fake_ts", (PetscObject *)&fakets));
234       if (!fakets) {
235         PetscCall(TSCreate(PetscObjectComm((PetscObject)tj), &fakets));
236         PetscCall(PetscObjectCompose((PetscObject)tj, "__fake_ts", (PetscObject)fakets));
237         PetscCall(PetscObjectDereference((PetscObject)fakets));
238         PetscCall(VecDuplicate(U, &U2));
239         PetscCall(TSSetSolution(fakets, U2));
240         PetscCall(PetscObjectDereference((PetscObject)U2));
241       }
242     }
243     PetscCall(TSTrajectoryGet(tj, fakets, stepnum, time));
244     PetscCall(TSGetSolution(fakets, &U2));
245     PetscCall(VecCopy(U2, U));
246     PetscCall(PetscObjectStateGet((PetscObject)U, &tj->lag.Ucached.state));
247     PetscCall(PetscObjectGetId((PetscObject)U, &tj->lag.Ucached.id));
248     tj->lag.Ucached.time = *time;
249     tj->lag.Ucached.step = stepnum;
250   }
251   PetscCall(PetscLogEventEnd(TSTrajectory_GetVecs, tj, ts, 0, 0));
252   PetscFunctionReturn(PETSC_SUCCESS);
253 }
254 
255 /*@C
256   TSTrajectoryViewFromOptions - View a `TSTrajectory` based on values in the options database
257 
258   Collective
259 
260   Input Parameters:
261 + A    - the `TSTrajectory` context
262 . obj  - Optional object that provides prefix used for option name
263 - name - command line option
264 
265   Level: intermediate
266 
267 .seealso: [](ch_ts), `TSTrajectory`, `TSTrajectoryView`, `PetscObjectViewFromOptions()`, `TSTrajectoryCreate()`
268 @*/
269 PetscErrorCode TSTrajectoryViewFromOptions(TSTrajectory A, PetscObject obj, const char name[])
270 {
271   PetscFunctionBegin;
272   PetscValidHeaderSpecific(A, TSTRAJECTORY_CLASSID, 1);
273   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
274   PetscFunctionReturn(PETSC_SUCCESS);
275 }
276 
277 /*@C
278   TSTrajectoryView - Prints information about the trajectory object
279 
280   Collective
281 
282   Input Parameters:
283 + tj     - the `TSTrajectory` context obtained from `TSTrajectoryCreate()`
284 - viewer - visualization context
285 
286   Options Database Key:
287 . -ts_trajectory_view - calls `TSTrajectoryView()` at end of `TSAdjointStep()`
288 
289   Level: developer
290 
291   Notes:
292   The available visualization contexts include
293 +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
294 -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
295   output where only the first processor opens
296   the file.  All other processors send their
297   data to the first processor to print.
298 
299   The user can open an alternative visualization context with
300   `PetscViewerASCIIOpen()` - output to a specified file.
301 
302 .seealso: [](ch_ts), `TS`, `TSTrajectory`, `PetscViewer`, `PetscViewerASCIIOpen()`
303 @*/
304 PetscErrorCode TSTrajectoryView(TSTrajectory tj, PetscViewer viewer)
305 {
306   PetscBool iascii;
307 
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
310   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)tj), &viewer));
311   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
312   PetscCheckSameComm(tj, 1, viewer, 2);
313 
314   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
315   if (iascii) {
316     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)tj, viewer));
317     PetscCall(PetscViewerASCIIPrintf(viewer, "  total number of recomputations for adjoint calculation = %" PetscInt_FMT "\n", tj->recomps));
318     PetscCall(PetscViewerASCIIPrintf(viewer, "  disk checkpoint reads = %" PetscInt_FMT "\n", tj->diskreads));
319     PetscCall(PetscViewerASCIIPrintf(viewer, "  disk checkpoint writes = %" PetscInt_FMT "\n", tj->diskwrites));
320     PetscCall(PetscViewerASCIIPushTab(viewer));
321     PetscTryTypeMethod(tj, view, viewer);
322     PetscCall(PetscViewerASCIIPopTab(viewer));
323   }
324   PetscFunctionReturn(PETSC_SUCCESS);
325 }
326 
327 /*@C
328   TSTrajectorySetVariableNames - Sets the name of each component in the solution vector so that it may be saved with the trajectory
329 
330   Collective
331 
332   Input Parameters:
333 + ctx   - the trajectory context
334 - names - the names of the components, final string must be NULL
335 
336   Level: intermediate
337 
338   Fortran Notes:
339   Fortran interface is not possible because of the string array argument
340 
341 .seealso: [](ch_ts), `TSTrajectory`, `TSGetTrajectory()`
342 @*/
343 PetscErrorCode TSTrajectorySetVariableNames(TSTrajectory ctx, const char *const *names)
344 {
345   PetscFunctionBegin;
346   PetscValidHeaderSpecific(ctx, TSTRAJECTORY_CLASSID, 1);
347   PetscAssertPointer(names, 2);
348   PetscCall(PetscStrArrayDestroy(&ctx->names));
349   PetscCall(PetscStrArrayallocpy(names, &ctx->names));
350   PetscFunctionReturn(PETSC_SUCCESS);
351 }
352 
353 /*@C
354   TSTrajectorySetTransform - Solution vector will be transformed by provided function before being saved to disk
355 
356   Collective
357 
358   Input Parameters:
359 + tj        - the `TSTrajectory` context
360 . transform - the transform function
361 . destroy   - function to destroy the optional context
362 - tctx      - optional context used by transform function
363 
364   Level: intermediate
365 
366 .seealso: [](ch_ts), `TSTrajectorySetVariableNames()`, `TSTrajectory`, `TSMonitorLGSetTransform()`
367 @*/
368 PetscErrorCode TSTrajectorySetTransform(TSTrajectory tj, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
369 {
370   PetscFunctionBegin;
371   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
372   tj->transform        = transform;
373   tj->transformdestroy = destroy;
374   tj->transformctx     = tctx;
375   PetscFunctionReturn(PETSC_SUCCESS);
376 }
377 
378 /*@
379   TSTrajectoryCreate - This function creates an empty trajectory object used to store the time dependent solution of an ODE/DAE
380 
381   Collective
382 
383   Input Parameter:
384 . comm - the communicator
385 
386   Output Parameter:
387 . tj - the trajectory object
388 
389   Level: developer
390 
391   Notes:
392   Usually one does not call this routine, it is called automatically when one calls `TSSetSaveTrajectory()`.
393 
394 .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSTrajectorySetUp()`, `TSTrajectoryDestroy()`, `TSTrajectorySetType()`, `TSTrajectorySetVariableNames()`, `TSGetTrajectory()`, `TSTrajectorySetKeepFiles()`
395 @*/
396 PetscErrorCode TSTrajectoryCreate(MPI_Comm comm, TSTrajectory *tj)
397 {
398   TSTrajectory t;
399 
400   PetscFunctionBegin;
401   PetscAssertPointer(tj, 2);
402   *tj = NULL;
403   PetscCall(TSInitializePackage());
404 
405   PetscCall(PetscHeaderCreate(t, TSTRAJECTORY_CLASSID, "TSTrajectory", "Time stepping", "TS", comm, TSTrajectoryDestroy, TSTrajectoryView));
406   t->setupcalled = PETSC_FALSE;
407   PetscCall(TSHistoryCreate(comm, &t->tsh));
408 
409   t->lag.order            = 1;
410   t->lag.L                = NULL;
411   t->lag.T                = NULL;
412   t->lag.W                = NULL;
413   t->lag.WW               = NULL;
414   t->lag.TW               = NULL;
415   t->lag.TT               = NULL;
416   t->lag.caching          = PETSC_TRUE;
417   t->lag.Ucached.id       = 0;
418   t->lag.Ucached.state    = -1;
419   t->lag.Ucached.time     = PETSC_MIN_REAL;
420   t->lag.Ucached.step     = PETSC_MAX_INT;
421   t->lag.Udotcached.id    = 0;
422   t->lag.Udotcached.state = -1;
423   t->lag.Udotcached.time  = PETSC_MIN_REAL;
424   t->lag.Udotcached.step  = PETSC_MAX_INT;
425   t->adjoint_solve_mode   = PETSC_TRUE;
426   t->solution_only        = PETSC_FALSE;
427   t->keepfiles            = PETSC_FALSE;
428   t->usehistory           = PETSC_TRUE;
429   *tj                     = t;
430   PetscCall(TSTrajectorySetFiletemplate(t, "TS-%06" PetscInt_FMT ".bin"));
431   PetscFunctionReturn(PETSC_SUCCESS);
432 }
433 
434 /*@C
435   TSTrajectorySetType - Sets the storage method to be used as in a trajectory
436 
437   Collective
438 
439   Input Parameters:
440 + tj   - the `TSTrajectory` context
441 . ts   - the `TS` context
442 - type - a known method
443 
444   Options Database Key:
445 . -ts_trajectory_type <type> - Sets the method; use -help for a list of available methods (for instance, basic)
446 
447   Level: developer
448 
449   Developer Notes:
450   Why does this option require access to the `TS`
451 
452 .seealso: [](ch_ts), `TSTrajectory`, `TS`, `TSTrajectoryCreate()`, `TSTrajectorySetFromOptions()`, `TSTrajectoryDestroy()`, `TSTrajectoryGetType()`
453 @*/
454 PetscErrorCode TSTrajectorySetType(TSTrajectory tj, TS ts, TSTrajectoryType type)
455 {
456   PetscErrorCode (*r)(TSTrajectory, TS);
457   PetscBool match;
458 
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
461   PetscCall(PetscObjectTypeCompare((PetscObject)tj, type, &match));
462   if (match) PetscFunctionReturn(PETSC_SUCCESS);
463 
464   PetscCall(PetscFunctionListFind(TSTrajectoryList, type, &r));
465   PetscCheck(r, PetscObjectComm((PetscObject)tj), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown TSTrajectory type: %s", type);
466   if (tj->ops->destroy) {
467     PetscCall((*(tj)->ops->destroy)(tj));
468 
469     tj->ops->destroy = NULL;
470   }
471   PetscCall(PetscMemzero(tj->ops, sizeof(*tj->ops)));
472 
473   PetscCall(PetscObjectChangeTypeName((PetscObject)tj, type));
474   PetscCall((*r)(tj, ts));
475   PetscFunctionReturn(PETSC_SUCCESS);
476 }
477 
478 /*@C
479   TSTrajectoryGetType - Gets the trajectory type
480 
481   Collective
482 
483   Input Parameters:
484 + tj - the `TSTrajectory` context
485 - ts - the `TS` context
486 
487   Output Parameter:
488 . type - a known method
489 
490   Level: developer
491 
492 .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectorySetFromOptions()`, `TSTrajectoryDestroy()`, `TSTrajectorySetType()`
493 @*/
494 PetscErrorCode TSTrajectoryGetType(TSTrajectory tj, TS ts, TSTrajectoryType *type)
495 {
496   PetscFunctionBegin;
497   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
498   if (type) *type = ((PetscObject)tj)->type_name;
499   PetscFunctionReturn(PETSC_SUCCESS);
500 }
501 
502 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Basic(TSTrajectory, TS);
503 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Singlefile(TSTrajectory, TS);
504 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Memory(TSTrajectory, TS);
505 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Visualization(TSTrajectory, TS);
506 
507 /*@C
508   TSTrajectoryRegisterAll - Registers all of the `TSTrajectory` storage schecmes in the `TS` package.
509 
510   Not Collective
511 
512   Level: developer
513 
514 .seealso: [](ch_ts), `TSTrajectory`, `TSTrajectoryRegister()`
515 @*/
516 PetscErrorCode TSTrajectoryRegisterAll(void)
517 {
518   PetscFunctionBegin;
519   if (TSTrajectoryRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
520   TSTrajectoryRegisterAllCalled = PETSC_TRUE;
521 
522   PetscCall(TSTrajectoryRegister(TSTRAJECTORYBASIC, TSTrajectoryCreate_Basic));
523   PetscCall(TSTrajectoryRegister(TSTRAJECTORYSINGLEFILE, TSTrajectoryCreate_Singlefile));
524   PetscCall(TSTrajectoryRegister(TSTRAJECTORYMEMORY, TSTrajectoryCreate_Memory));
525   PetscCall(TSTrajectoryRegister(TSTRAJECTORYVISUALIZATION, TSTrajectoryCreate_Visualization));
526   PetscFunctionReturn(PETSC_SUCCESS);
527 }
528 
529 /*@
530   TSTrajectoryReset - Resets a trajectory context
531 
532   Collective
533 
534   Input Parameter:
535 . tj - the `TSTrajectory` context obtained from `TSGetTrajectory()`
536 
537   Level: developer
538 
539 .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectorySetUp()`
540 @*/
541 PetscErrorCode TSTrajectoryReset(TSTrajectory tj)
542 {
543   PetscFunctionBegin;
544   if (!tj) PetscFunctionReturn(PETSC_SUCCESS);
545   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
546   PetscTryTypeMethod(tj, reset);
547   PetscCall(PetscFree(tj->dirfiletemplate));
548   PetscCall(TSHistoryDestroy(&tj->tsh));
549   PetscCall(TSHistoryCreate(PetscObjectComm((PetscObject)tj), &tj->tsh));
550   tj->setupcalled = PETSC_FALSE;
551   PetscFunctionReturn(PETSC_SUCCESS);
552 }
553 
554 /*@
555   TSTrajectoryDestroy - Destroys a trajectory context
556 
557   Collective
558 
559   Input Parameter:
560 . tj - the `TSTrajectory` context obtained from `TSTrajectoryCreate()`
561 
562   Level: developer
563 
564 .seealso: [](ch_ts), `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectorySetUp()`
565 @*/
566 PetscErrorCode TSTrajectoryDestroy(TSTrajectory *tj)
567 {
568   PetscFunctionBegin;
569   if (!*tj) PetscFunctionReturn(PETSC_SUCCESS);
570   PetscValidHeaderSpecific((*tj), TSTRAJECTORY_CLASSID, 1);
571   if (--((PetscObject)(*tj))->refct > 0) {
572     *tj = NULL;
573     PetscFunctionReturn(PETSC_SUCCESS);
574   }
575 
576   PetscCall(TSTrajectoryReset(*tj));
577   PetscCall(TSHistoryDestroy(&(*tj)->tsh));
578   PetscCall(VecDestroyVecs((*tj)->lag.order + 1, &(*tj)->lag.W));
579   PetscCall(PetscFree5((*tj)->lag.L, (*tj)->lag.T, (*tj)->lag.WW, (*tj)->lag.TT, (*tj)->lag.TW));
580   PetscCall(VecDestroy(&(*tj)->U));
581   PetscCall(VecDestroy(&(*tj)->Udot));
582 
583   if ((*tj)->transformdestroy) PetscCall((*(*tj)->transformdestroy)((*tj)->transformctx));
584   PetscTryTypeMethod((*tj), destroy);
585   if (!((*tj)->keepfiles)) {
586     PetscMPIInt rank;
587     MPI_Comm    comm;
588 
589     PetscCall(PetscObjectGetComm((PetscObject)(*tj), &comm));
590     PetscCallMPI(MPI_Comm_rank(comm, &rank));
591     if (rank == 0 && (*tj)->dirname) { /* we own the directory, so we run PetscRMTree on it */
592       PetscCall(PetscRMTree((*tj)->dirname));
593     }
594   }
595   PetscCall(PetscStrArrayDestroy(&(*tj)->names));
596   PetscCall(PetscFree((*tj)->dirname));
597   PetscCall(PetscFree((*tj)->filetemplate));
598   PetscCall(PetscHeaderDestroy(tj));
599   PetscFunctionReturn(PETSC_SUCCESS);
600 }
601 
602 /*
603   TSTrajectorySetTypeFromOptions_Private - Sets the type of `TSTrajectory` from user options.
604 
605   Collective
606 
607   Input Parameter:
608 + tj - the `TSTrajectory` context
609 - ts - the TS context
610 
611   Options Database Key:
612 . -ts_trajectory_type <type> - TSTRAJECTORYBASIC, TSTRAJECTORYMEMORY, TSTRAJECTORYSINGLEFILE, TSTRAJECTORYVISUALIZATION
613 
614   Level: developer
615 
616 .seealso: [](ch_ts), `TSTrajectory`, `TSTrajectoryType`, `TSTrajectorySetFromOptions()`, `TSTrajectorySetType()`
617 */
618 static PetscErrorCode TSTrajectorySetTypeFromOptions_Private(PetscOptionItems *PetscOptionsObject, TSTrajectory tj, TS ts)
619 {
620   PetscBool   opt;
621   const char *defaultType;
622   char        typeName[256];
623 
624   PetscFunctionBegin;
625   if (((PetscObject)tj)->type_name) defaultType = ((PetscObject)tj)->type_name;
626   else defaultType = TSTRAJECTORYBASIC;
627 
628   PetscCall(TSTrajectoryRegisterAll());
629   PetscCall(PetscOptionsFList("-ts_trajectory_type", "TSTrajectory method", "TSTrajectorySetType", TSTrajectoryList, defaultType, typeName, 256, &opt));
630   if (opt) {
631     PetscCall(TSTrajectorySetType(tj, ts, typeName));
632   } else {
633     PetscCall(TSTrajectorySetType(tj, ts, defaultType));
634   }
635   PetscFunctionReturn(PETSC_SUCCESS);
636 }
637 
638 /*@
639   TSTrajectorySetUseHistory - Use `TSHistory` in `TSTrajectory`
640 
641   Collective
642 
643   Input Parameters:
644 + tj  - the `TSTrajectory` context
645 - flg - `PETSC_TRUE` to save, `PETSC_FALSE` to disable
646 
647   Options Database Key:
648 . -ts_trajectory_use_history - have it use `TSHistory`
649 
650   Level: advanced
651 
652 .seealso: [](ch_ts), `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetUp()`
653 @*/
654 PetscErrorCode TSTrajectorySetUseHistory(TSTrajectory tj, PetscBool flg)
655 {
656   PetscFunctionBegin;
657   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
658   PetscValidLogicalCollectiveBool(tj, flg, 2);
659   tj->usehistory = flg;
660   PetscFunctionReturn(PETSC_SUCCESS);
661 }
662 
663 /*@
664   TSTrajectorySetMonitor - Monitor the schedules generated by the `TSTrajectory` checkpointing controller
665 
666   Collective
667 
668   Input Parameters:
669 + tj  - the `TSTrajectory` context
670 - flg - `PETSC_TRUE` to active a monitor, `PETSC_FALSE` to disable
671 
672   Options Database Key:
673 . -ts_trajectory_monitor - print `TSTrajectory` information
674 
675   Level: developer
676 
677 .seealso: [](ch_ts), `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetUp()`
678 @*/
679 PetscErrorCode TSTrajectorySetMonitor(TSTrajectory tj, PetscBool flg)
680 {
681   PetscFunctionBegin;
682   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
683   PetscValidLogicalCollectiveBool(tj, flg, 2);
684   if (flg) tj->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)tj));
685   else tj->monitor = NULL;
686   PetscFunctionReturn(PETSC_SUCCESS);
687 }
688 
689 /*@
690   TSTrajectorySetKeepFiles - Keep the files generated by the `TSTrajectory` once the program is done
691 
692   Collective
693 
694   Input Parameters:
695 + tj  - the `TSTrajectory` context
696 - flg - `PETSC_TRUE` to save, `PETSC_FALSE` to disable
697 
698   Options Database Key:
699 . -ts_trajectory_keep_files - have it keep the files
700 
701   Level: advanced
702 
703   Note:
704   By default the `TSTrajectory` used for adjoint computations, `TSTRAJECTORYBASIC`, removes the files it generates at the end of the run. This causes the files to be kept.
705 
706 .seealso: [](ch_ts), `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetUp()`, `TSTrajectorySetMonitor()`
707 @*/
708 PetscErrorCode TSTrajectorySetKeepFiles(TSTrajectory tj, PetscBool flg)
709 {
710   PetscFunctionBegin;
711   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
712   PetscValidLogicalCollectiveBool(tj, flg, 2);
713   tj->keepfiles = flg;
714   PetscFunctionReturn(PETSC_SUCCESS);
715 }
716 
717 /*@C
718   TSTrajectorySetDirname - Specify the name of the directory where `TSTrajectory` disk checkpoints are stored.
719 
720   Collective
721 
722   Input Parameters:
723 + tj      - the `TSTrajectory` context
724 - dirname - the directory name
725 
726   Options Database Key:
727 . -ts_trajectory_dirname - set the directory name
728 
729   Level: developer
730 
731   Notes:
732   The final location of the files is determined by dirname/filetemplate where filetemplate was provided by `TSTrajectorySetFiletemplate()`
733 
734   If this is not called `TSTrajectory` selects a unique new name for the directory
735 
736 .seealso: [](ch_ts), `TSTrajectory`, `TSTrajectorySetFiletemplate()`, `TSTrajectorySetUp()`
737 @*/
738 PetscErrorCode TSTrajectorySetDirname(TSTrajectory tj, const char dirname[])
739 {
740   PetscBool flg;
741 
742   PetscFunctionBegin;
743   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
744   PetscCall(PetscStrcmp(tj->dirname, dirname, &flg));
745   PetscCheck(flg || !tj->dirfiletemplate, PetscObjectComm((PetscObject)tj), PETSC_ERR_ARG_WRONGSTATE, "Cannot set directoryname after TSTrajectory has been setup");
746   PetscCall(PetscFree(tj->dirname));
747   PetscCall(PetscStrallocpy(dirname, &tj->dirname));
748   PetscFunctionReturn(PETSC_SUCCESS);
749 }
750 
751 /*@C
752   TSTrajectorySetFiletemplate - Specify the name template for the files storing `TSTrajectory` checkpoints.
753 
754   Collective
755 
756   Input Parameters:
757 + tj           - the `TSTrajectory` context
758 - filetemplate - the template
759 
760   Options Database Key:
761 . -ts_trajectory_file_template - set the file name template
762 
763   Level: developer
764 
765   Notes:
766   The name template should be of the form, for example filename-%06" PetscInt_FMT ".bin It should not begin with a leading /
767 
768   The final location of the files is determined by dirname/filetemplate where dirname was provided by `TSTrajectorySetDirname()`. The %06" PetscInt_FMT " is replaced by the
769   timestep counter
770 
771 .seealso: [](ch_ts), `TSTrajectory`, `TSTrajectorySetDirname()`, `TSTrajectorySetUp()`
772 @*/
773 PetscErrorCode TSTrajectorySetFiletemplate(TSTrajectory tj, const char filetemplate[])
774 {
775   const char *ptr = NULL, *ptr2 = NULL;
776 
777   PetscFunctionBegin;
778   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
779   PetscAssertPointer(filetemplate, 2);
780   PetscCheck(!tj->dirfiletemplate, PetscObjectComm((PetscObject)tj), PETSC_ERR_ARG_WRONGSTATE, "Cannot set filetemplate after TSTrajectory has been setup");
781 
782   PetscCheck(filetemplate[0], PetscObjectComm((PetscObject)tj), PETSC_ERR_USER, "-ts_trajectory_file_template requires a file name template, e.g. filename-%%06" PetscInt_FMT ".bin");
783   /* Do some cursory validation of the input. */
784   PetscCall(PetscStrstr(filetemplate, "%", (char **)&ptr));
785   PetscCheck(ptr, PetscObjectComm((PetscObject)tj), PETSC_ERR_USER, "-ts_trajectory_file_template requires a file name template, e.g. filename-%%06" PetscInt_FMT ".bin");
786   for (ptr++; ptr && *ptr; ptr++) {
787     PetscCall(PetscStrchr(PetscInt_FMT "DiouxX", *ptr, (char **)&ptr2));
788     PetscCheck(ptr2 || (*ptr >= '0' && *ptr <= '9'), PetscObjectComm((PetscObject)tj), PETSC_ERR_USER, "Invalid file template argument to -ts_trajectory_file_template, should look like filename-%%06" PetscInt_FMT ".bin");
789     if (ptr2) break;
790   }
791   PetscCall(PetscFree(tj->filetemplate));
792   PetscCall(PetscStrallocpy(filetemplate, &tj->filetemplate));
793   PetscFunctionReturn(PETSC_SUCCESS);
794 }
795 
796 /*@
797   TSTrajectorySetFromOptions - Sets various `TSTrajectory` parameters from user options.
798 
799   Collective
800 
801   Input Parameters:
802 + tj - the `TSTrajectory` context obtained from `TSGetTrajectory()`
803 - ts - the `TS` context
804 
805   Options Database Keys:
806 + -ts_trajectory_type <type>             - basic, memory, singlefile, visualization
807 . -ts_trajectory_keep_files <true,false> - keep the files generated by the code after the program ends. This is true by default for singlefile and visualization
808 - -ts_trajectory_monitor                 - print `TSTrajectory` information
809 
810   Level: developer
811 
812   Note:
813   This is not normally called directly by users
814 
815 .seealso: [](ch_ts), `TSTrajectory`, `TSSetSaveTrajectory()`, `TSTrajectorySetUp()`
816 @*/
817 PetscErrorCode TSTrajectorySetFromOptions(TSTrajectory tj, TS ts)
818 {
819   PetscBool set, flg;
820   char      dirname[PETSC_MAX_PATH_LEN], filetemplate[PETSC_MAX_PATH_LEN];
821 
822   PetscFunctionBegin;
823   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
824   if (ts) PetscValidHeaderSpecific(ts, TS_CLASSID, 2);
825   PetscObjectOptionsBegin((PetscObject)tj);
826   PetscCall(TSTrajectorySetTypeFromOptions_Private(PetscOptionsObject, tj, ts));
827   PetscCall(PetscOptionsBool("-ts_trajectory_use_history", "Turn on/off usage of TSHistory", NULL, tj->usehistory, &tj->usehistory, NULL));
828   PetscCall(PetscOptionsBool("-ts_trajectory_monitor", "Print checkpointing schedules", "TSTrajectorySetMonitor", tj->monitor ? PETSC_TRUE : PETSC_FALSE, &flg, &set));
829   if (set) PetscCall(TSTrajectorySetMonitor(tj, flg));
830   PetscCall(PetscOptionsInt("-ts_trajectory_reconstruction_order", "Interpolation order for reconstruction", NULL, tj->lag.order, &tj->lag.order, NULL));
831   PetscCall(PetscOptionsBool("-ts_trajectory_reconstruction_caching", "Turn on/off caching of TSTrajectoryGetVecs input", NULL, tj->lag.caching, &tj->lag.caching, NULL));
832   PetscCall(PetscOptionsBool("-ts_trajectory_adjointmode", "Instruct the trajectory that will be used in a TSAdjointSolve()", NULL, tj->adjoint_solve_mode, &tj->adjoint_solve_mode, NULL));
833   PetscCall(PetscOptionsBool("-ts_trajectory_solution_only", "Checkpoint solution only", "TSTrajectorySetSolutionOnly", tj->solution_only, &tj->solution_only, NULL));
834   PetscCall(PetscOptionsBool("-ts_trajectory_keep_files", "Keep any trajectory files generated during the run", "TSTrajectorySetKeepFiles", tj->keepfiles, &flg, &set));
835   if (set) PetscCall(TSTrajectorySetKeepFiles(tj, flg));
836 
837   PetscCall(PetscOptionsString("-ts_trajectory_dirname", "Directory name for TSTrajectory file", "TSTrajectorySetDirname", NULL, dirname, sizeof(dirname) - 14, &set));
838   if (set) PetscCall(TSTrajectorySetDirname(tj, dirname));
839 
840   PetscCall(PetscOptionsString("-ts_trajectory_file_template", "Template for TSTrajectory file name, use filename-%06" PetscInt_FMT ".bin", "TSTrajectorySetFiletemplate", NULL, filetemplate, sizeof(filetemplate), &set));
841   if (set) PetscCall(TSTrajectorySetFiletemplate(tj, filetemplate));
842 
843   /* Handle specific TSTrajectory options */
844   PetscTryTypeMethod(tj, setfromoptions, PetscOptionsObject);
845   PetscOptionsEnd();
846   PetscFunctionReturn(PETSC_SUCCESS);
847 }
848 
849 /*@
850   TSTrajectorySetUp - Sets up the internal data structures, e.g. stacks, for the later use
851   of a `TS` `TSTrajectory`.
852 
853   Collective
854 
855   Input Parameters:
856 + tj - the `TSTrajectory` context
857 - ts - the TS context obtained from `TSCreate()`
858 
859   Level: developer
860 
861 .seealso: [](ch_ts), `TSTrajectory`, `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`
862 @*/
863 PetscErrorCode TSTrajectorySetUp(TSTrajectory tj, TS ts)
864 {
865   size_t s1, s2;
866 
867   PetscFunctionBegin;
868   if (!tj) PetscFunctionReturn(PETSC_SUCCESS);
869   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
870   if (ts) PetscValidHeaderSpecific(ts, TS_CLASSID, 2);
871   if (tj->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
872 
873   PetscCall(PetscLogEventBegin(TSTrajectory_SetUp, tj, ts, 0, 0));
874   if (!((PetscObject)tj)->type_name) PetscCall(TSTrajectorySetType(tj, ts, TSTRAJECTORYBASIC));
875   PetscTryTypeMethod(tj, setup, ts);
876 
877   tj->setupcalled = PETSC_TRUE;
878 
879   /* Set the counters to zero */
880   tj->recomps    = 0;
881   tj->diskreads  = 0;
882   tj->diskwrites = 0;
883   PetscCall(PetscStrlen(tj->dirname, &s1));
884   PetscCall(PetscStrlen(tj->filetemplate, &s2));
885   PetscCall(PetscFree(tj->dirfiletemplate));
886   PetscCall(PetscMalloc((s1 + s2 + 10) * sizeof(char), &tj->dirfiletemplate));
887   PetscCall(PetscSNPrintf(tj->dirfiletemplate, s1 + s2 + 10, "%s/%s", tj->dirname, tj->filetemplate));
888   PetscCall(PetscLogEventEnd(TSTrajectory_SetUp, tj, ts, 0, 0));
889   PetscFunctionReturn(PETSC_SUCCESS);
890 }
891 
892 /*@
893   TSTrajectorySetSolutionOnly - Tells the trajectory to store just the solution, and not any intermediate stage information
894 
895   Collective
896 
897   Input Parameters:
898 + tj            - the `TSTrajectory` context obtained with `TSGetTrajectory()`
899 - solution_only - the boolean flag
900 
901   Level: developer
902 
903 .seealso: [](ch_ts), `TSTrajectory`, `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectoryGetSolutionOnly()`
904 @*/
905 PetscErrorCode TSTrajectorySetSolutionOnly(TSTrajectory tj, PetscBool solution_only)
906 {
907   PetscFunctionBegin;
908   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
909   PetscValidLogicalCollectiveBool(tj, solution_only, 2);
910   tj->solution_only = solution_only;
911   PetscFunctionReturn(PETSC_SUCCESS);
912 }
913 
914 /*@
915   TSTrajectoryGetSolutionOnly - Gets the value set with `TSTrajectorySetSolutionOnly()`.
916 
917   Logically Collective
918 
919   Input Parameter:
920 . tj - the `TSTrajectory` context
921 
922   Output Parameter:
923 . solution_only - the boolean flag
924 
925   Level: developer
926 
927 .seealso: [](ch_ts), `TSTrajectory`, `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetSolutionOnly()`
928 @*/
929 PetscErrorCode TSTrajectoryGetSolutionOnly(TSTrajectory tj, PetscBool *solution_only)
930 {
931   PetscFunctionBegin;
932   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
933   PetscAssertPointer(solution_only, 2);
934   *solution_only = tj->solution_only;
935   PetscFunctionReturn(PETSC_SUCCESS);
936 }
937 
938 /*@
939   TSTrajectoryGetUpdatedHistoryVecs - Get updated state and time-derivative history vectors.
940 
941   Collective
942 
943   Input Parameters:
944 + tj   - the `TSTrajectory` context
945 . ts   - the `TS` solver context
946 - time - the requested time
947 
948   Output Parameters:
949 + U    - state vector at given time (can be interpolated)
950 - Udot - time-derivative vector at given time (can be interpolated)
951 
952   Level: developer
953 
954   Notes:
955   The vectors are interpolated if time does not match any time step stored in the `TSTrajectory()`. Pass NULL to not request a vector.
956 
957   This function differs from `TSTrajectoryGetVecs()` since the vectors obtained cannot be modified, and they need to be returned by
958   calling `TSTrajectoryRestoreUpdatedHistoryVecs()`.
959 
960 .seealso: [](ch_ts), `TSTrajectory`, `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectoryRestoreUpdatedHistoryVecs()`, `TSTrajectoryGetVecs()`
961 @*/
962 PetscErrorCode TSTrajectoryGetUpdatedHistoryVecs(TSTrajectory tj, TS ts, PetscReal time, Vec *U, Vec *Udot)
963 {
964   PetscFunctionBegin;
965   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
966   PetscValidHeaderSpecific(ts, TS_CLASSID, 2);
967   PetscValidLogicalCollectiveReal(tj, time, 3);
968   if (U) PetscAssertPointer(U, 4);
969   if (Udot) PetscAssertPointer(Udot, 5);
970   if (U && !tj->U) {
971     DM dm;
972 
973     PetscCall(TSGetDM(ts, &dm));
974     PetscCall(DMCreateGlobalVector(dm, &tj->U));
975   }
976   if (Udot && !tj->Udot) {
977     DM dm;
978 
979     PetscCall(TSGetDM(ts, &dm));
980     PetscCall(DMCreateGlobalVector(dm, &tj->Udot));
981   }
982   PetscCall(TSTrajectoryGetVecs(tj, ts, PETSC_DECIDE, &time, U ? tj->U : NULL, Udot ? tj->Udot : NULL));
983   if (U) {
984     PetscCall(VecLockReadPush(tj->U));
985     *U = tj->U;
986   }
987   if (Udot) {
988     PetscCall(VecLockReadPush(tj->Udot));
989     *Udot = tj->Udot;
990   }
991   PetscFunctionReturn(PETSC_SUCCESS);
992 }
993 
994 /*@
995   TSTrajectoryRestoreUpdatedHistoryVecs - Restores updated state and time-derivative history vectors obtained with `TSTrajectoryGetUpdatedHistoryVecs()`.
996 
997   Collective
998 
999   Input Parameters:
1000 + tj   - the `TSTrajectory` context
1001 . U    - state vector at given time (can be interpolated)
1002 - Udot - time-derivative vector at given time (can be interpolated)
1003 
1004   Level: developer
1005 
1006 .seealso: [](ch_ts), `TSTrajectory`, `TSTrajectoryGetUpdatedHistoryVecs()`
1007 @*/
1008 PetscErrorCode TSTrajectoryRestoreUpdatedHistoryVecs(TSTrajectory tj, Vec *U, Vec *Udot)
1009 {
1010   PetscFunctionBegin;
1011   PetscValidHeaderSpecific(tj, TSTRAJECTORY_CLASSID, 1);
1012   if (U) PetscValidHeaderSpecific(*U, VEC_CLASSID, 2);
1013   if (Udot) PetscValidHeaderSpecific(*Udot, VEC_CLASSID, 3);
1014   PetscCheck(!U || *U == tj->U, PetscObjectComm((PetscObject)*U), PETSC_ERR_USER, "U was not obtained from TSTrajectoryGetUpdatedHistoryVecs()");
1015   PetscCheck(!Udot || *Udot == tj->Udot, PetscObjectComm((PetscObject)*Udot), PETSC_ERR_USER, "Udot was not obtained from TSTrajectoryGetUpdatedHistoryVecs()");
1016   if (U) {
1017     PetscCall(VecLockReadPop(tj->U));
1018     *U = NULL;
1019   }
1020   if (Udot) {
1021     PetscCall(VecLockReadPop(tj->Udot));
1022     *Udot = NULL;
1023   }
1024   PetscFunctionReturn(PETSC_SUCCESS);
1025 }
1026