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