xref: /petsc/src/ts/trajectory/interface/traj.c (revision d3ef4daaf99d19e98efa749367c59a1afaa53b93)
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   PetscCheck(flg || !tj->dirfiletemplate,PetscObjectComm((PetscObject)tj),PETSC_ERR_ARG_WRONGSTATE,"Cannot set directoryname after TSTrajectory has been setup");
745   PetscCall(PetscFree(tj->dirname));
746   PetscCall(PetscStrallocpy(dirname,&tj->dirname));
747   PetscFunctionReturn(0);
748 }
749 
750 /*@C
751    TSTrajectorySetFiletemplate - Specify the name template for the files storing checkpoints.
752 
753    Collective on TSTrajectory
754 
755    Input Parameters:
756 +  tj      - the TSTrajectory context
757 -  filetemplate - the template
758 
759    Options Database Keys:
760 .  -ts_trajectory_file_template - set the file name template
761 
762    Notes:
763     The name template should be of the form, for example filename-%06" PetscInt_FMT ".bin It should not begin with a leading /
764 
765    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
766    timestep counter
767 
768    Level: developer
769 
770 .seealso: `TSTrajectorySetDirname()`, `TSTrajectorySetUp()`
771 @*/
772 PetscErrorCode TSTrajectorySetFiletemplate(TSTrajectory tj,const char filetemplate[])
773 {
774   const char     *ptr,*ptr2;
775 
776   PetscFunctionBegin;
777   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
778   PetscValidCharPointer(filetemplate,2);
779   PetscCheck(!tj->dirfiletemplate,PetscObjectComm((PetscObject)tj),PETSC_ERR_ARG_WRONGSTATE,"Cannot set filetemplate after TSTrajectory has been setup");
780 
781   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");
782   /* Do some cursory validation of the input. */
783   PetscCall(PetscStrstr(filetemplate,"%",(char**)&ptr));
784   PetscCheck(ptr,PetscObjectComm((PetscObject)tj),PETSC_ERR_USER,"-ts_trajectory_file_template requires a file name template, e.g. filename-%%06" PetscInt_FMT ".bin");
785   for (ptr++; ptr && *ptr; ptr++) {
786     PetscCall(PetscStrchr(PetscInt_FMT "DiouxX",*ptr,(char**)&ptr2));
787     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");
788     if (ptr2) break;
789   }
790   PetscCall(PetscFree(tj->filetemplate));
791   PetscCall(PetscStrallocpy(filetemplate,&tj->filetemplate));
792   PetscFunctionReturn(0);
793 }
794 
795 /*@
796    TSTrajectorySetFromOptions - Sets various TSTrajectory parameters from user options.
797 
798    Collective on TSTrajectory
799 
800    Input Parameters:
801 +  tj - the TSTrajectory context obtained from TSTrajectoryCreate()
802 -  ts - the TS context
803 
804    Options Database Keys:
805 +  -ts_trajectory_type <type> - TSTRAJECTORYBASIC, TSTRAJECTORYMEMORY, TSTRAJECTORYSINGLEFILE, TSTRAJECTORYVISUALIZATION
806 .  -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
807 -  -ts_trajectory_monitor - print TSTrajectory information
808 
809    Level: developer
810 
811    Notes:
812     This is not normally called directly by users
813 
814 .seealso: `TSSetSaveTrajectory()`, `TSTrajectorySetUp()`
815 @*/
816 PetscErrorCode  TSTrajectorySetFromOptions(TSTrajectory tj,TS ts)
817 {
818   PetscBool      set,flg;
819   char           dirname[PETSC_MAX_PATH_LEN],filetemplate[PETSC_MAX_PATH_LEN];
820 
821   PetscFunctionBegin;
822   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
823   if (ts) PetscValidHeaderSpecific(ts,TS_CLASSID,2);
824   PetscObjectOptionsBegin((PetscObject)tj);
825   PetscCall(TSTrajectorySetTypeFromOptions_Private(PetscOptionsObject,tj,ts));
826   PetscCall(PetscOptionsBool("-ts_trajectory_use_history","Turn on/off usage of TSHistory",NULL,tj->usehistory,&tj->usehistory,NULL));
827   PetscCall(PetscOptionsBool("-ts_trajectory_monitor","Print checkpointing schedules","TSTrajectorySetMonitor",tj->monitor ? PETSC_TRUE:PETSC_FALSE,&flg,&set));
828   if (set) PetscCall(TSTrajectorySetMonitor(tj,flg));
829   PetscCall(PetscOptionsInt("-ts_trajectory_reconstruction_order","Interpolation order for reconstruction",NULL,tj->lag.order,&tj->lag.order,NULL));
830   PetscCall(PetscOptionsBool("-ts_trajectory_reconstruction_caching","Turn on/off caching of TSTrajectoryGetVecs input",NULL,tj->lag.caching,&tj->lag.caching,NULL));
831   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));
832   PetscCall(PetscOptionsBool("-ts_trajectory_solution_only","Checkpoint solution only","TSTrajectorySetSolutionOnly",tj->solution_only,&tj->solution_only,NULL));
833   PetscCall(PetscOptionsBool("-ts_trajectory_keep_files","Keep any trajectory files generated during the run","TSTrajectorySetKeepFiles",tj->keepfiles,&flg,&set));
834   if (set) PetscCall(TSTrajectorySetKeepFiles(tj,flg));
835 
836   PetscCall(PetscOptionsString("-ts_trajectory_dirname","Directory name for TSTrajectory file","TSTrajectorySetDirname",NULL,dirname,sizeof(dirname)-14,&set));
837   if (set) PetscCall(TSTrajectorySetDirname(tj,dirname));
838 
839   PetscCall(PetscOptionsString("-ts_trajectory_file_template","Template for TSTrajectory file name, use filename-%06" PetscInt_FMT ".bin","TSTrajectorySetFiletemplate",NULL,filetemplate,sizeof(filetemplate),&set));
840   if (set) PetscCall(TSTrajectorySetFiletemplate(tj,filetemplate));
841 
842   /* Handle specific TSTrajectory options */
843   if (tj->ops->setfromoptions) PetscCall((*tj->ops->setfromoptions)(PetscOptionsObject,tj));
844   PetscOptionsEnd();
845   PetscFunctionReturn(0);
846 }
847 
848 /*@
849    TSTrajectorySetUp - Sets up the internal data structures, e.g. stacks, for the later use
850    of a TS trajectory.
851 
852    Collective on TS
853 
854    Input Parameters:
855 +  ts - the TS context obtained from TSCreate()
856 -  tj - the TS trajectory context
857 
858    Level: developer
859 
860 .seealso: `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`
861 @*/
862 PetscErrorCode  TSTrajectorySetUp(TSTrajectory tj,TS ts)
863 {
864   size_t         s1,s2;
865 
866   PetscFunctionBegin;
867   if (!tj) PetscFunctionReturn(0);
868   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
869   if (ts) PetscValidHeaderSpecific(ts,TS_CLASSID,2);
870   if (tj->setupcalled) PetscFunctionReturn(0);
871 
872   PetscCall(PetscLogEventBegin(TSTrajectory_SetUp,tj,ts,0,0));
873   if (!((PetscObject)tj)->type_name) {
874     PetscCall(TSTrajectorySetType(tj,ts,TSTRAJECTORYBASIC));
875   }
876   if (tj->ops->setup) PetscCall((*tj->ops->setup)(tj,ts));
877 
878   tj->setupcalled = PETSC_TRUE;
879 
880   /* Set the counters to zero */
881   tj->recomps    = 0;
882   tj->diskreads  = 0;
883   tj->diskwrites = 0;
884   PetscCall(PetscStrlen(tj->dirname,&s1));
885   PetscCall(PetscStrlen(tj->filetemplate,&s2));
886   PetscCall(PetscFree(tj->dirfiletemplate));
887   PetscCall(PetscMalloc((s1 + s2 + 10)*sizeof(char),&tj->dirfiletemplate));
888   PetscCall(PetscSNPrintf(tj->dirfiletemplate,s1+s2+10,"%s/%s",tj->dirname,tj->filetemplate));
889   PetscCall(PetscLogEventEnd(TSTrajectory_SetUp,tj,ts,0,0));
890   PetscFunctionReturn(0);
891 }
892 
893 /*@
894    TSTrajectorySetSolutionOnly - Tells the trajectory to store just the solution, and not any intermediate stage also.
895 
896    Collective on TSTrajectory
897 
898    Input Parameters:
899 +  tj  - the TS trajectory context
900 -  flg - the boolean flag
901 
902    Level: developer
903 
904 .seealso: `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectoryGetSolutionOnly()`
905 @*/
906 PetscErrorCode TSTrajectorySetSolutionOnly(TSTrajectory tj,PetscBool solution_only)
907 {
908   PetscFunctionBegin;
909   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
910   PetscValidLogicalCollectiveBool(tj,solution_only,2);
911   tj->solution_only = solution_only;
912   PetscFunctionReturn(0);
913 }
914 
915 /*@
916    TSTrajectoryGetSolutionOnly - Gets the value set with TSTrajectorySetSolutionOnly.
917 
918    Logically collective on TSTrajectory
919 
920    Input Parameter:
921 .  tj  - the TS trajectory context
922 
923    Output Parameter:
924 .  flg - the boolean flag
925 
926    Level: developer
927 
928 .seealso: `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetSolutionOnly()`
929 @*/
930 PetscErrorCode TSTrajectoryGetSolutionOnly(TSTrajectory tj,PetscBool *solution_only)
931 {
932   PetscFunctionBegin;
933   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
934   PetscValidBoolPointer(solution_only,2);
935   *solution_only = tj->solution_only;
936   PetscFunctionReturn(0);
937 }
938 
939 /*@
940    TSTrajectoryGetUpdatedHistoryVecs - Get updated state and time-derivative history vectors.
941 
942    Collective on TSTrajectory
943 
944    Input Parameters:
945 +  tj   - the TS trajectory context
946 .  ts   - the TS solver context
947 -  time - the requested time
948 
949    Output Parameters:
950 +  U    - state vector at given time (can be interpolated)
951 -  Udot - time-derivative vector at given time (can be interpolated)
952 
953    Level: developer
954 
955    Notes: The vectors are interpolated if time does not match any time step stored in the TSTrajectory(). Pass NULL to not request a vector.
956           This function differs from TSTrajectoryGetVecs since the vectors obtained cannot be modified, and they need to be returned by
957           calling TSTrajectoryRestoreUpdatedHistoryVecs().
958 
959 .seealso: `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectoryRestoreUpdatedHistoryVecs()`, `TSTrajectoryGetVecs()`
960 @*/
961 PetscErrorCode TSTrajectoryGetUpdatedHistoryVecs(TSTrajectory tj, TS ts, PetscReal time, Vec *U, Vec *Udot)
962 {
963   PetscFunctionBegin;
964   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
965   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
966   PetscValidLogicalCollectiveReal(tj,time,3);
967   if (U) PetscValidPointer(U,4);
968   if (Udot) PetscValidPointer(Udot,5);
969   if (U && !tj->U) {
970     DM dm;
971 
972     PetscCall(TSGetDM(ts,&dm));
973     PetscCall(DMCreateGlobalVector(dm,&tj->U));
974   }
975   if (Udot && !tj->Udot) {
976     DM dm;
977 
978     PetscCall(TSGetDM(ts,&dm));
979     PetscCall(DMCreateGlobalVector(dm,&tj->Udot));
980   }
981   PetscCall(TSTrajectoryGetVecs(tj,ts,PETSC_DECIDE,&time,U ? tj->U : NULL,Udot ? tj->Udot : NULL));
982   if (U) {
983     PetscCall(VecLockReadPush(tj->U));
984     *U   = tj->U;
985   }
986   if (Udot) {
987     PetscCall(VecLockReadPush(tj->Udot));
988     *Udot = tj->Udot;
989   }
990   PetscFunctionReturn(0);
991 }
992 
993 /*@
994    TSTrajectoryRestoreUpdatedHistoryVecs - Restores updated state and time-derivative history vectors obtained with TSTrajectoryGetUpdatedHistoryVecs().
995 
996    Collective on TSTrajectory
997 
998    Input Parameters:
999 +  tj   - the TS trajectory context
1000 .  U    - state vector at given time (can be interpolated)
1001 -  Udot - time-derivative vector at given time (can be interpolated)
1002 
1003    Level: developer
1004 
1005 .seealso: `TSTrajectoryGetUpdatedHistoryVecs()`
1006 @*/
1007 PetscErrorCode TSTrajectoryRestoreUpdatedHistoryVecs(TSTrajectory tj, Vec *U, Vec *Udot)
1008 {
1009   PetscFunctionBegin;
1010   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
1011   if (U) PetscValidHeaderSpecific(*U,VEC_CLASSID,2);
1012   if (Udot) PetscValidHeaderSpecific(*Udot,VEC_CLASSID,3);
1013   PetscCheck(!U || *U == tj->U,PetscObjectComm((PetscObject)*U),PETSC_ERR_USER,"U was not obtained from TSTrajectoryGetUpdatedHistoryVecs()");
1014   PetscCheck(!Udot || *Udot == tj->Udot,PetscObjectComm((PetscObject)*Udot),PETSC_ERR_USER,"Udot was not obtained from TSTrajectoryGetUpdatedHistoryVecs()");
1015   if (U) {
1016     PetscCall(VecLockReadPop(tj->U));
1017     *U   = NULL;
1018   }
1019   if (Udot) {
1020     PetscCall(VecLockReadPop(tj->Udot));
1021     *Udot = NULL;
1022   }
1023   PetscFunctionReturn(0);
1024 }
1025