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