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