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