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