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