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