xref: /petsc/src/ts/trajectory/interface/traj.c (revision 71052fdfa316db9eff6713675d06cb2251c7acfb)
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   PetscCall((*tj->ops->set)(tj,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   PetscCall((*tj->ops->get)(tj,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     if (tj->ops->view) {
323       PetscCall(PetscViewerASCIIPushTab(viewer));
324       PetscCall((*tj->ops->view)(tj,viewer));
325       PetscCall(PetscViewerASCIIPopTab(viewer));
326     }
327   }
328   PetscFunctionReturn(0);
329 }
330 
331 /*@C
332    TSTrajectorySetVariableNames - Sets the name of each component in the solution vector so that it may be saved with the trajectory
333 
334    Collective on TSTrajectory
335 
336    Input Parameters:
337 +  tr - the trajectory context
338 -  names - the names of the components, final string must be NULL
339 
340    Level: intermediate
341 
342    Note: Fortran interface is not possible because of the string array argument
343 
344 .seealso: `TSTrajectory`, `TSGetTrajectory()`
345 @*/
346 PetscErrorCode  TSTrajectorySetVariableNames(TSTrajectory ctx,const char * const *names)
347 {
348   PetscFunctionBegin;
349   PetscValidHeaderSpecific(ctx,TSTRAJECTORY_CLASSID,1);
350   PetscValidPointer(names,2);
351   PetscCall(PetscStrArrayDestroy(&ctx->names));
352   PetscCall(PetscStrArrayallocpy(names,&ctx->names));
353   PetscFunctionReturn(0);
354 }
355 
356 /*@C
357    TSTrajectorySetTransform - Solution vector will be transformed by provided function before being saved to disk
358 
359    Collective on TSLGCtx
360 
361    Input Parameters:
362 +  tj - the TSTrajectory context
363 .  transform - the transform function
364 .  destroy - function to destroy the optional context
365 -  ctx - optional context used by transform function
366 
367    Level: intermediate
368 
369 .seealso: `TSTrajectorySetVariableNames()`, `TSTrajectory`, `TSMonitorLGSetTransform()`
370 @*/
371 PetscErrorCode  TSTrajectorySetTransform(TSTrajectory tj,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
372 {
373   PetscFunctionBegin;
374   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
375   tj->transform        = transform;
376   tj->transformdestroy = destroy;
377   tj->transformctx     = tctx;
378   PetscFunctionReturn(0);
379 }
380 
381 /*@
382   TSTrajectoryCreate - This function creates an empty trajectory object used to store the time dependent solution of an ODE/DAE
383 
384   Collective
385 
386   Input Parameter:
387 . comm - the communicator
388 
389   Output Parameter:
390 . tj   - the trajectory object
391 
392   Level: developer
393 
394   Notes:
395     Usually one does not call this routine, it is called automatically when one calls TSSetSaveTrajectory().
396 
397 .seealso: `TSTrajectorySetUp()`, `TSTrajectoryDestroy()`, `TSTrajectorySetType()`, `TSTrajectorySetVariableNames()`, `TSGetTrajectory()`, `TSTrajectorySetKeepFiles()`
398 @*/
399 PetscErrorCode  TSTrajectoryCreate(MPI_Comm comm,TSTrajectory *tj)
400 {
401   TSTrajectory   t;
402 
403   PetscFunctionBegin;
404   PetscValidPointer(tj,2);
405   *tj = NULL;
406   PetscCall(TSInitializePackage());
407 
408   PetscCall(PetscHeaderCreate(t,TSTRAJECTORY_CLASSID,"TSTrajectory","Time stepping","TS",comm,TSTrajectoryDestroy,TSTrajectoryView));
409   t->setupcalled = PETSC_FALSE;
410   PetscCall(TSHistoryCreate(comm,&t->tsh));
411 
412   t->lag.order            = 1;
413   t->lag.L                = NULL;
414   t->lag.T                = NULL;
415   t->lag.W                = NULL;
416   t->lag.WW               = NULL;
417   t->lag.TW               = NULL;
418   t->lag.TT               = NULL;
419   t->lag.caching          = PETSC_TRUE;
420   t->lag.Ucached.id       = 0;
421   t->lag.Ucached.state    = -1;
422   t->lag.Ucached.time     = PETSC_MIN_REAL;
423   t->lag.Ucached.step     = PETSC_MAX_INT;
424   t->lag.Udotcached.id    = 0;
425   t->lag.Udotcached.state = -1;
426   t->lag.Udotcached.time  = PETSC_MIN_REAL;
427   t->lag.Udotcached.step  = PETSC_MAX_INT;
428   t->adjoint_solve_mode   = PETSC_TRUE;
429   t->solution_only        = PETSC_FALSE;
430   t->keepfiles            = PETSC_FALSE;
431   t->usehistory           = PETSC_TRUE;
432   *tj  = t;
433   PetscCall(TSTrajectorySetFiletemplate(t,"TS-%06" PetscInt_FMT ".bin"));
434   PetscFunctionReturn(0);
435 }
436 
437 /*@C
438   TSTrajectorySetType - Sets the storage method to be used as in a trajectory
439 
440   Collective on TS
441 
442   Input Parameters:
443 + tj   - the TSTrajectory context
444 . ts   - the TS context
445 - type - a known method
446 
447   Options Database Command:
448 . -ts_trajectory_type <type> - Sets the method; use -help for a list of available methods (for instance, basic)
449 
450    Level: developer
451 
452 .seealso: `TS`, `TSTrajectoryCreate()`, `TSTrajectorySetFromOptions()`, `TSTrajectoryDestroy()`, `TSTrajectoryGetType()`
453 
454 @*/
455 PetscErrorCode  TSTrajectorySetType(TSTrajectory tj,TS ts,TSTrajectoryType type)
456 {
457   PetscErrorCode (*r)(TSTrajectory,TS);
458   PetscBool      match;
459 
460   PetscFunctionBegin;
461   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
462   PetscCall(PetscObjectTypeCompare((PetscObject)tj,type,&match));
463   if (match) PetscFunctionReturn(0);
464 
465   PetscCall(PetscFunctionListFind(TSTrajectoryList,type,&r));
466   PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSTrajectory type: %s",type);
467   if (tj->ops->destroy) {
468     PetscCall((*(tj)->ops->destroy)(tj));
469 
470     tj->ops->destroy = NULL;
471   }
472   PetscCall(PetscMemzero(tj->ops,sizeof(*tj->ops)));
473 
474   PetscCall(PetscObjectChangeTypeName((PetscObject)tj,type));
475   PetscCall((*r)(tj,ts));
476   PetscFunctionReturn(0);
477 }
478 
479 /*@C
480   TSTrajectoryGetType - Gets the trajectory type
481 
482   Collective on TS
483 
484   Input Parameters:
485 + tj   - the TSTrajectory context
486 - ts   - the TS context
487 
488   Output Parameters:
489 . type - a known method
490 
491   Level: developer
492 
493 .seealso: `TS`, `TSTrajectoryCreate()`, `TSTrajectorySetFromOptions()`, `TSTrajectoryDestroy()`, `TSTrajectorySetType()`
494 
495 @*/
496 PetscErrorCode TSTrajectoryGetType(TSTrajectory tj,TS ts,TSTrajectoryType *type)
497 {
498   PetscFunctionBegin;
499   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
500   if (type) *type = ((PetscObject)tj)->type_name;
501   PetscFunctionReturn(0);
502 }
503 
504 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Basic(TSTrajectory,TS);
505 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Singlefile(TSTrajectory,TS);
506 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Memory(TSTrajectory,TS);
507 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Visualization(TSTrajectory,TS);
508 
509 /*@C
510   TSTrajectoryRegisterAll - Registers all of the trajectory storage schecmes in the TS package.
511 
512   Not Collective
513 
514   Level: developer
515 
516 .seealso: `TSTrajectoryRegister()`
517 @*/
518 PetscErrorCode  TSTrajectoryRegisterAll(void)
519 {
520   PetscFunctionBegin;
521   if (TSTrajectoryRegisterAllCalled) PetscFunctionReturn(0);
522   TSTrajectoryRegisterAllCalled = PETSC_TRUE;
523 
524   PetscCall(TSTrajectoryRegister(TSTRAJECTORYBASIC,TSTrajectoryCreate_Basic));
525   PetscCall(TSTrajectoryRegister(TSTRAJECTORYSINGLEFILE,TSTrajectoryCreate_Singlefile));
526   PetscCall(TSTrajectoryRegister(TSTRAJECTORYMEMORY,TSTrajectoryCreate_Memory));
527   PetscCall(TSTrajectoryRegister(TSTRAJECTORYVISUALIZATION,TSTrajectoryCreate_Visualization));
528   PetscFunctionReturn(0);
529 }
530 
531 /*@
532    TSTrajectoryReset - Resets a trajectory context
533 
534    Collective on TSTrajectory
535 
536    Input Parameter:
537 .  tj - the TSTrajectory context obtained from TSTrajectoryCreate()
538 
539    Level: developer
540 
541 .seealso: `TSTrajectoryCreate()`, `TSTrajectorySetUp()`
542 @*/
543 PetscErrorCode TSTrajectoryReset(TSTrajectory tj)
544 {
545   PetscFunctionBegin;
546   if (!tj) PetscFunctionReturn(0);
547   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
548   if (tj->ops->reset) PetscCall((*tj->ops->reset)(tj));
549   PetscCall(PetscFree(tj->dirfiletemplate));
550   PetscCall(TSHistoryDestroy(&tj->tsh));
551   PetscCall(TSHistoryCreate(PetscObjectComm((PetscObject)tj),&tj->tsh));
552   tj->setupcalled = PETSC_FALSE;
553   PetscFunctionReturn(0);
554 }
555 
556 /*@
557    TSTrajectoryDestroy - Destroys a trajectory context
558 
559    Collective on TSTrajectory
560 
561    Input Parameter:
562 .  tj - the TSTrajectory context obtained from TSTrajectoryCreate()
563 
564    Level: developer
565 
566 .seealso: `TSTrajectoryCreate()`, `TSTrajectorySetUp()`
567 @*/
568 PetscErrorCode TSTrajectoryDestroy(TSTrajectory *tj)
569 {
570   PetscFunctionBegin;
571   if (!*tj) PetscFunctionReturn(0);
572   PetscValidHeaderSpecific((*tj),TSTRAJECTORY_CLASSID,1);
573   if (--((PetscObject)(*tj))->refct > 0) {*tj = NULL; PetscFunctionReturn(0);}
574 
575   PetscCall(TSTrajectoryReset(*tj));
576   PetscCall(TSHistoryDestroy(&(*tj)->tsh));
577   PetscCall(VecDestroyVecs((*tj)->lag.order+1,&(*tj)->lag.W));
578   PetscCall(PetscFree5((*tj)->lag.L,(*tj)->lag.T,(*tj)->lag.WW,(*tj)->lag.TT,(*tj)->lag.TW));
579   PetscCall(VecDestroy(&(*tj)->U));
580   PetscCall(VecDestroy(&(*tj)->Udot));
581 
582   if ((*tj)->transformdestroy) PetscCall((*(*tj)->transformdestroy)((*tj)->transformctx));
583   if ((*tj)->ops->destroy) PetscCall((*(*tj)->ops->destroy)((*tj)));
584   if (!((*tj)->keepfiles)) {
585     PetscMPIInt rank;
586     MPI_Comm    comm;
587 
588     PetscCall(PetscObjectGetComm((PetscObject)(*tj),&comm));
589     PetscCallMPI(MPI_Comm_rank(comm,&rank));
590     if (rank == 0 && (*tj)->dirname) { /* we own the directory, so we run PetscRMTree on it */
591       PetscCall(PetscRMTree((*tj)->dirname));
592     }
593   }
594   PetscCall(PetscStrArrayDestroy(&(*tj)->names));
595   PetscCall(PetscFree((*tj)->dirname));
596   PetscCall(PetscFree((*tj)->filetemplate));
597   PetscCall(PetscHeaderDestroy(tj));
598   PetscFunctionReturn(0);
599 }
600 
601 /*
602   TSTrajectorySetTypeFromOptions_Private - Sets the type of ts from user options.
603 
604   Collective on TSTrajectory
605 
606   Input Parameter:
607 + tj - the TSTrajectory context
608 - ts - the TS context
609 
610   Options Database Keys:
611 . -ts_trajectory_type <type> - TSTRAJECTORYBASIC, TSTRAJECTORYMEMORY, TSTRAJECTORYSINGLEFILE, TSTRAJECTORYVISUALIZATION
612 
613   Level: developer
614 
615 .seealso: `TSTrajectorySetFromOptions()`, `TSTrajectorySetType()`
616 */
617 static PetscErrorCode TSTrajectorySetTypeFromOptions_Private(PetscOptionItems *PetscOptionsObject,TSTrajectory tj,TS ts)
618 {
619   PetscBool      opt;
620   const char     *defaultType;
621   char           typeName[256];
622 
623   PetscFunctionBegin;
624   if (((PetscObject)tj)->type_name) defaultType = ((PetscObject)tj)->type_name;
625   else defaultType = TSTRAJECTORYBASIC;
626 
627   PetscCall(TSTrajectoryRegisterAll());
628   PetscCall(PetscOptionsFList("-ts_trajectory_type","TSTrajectory method","TSTrajectorySetType",TSTrajectoryList,defaultType,typeName,256,&opt));
629   if (opt) {
630     PetscCall(TSTrajectorySetType(tj,ts,typeName));
631   } else {
632     PetscCall(TSTrajectorySetType(tj,ts,defaultType));
633   }
634   PetscFunctionReturn(0);
635 }
636 
637 /*@
638    TSTrajectorySetUseHistory - Use TSHistory in TSTrajectory
639 
640    Collective on TSTrajectory
641 
642    Input Parameters:
643 +  tj - the TSTrajectory context
644 -  flg - PETSC_TRUE to save, PETSC_FALSE to disable
645 
646    Options Database Keys:
647 .  -ts_trajectory_use_history - have it use TSHistory
648 
649    Level: advanced
650 
651 .seealso: `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetUp()`
652 @*/
653 PetscErrorCode TSTrajectorySetUseHistory(TSTrajectory tj,PetscBool flg)
654 {
655   PetscFunctionBegin;
656   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
657   PetscValidLogicalCollectiveBool(tj,flg,2);
658   tj->usehistory = flg;
659   PetscFunctionReturn(0);
660 }
661 
662 /*@
663    TSTrajectorySetMonitor - Monitor the schedules generated by the checkpointing controller
664 
665    Collective on TSTrajectory
666 
667    Input Parameters:
668 +  tj - the TSTrajectory context
669 -  flg - PETSC_TRUE to active a monitor, PETSC_FALSE to disable
670 
671    Options Database Keys:
672 .  -ts_trajectory_monitor - print TSTrajectory information
673 
674    Level: developer
675 
676 .seealso: `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetUp()`
677 @*/
678 PetscErrorCode TSTrajectorySetMonitor(TSTrajectory tj,PetscBool flg)
679 {
680   PetscFunctionBegin;
681   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
682   PetscValidLogicalCollectiveBool(tj,flg,2);
683   if (flg) tj->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)tj));
684   else tj->monitor = NULL;
685   PetscFunctionReturn(0);
686 }
687 
688 /*@
689    TSTrajectorySetKeepFiles - Keep the files generated by the TSTrajectory
690 
691    Collective on TSTrajectory
692 
693    Input Parameters:
694 +  tj - the TSTrajectory context
695 -  flg - PETSC_TRUE to save, PETSC_FALSE to disable
696 
697    Options Database Keys:
698 .  -ts_trajectory_keep_files - have it keep the files
699 
700    Notes:
701     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.
702 
703    Level: advanced
704 
705 .seealso: `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetUp()`, `TSTrajectorySetMonitor()`
706 @*/
707 PetscErrorCode TSTrajectorySetKeepFiles(TSTrajectory tj,PetscBool flg)
708 {
709   PetscFunctionBegin;
710   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
711   PetscValidLogicalCollectiveBool(tj,flg,2);
712   tj->keepfiles = flg;
713   PetscFunctionReturn(0);
714 }
715 
716 /*@C
717    TSTrajectorySetDirname - Specify the name of the directory where disk checkpoints are stored.
718 
719    Collective on TSTrajectory
720 
721    Input Parameters:
722 +  tj      - the TSTrajectory context
723 -  dirname - the directory name
724 
725    Options Database Keys:
726 .  -ts_trajectory_dirname - set the directory name
727 
728    Notes:
729     The final location of the files is determined by dirname/filetemplate where filetemplate was provided by TSTrajectorySetFiletemplate()
730 
731    Level: developer
732 
733 .seealso: `TSTrajectorySetFiletemplate()`, `TSTrajectorySetUp()`
734 @*/
735 PetscErrorCode TSTrajectorySetDirname(TSTrajectory tj,const char dirname[])
736 {
737   PetscBool      flg;
738 
739   PetscFunctionBegin;
740   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
741   PetscCall(PetscStrcmp(tj->dirname,dirname,&flg));
742   PetscCheck(flg || !tj->dirfiletemplate,PetscObjectComm((PetscObject)tj),PETSC_ERR_ARG_WRONGSTATE,"Cannot set directoryname after TSTrajectory has been setup");
743   PetscCall(PetscFree(tj->dirname));
744   PetscCall(PetscStrallocpy(dirname,&tj->dirname));
745   PetscFunctionReturn(0);
746 }
747 
748 /*@C
749    TSTrajectorySetFiletemplate - Specify the name template for the files storing checkpoints.
750 
751    Collective on TSTrajectory
752 
753    Input Parameters:
754 +  tj      - the TSTrajectory context
755 -  filetemplate - the template
756 
757    Options Database Keys:
758 .  -ts_trajectory_file_template - set the file name template
759 
760    Notes:
761     The name template should be of the form, for example filename-%06" PetscInt_FMT ".bin It should not begin with a leading /
762 
763    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
764    timestep counter
765 
766    Level: developer
767 
768 .seealso: `TSTrajectorySetDirname()`, `TSTrajectorySetUp()`
769 @*/
770 PetscErrorCode TSTrajectorySetFiletemplate(TSTrajectory tj,const char filetemplate[])
771 {
772   const char     *ptr,*ptr2;
773 
774   PetscFunctionBegin;
775   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
776   PetscValidCharPointer(filetemplate,2);
777   PetscCheck(!tj->dirfiletemplate,PetscObjectComm((PetscObject)tj),PETSC_ERR_ARG_WRONGSTATE,"Cannot set filetemplate after TSTrajectory has been setup");
778 
779   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");
780   /* Do some cursory validation of the input. */
781   PetscCall(PetscStrstr(filetemplate,"%",(char**)&ptr));
782   PetscCheck(ptr,PetscObjectComm((PetscObject)tj),PETSC_ERR_USER,"-ts_trajectory_file_template requires a file name template, e.g. filename-%%06" PetscInt_FMT ".bin");
783   for (ptr++; ptr && *ptr; ptr++) {
784     PetscCall(PetscStrchr(PetscInt_FMT "DiouxX",*ptr,(char**)&ptr2));
785     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");
786     if (ptr2) break;
787   }
788   PetscCall(PetscFree(tj->filetemplate));
789   PetscCall(PetscStrallocpy(filetemplate,&tj->filetemplate));
790   PetscFunctionReturn(0);
791 }
792 
793 /*@
794    TSTrajectorySetFromOptions - Sets various TSTrajectory parameters from user options.
795 
796    Collective on TSTrajectory
797 
798    Input Parameters:
799 +  tj - the TSTrajectory context obtained from TSTrajectoryCreate()
800 -  ts - the TS context
801 
802    Options Database Keys:
803 +  -ts_trajectory_type <type> - TSTRAJECTORYBASIC, TSTRAJECTORYMEMORY, TSTRAJECTORYSINGLEFILE, TSTRAJECTORYVISUALIZATION
804 .  -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
805 -  -ts_trajectory_monitor - print TSTrajectory information
806 
807    Level: developer
808 
809    Notes:
810     This is not normally called directly by users
811 
812 .seealso: `TSSetSaveTrajectory()`, `TSTrajectorySetUp()`
813 @*/
814 PetscErrorCode  TSTrajectorySetFromOptions(TSTrajectory tj,TS ts)
815 {
816   PetscBool      set,flg;
817   char           dirname[PETSC_MAX_PATH_LEN],filetemplate[PETSC_MAX_PATH_LEN];
818 
819   PetscFunctionBegin;
820   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
821   if (ts) PetscValidHeaderSpecific(ts,TS_CLASSID,2);
822   PetscObjectOptionsBegin((PetscObject)tj);
823   PetscCall(TSTrajectorySetTypeFromOptions_Private(PetscOptionsObject,tj,ts));
824   PetscCall(PetscOptionsBool("-ts_trajectory_use_history","Turn on/off usage of TSHistory",NULL,tj->usehistory,&tj->usehistory,NULL));
825   PetscCall(PetscOptionsBool("-ts_trajectory_monitor","Print checkpointing schedules","TSTrajectorySetMonitor",tj->monitor ? PETSC_TRUE:PETSC_FALSE,&flg,&set));
826   if (set) PetscCall(TSTrajectorySetMonitor(tj,flg));
827   PetscCall(PetscOptionsInt("-ts_trajectory_reconstruction_order","Interpolation order for reconstruction",NULL,tj->lag.order,&tj->lag.order,NULL));
828   PetscCall(PetscOptionsBool("-ts_trajectory_reconstruction_caching","Turn on/off caching of TSTrajectoryGetVecs input",NULL,tj->lag.caching,&tj->lag.caching,NULL));
829   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));
830   PetscCall(PetscOptionsBool("-ts_trajectory_solution_only","Checkpoint solution only","TSTrajectorySetSolutionOnly",tj->solution_only,&tj->solution_only,NULL));
831   PetscCall(PetscOptionsBool("-ts_trajectory_keep_files","Keep any trajectory files generated during the run","TSTrajectorySetKeepFiles",tj->keepfiles,&flg,&set));
832   if (set) PetscCall(TSTrajectorySetKeepFiles(tj,flg));
833 
834   PetscCall(PetscOptionsString("-ts_trajectory_dirname","Directory name for TSTrajectory file","TSTrajectorySetDirname",NULL,dirname,sizeof(dirname)-14,&set));
835   if (set) PetscCall(TSTrajectorySetDirname(tj,dirname));
836 
837   PetscCall(PetscOptionsString("-ts_trajectory_file_template","Template for TSTrajectory file name, use filename-%06" PetscInt_FMT ".bin","TSTrajectorySetFiletemplate",NULL,filetemplate,sizeof(filetemplate),&set));
838   if (set) PetscCall(TSTrajectorySetFiletemplate(tj,filetemplate));
839 
840   /* Handle specific TSTrajectory options */
841   if (tj->ops->setfromoptions) PetscCall((*tj->ops->setfromoptions)(PetscOptionsObject,tj));
842   PetscOptionsEnd();
843   PetscFunctionReturn(0);
844 }
845 
846 /*@
847    TSTrajectorySetUp - Sets up the internal data structures, e.g. stacks, for the later use
848    of a TS trajectory.
849 
850    Collective on TS
851 
852    Input Parameters:
853 +  ts - the TS context obtained from TSCreate()
854 -  tj - the TS trajectory context
855 
856    Level: developer
857 
858 .seealso: `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`
859 @*/
860 PetscErrorCode  TSTrajectorySetUp(TSTrajectory tj,TS ts)
861 {
862   size_t         s1,s2;
863 
864   PetscFunctionBegin;
865   if (!tj) PetscFunctionReturn(0);
866   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
867   if (ts) PetscValidHeaderSpecific(ts,TS_CLASSID,2);
868   if (tj->setupcalled) PetscFunctionReturn(0);
869 
870   PetscCall(PetscLogEventBegin(TSTrajectory_SetUp,tj,ts,0,0));
871   if (!((PetscObject)tj)->type_name) {
872     PetscCall(TSTrajectorySetType(tj,ts,TSTRAJECTORYBASIC));
873   }
874   if (tj->ops->setup) PetscCall((*tj->ops->setup)(tj,ts));
875 
876   tj->setupcalled = PETSC_TRUE;
877 
878   /* Set the counters to zero */
879   tj->recomps    = 0;
880   tj->diskreads  = 0;
881   tj->diskwrites = 0;
882   PetscCall(PetscStrlen(tj->dirname,&s1));
883   PetscCall(PetscStrlen(tj->filetemplate,&s2));
884   PetscCall(PetscFree(tj->dirfiletemplate));
885   PetscCall(PetscMalloc((s1 + s2 + 10)*sizeof(char),&tj->dirfiletemplate));
886   PetscCall(PetscSNPrintf(tj->dirfiletemplate,s1+s2+10,"%s/%s",tj->dirname,tj->filetemplate));
887   PetscCall(PetscLogEventEnd(TSTrajectory_SetUp,tj,ts,0,0));
888   PetscFunctionReturn(0);
889 }
890 
891 /*@
892    TSTrajectorySetSolutionOnly - Tells the trajectory to store just the solution, and not any intermediate stage also.
893 
894    Collective on TSTrajectory
895 
896    Input Parameters:
897 +  tj  - the TS trajectory context
898 -  flg - the boolean flag
899 
900    Level: developer
901 
902 .seealso: `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectoryGetSolutionOnly()`
903 @*/
904 PetscErrorCode TSTrajectorySetSolutionOnly(TSTrajectory tj,PetscBool solution_only)
905 {
906   PetscFunctionBegin;
907   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
908   PetscValidLogicalCollectiveBool(tj,solution_only,2);
909   tj->solution_only = solution_only;
910   PetscFunctionReturn(0);
911 }
912 
913 /*@
914    TSTrajectoryGetSolutionOnly - Gets the value set with TSTrajectorySetSolutionOnly.
915 
916    Logically collective on TSTrajectory
917 
918    Input Parameter:
919 .  tj  - the TS trajectory context
920 
921    Output Parameter:
922 .  flg - the boolean flag
923 
924    Level: developer
925 
926 .seealso: `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetSolutionOnly()`
927 @*/
928 PetscErrorCode TSTrajectoryGetSolutionOnly(TSTrajectory tj,PetscBool *solution_only)
929 {
930   PetscFunctionBegin;
931   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
932   PetscValidBoolPointer(solution_only,2);
933   *solution_only = tj->solution_only;
934   PetscFunctionReturn(0);
935 }
936 
937 /*@
938    TSTrajectoryGetUpdatedHistoryVecs - Get updated state and time-derivative history vectors.
939 
940    Collective on TSTrajectory
941 
942    Input Parameters:
943 +  tj   - the TS trajectory context
944 .  ts   - the TS solver context
945 -  time - the requested time
946 
947    Output Parameters:
948 +  U    - state vector at given time (can be interpolated)
949 -  Udot - time-derivative vector at given time (can be interpolated)
950 
951    Level: developer
952 
953    Notes: The vectors are interpolated if time does not match any time step stored in the TSTrajectory(). Pass NULL to not request a vector.
954           This function differs from TSTrajectoryGetVecs since the vectors obtained cannot be modified, and they need to be returned by
955           calling TSTrajectoryRestoreUpdatedHistoryVecs().
956 
957 .seealso: `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectoryRestoreUpdatedHistoryVecs()`, `TSTrajectoryGetVecs()`
958 @*/
959 PetscErrorCode TSTrajectoryGetUpdatedHistoryVecs(TSTrajectory tj, TS ts, PetscReal time, Vec *U, Vec *Udot)
960 {
961   PetscFunctionBegin;
962   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
963   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
964   PetscValidLogicalCollectiveReal(tj,time,3);
965   if (U) PetscValidPointer(U,4);
966   if (Udot) PetscValidPointer(Udot,5);
967   if (U && !tj->U) {
968     DM dm;
969 
970     PetscCall(TSGetDM(ts,&dm));
971     PetscCall(DMCreateGlobalVector(dm,&tj->U));
972   }
973   if (Udot && !tj->Udot) {
974     DM dm;
975 
976     PetscCall(TSGetDM(ts,&dm));
977     PetscCall(DMCreateGlobalVector(dm,&tj->Udot));
978   }
979   PetscCall(TSTrajectoryGetVecs(tj,ts,PETSC_DECIDE,&time,U ? tj->U : NULL,Udot ? tj->Udot : NULL));
980   if (U) {
981     PetscCall(VecLockReadPush(tj->U));
982     *U   = tj->U;
983   }
984   if (Udot) {
985     PetscCall(VecLockReadPush(tj->Udot));
986     *Udot = tj->Udot;
987   }
988   PetscFunctionReturn(0);
989 }
990 
991 /*@
992    TSTrajectoryRestoreUpdatedHistoryVecs - Restores updated state and time-derivative history vectors obtained with TSTrajectoryGetUpdatedHistoryVecs().
993 
994    Collective on TSTrajectory
995 
996    Input Parameters:
997 +  tj   - the TS trajectory context
998 .  U    - state vector at given time (can be interpolated)
999 -  Udot - time-derivative vector at given time (can be interpolated)
1000 
1001    Level: developer
1002 
1003 .seealso: `TSTrajectoryGetUpdatedHistoryVecs()`
1004 @*/
1005 PetscErrorCode TSTrajectoryRestoreUpdatedHistoryVecs(TSTrajectory tj, Vec *U, Vec *Udot)
1006 {
1007   PetscFunctionBegin;
1008   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
1009   if (U) PetscValidHeaderSpecific(*U,VEC_CLASSID,2);
1010   if (Udot) PetscValidHeaderSpecific(*Udot,VEC_CLASSID,3);
1011   PetscCheck(!U || *U == tj->U,PetscObjectComm((PetscObject)*U),PETSC_ERR_USER,"U was not obtained from TSTrajectoryGetUpdatedHistoryVecs()");
1012   PetscCheck(!Udot || *Udot == tj->Udot,PetscObjectComm((PetscObject)*Udot),PETSC_ERR_USER,"Udot was not obtained from TSTrajectoryGetUpdatedHistoryVecs()");
1013   if (U) {
1014     PetscCall(VecLockReadPop(tj->U));
1015     *U   = NULL;
1016   }
1017   if (Udot) {
1018     PetscCall(VecLockReadPop(tj->Udot));
1019     *Udot = NULL;
1020   }
1021   PetscFunctionReturn(0);
1022 }
1023