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