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