xref: /petsc/src/ts/trajectory/interface/traj.c (revision 6a0bd7522af7eb76a79ca5f1af77fc9a30e8cdb2)
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 = TSTrajectorySetFiletemplate(t,"TS-%06D.bin");CHKERRQ(ierr);
451   PetscFunctionReturn(0);
452 }
453 
454 /*@C
455   TSTrajectorySetType - Sets the storage method to be used as in a trajectory
456 
457   Collective on TS
458 
459   Input Parameters:
460 + tj   - the TSTrajectory context
461 . ts   - the TS context
462 - type - a known method
463 
464   Options Database Command:
465 . -ts_trajectory_type <type> - Sets the method; use -help for a list of available methods (for instance, basic)
466 
467    Level: developer
468 
469 .keywords: TS, trajectory, timestep, set, type
470 
471 .seealso: TS, TSTrajectoryCreate(), TSTrajectorySetFromOptions(), TSTrajectoryDestroy(), TSTrajectoryGetType()
472 
473 @*/
474 PetscErrorCode  TSTrajectorySetType(TSTrajectory tj,TS ts,TSTrajectoryType type)
475 {
476   PetscErrorCode (*r)(TSTrajectory,TS);
477   PetscBool      match;
478   PetscErrorCode ierr;
479 
480   PetscFunctionBegin;
481   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
482   ierr = PetscObjectTypeCompare((PetscObject)tj,type,&match);CHKERRQ(ierr);
483   if (match) PetscFunctionReturn(0);
484 
485   ierr = PetscFunctionListFind(TSTrajectoryList,type,&r);CHKERRQ(ierr);
486   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSTrajectory type: %s",type);
487   if (tj->ops->destroy) {
488     ierr = (*(tj)->ops->destroy)(tj);CHKERRQ(ierr);
489 
490     tj->ops->destroy = NULL;
491   }
492   ierr = PetscMemzero(tj->ops,sizeof(*tj->ops));CHKERRQ(ierr);
493 
494   ierr = PetscObjectChangeTypeName((PetscObject)tj,type);CHKERRQ(ierr);
495   ierr = (*r)(tj,ts);CHKERRQ(ierr);
496   PetscFunctionReturn(0);
497 }
498 
499 /*@C
500   TSTrajectoryGetType - Gets the trajectory type
501 
502   Collective on TS
503 
504   Input Parameters:
505 + tj   - the TSTrajectory context
506 - ts   - the TS context
507 
508   Output Parameters:
509 . type - a known method
510 
511   Level: developer
512 
513 .keywords: TS, trajectory, timestep, get, type
514 
515 .seealso: TS, TSTrajectoryCreate(), TSTrajectorySetFromOptions(), TSTrajectoryDestroy(), TSTrajectorySetType()
516 
517 @*/
518 PetscErrorCode TSTrajectoryGetType(TSTrajectory tj,TS ts,TSTrajectoryType *type)
519 {
520   PetscFunctionBegin;
521   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
522   if (type) *type = ((PetscObject)tj)->type_name;
523   PetscFunctionReturn(0);
524 }
525 
526 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Basic(TSTrajectory,TS);
527 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Singlefile(TSTrajectory,TS);
528 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Memory(TSTrajectory,TS);
529 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Visualization(TSTrajectory,TS);
530 
531 /*@C
532   TSTrajectoryRegisterAll - Registers all of the trajectory storage schecmes in the TS package.
533 
534   Not Collective
535 
536   Level: developer
537 
538 .keywords: TS, trajectory, register, all
539 
540 .seealso: TSTrajectoryRegister()
541 @*/
542 PetscErrorCode  TSTrajectoryRegisterAll(void)
543 {
544   PetscErrorCode ierr;
545 
546   PetscFunctionBegin;
547   if (TSTrajectoryRegisterAllCalled) PetscFunctionReturn(0);
548   TSTrajectoryRegisterAllCalled = PETSC_TRUE;
549 
550   ierr = TSTrajectoryRegister(TSTRAJECTORYBASIC,TSTrajectoryCreate_Basic);CHKERRQ(ierr);
551   ierr = TSTrajectoryRegister(TSTRAJECTORYSINGLEFILE,TSTrajectoryCreate_Singlefile);CHKERRQ(ierr);
552   ierr = TSTrajectoryRegister(TSTRAJECTORYMEMORY,TSTrajectoryCreate_Memory);CHKERRQ(ierr);
553   ierr = TSTrajectoryRegister(TSTRAJECTORYVISUALIZATION,TSTrajectoryCreate_Visualization);CHKERRQ(ierr);
554   PetscFunctionReturn(0);
555 }
556 
557 /*@
558    TSTrajectoryReset - Resets a trajectory context
559 
560    Collective on TSTrajectory
561 
562    Input Parameter:
563 .  tj - the TSTrajectory context obtained from TSTrajectoryCreate()
564 
565    Level: developer
566 
567 .keywords: TS, trajectory, timestep, reset
568 
569 .seealso: TSTrajectoryCreate(), TSTrajectorySetUp()
570 @*/
571 PetscErrorCode TSTrajectoryReset(TSTrajectory tj)
572 {
573   PetscErrorCode ierr;
574 
575   PetscFunctionBegin;
576   if (!tj) PetscFunctionReturn(0);
577   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
578   if (tj->ops->reset) {
579     ierr = (*tj->ops->reset)(tj);CHKERRQ(ierr);
580   }
581   ierr = PetscFree(tj->dirfiletemplate);CHKERRQ(ierr);
582   ierr = TSHistoryDestroy(&tj->tsh);CHKERRQ(ierr);
583   ierr = TSHistoryCreate(PetscObjectComm((PetscObject)tj),&tj->tsh);CHKERRQ(ierr);
584   tj->setupcalled = PETSC_FALSE;
585   PetscFunctionReturn(0);
586 }
587 
588 /*@
589    TSTrajectoryDestroy - Destroys a trajectory context
590 
591    Collective on TSTrajectory
592 
593    Input Parameter:
594 .  tj - the TSTrajectory context obtained from TSTrajectoryCreate()
595 
596    Level: developer
597 
598 .keywords: TS, trajectory, timestep, destroy
599 
600 .seealso: TSTrajectoryCreate(), TSTrajectorySetUp()
601 @*/
602 PetscErrorCode TSTrajectoryDestroy(TSTrajectory *tj)
603 {
604   PetscErrorCode ierr;
605 
606   PetscFunctionBegin;
607   if (!*tj) PetscFunctionReturn(0);
608   PetscValidHeaderSpecific((*tj),TSTRAJECTORY_CLASSID,1);
609   if (--((PetscObject)(*tj))->refct > 0) {*tj = 0; PetscFunctionReturn(0);}
610 
611   ierr = TSTrajectoryReset(*tj);CHKERRQ(ierr);
612   ierr = TSHistoryDestroy(&(*tj)->tsh);CHKERRQ(ierr);
613   ierr = VecDestroyVecs((*tj)->lag.order+1,&(*tj)->lag.W);CHKERRQ(ierr);
614   ierr = PetscFree5((*tj)->lag.L,(*tj)->lag.T,(*tj)->lag.WW,(*tj)->lag.TT,(*tj)->lag.TW);CHKERRQ(ierr);
615   ierr = VecDestroy(&(*tj)->U);CHKERRQ(ierr);
616   ierr = VecDestroy(&(*tj)->Udot);CHKERRQ(ierr);
617 
618   if ((*tj)->transformdestroy) {ierr = (*(*tj)->transformdestroy)((*tj)->transformctx);CHKERRQ(ierr);}
619   if ((*tj)->ops->destroy) {ierr = (*(*tj)->ops->destroy)((*tj));CHKERRQ(ierr);}
620   if (!((*tj)->keepfiles)) {
621     PetscMPIInt rank;
622     MPI_Comm    comm;
623 
624     ierr = PetscObjectGetComm((PetscObject)(*tj),&comm);CHKERRQ(ierr);
625     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
626     if (!rank && (*tj)->dirname) { /* we own the directory, so we run PetscRMTree on it */
627       ierr = PetscRMTree((*tj)->dirname);CHKERRQ(ierr);
628     }
629   }
630   ierr = PetscStrArrayDestroy(&(*tj)->names);CHKERRQ(ierr);
631   ierr = PetscFree((*tj)->dirname);CHKERRQ(ierr);
632   ierr = PetscFree((*tj)->filetemplate);CHKERRQ(ierr);
633   ierr = PetscHeaderDestroy(tj);CHKERRQ(ierr);
634   PetscFunctionReturn(0);
635 }
636 
637 /*
638   TSTrajectorySetTypeFromOptions_Private - Sets the type of ts from user options.
639 
640   Collective on TSTrajectory
641 
642   Input Parameter:
643 + tj - the TSTrajectory context
644 - ts - the TS context
645 
646   Options Database Keys:
647 . -ts_trajectory_type <type> - TSTRAJECTORYBASIC, TSTRAJECTORYMEMORY, TSTRAJECTORYSINGLEFILE, TSTRAJECTORYVISUALIZATION
648 
649   Level: developer
650 
651 .keywords: TS, trajectory, set, options, type
652 
653 .seealso: TSTrajectorySetFromOptions(), TSTrajectorySetType()
654 */
655 static PetscErrorCode TSTrajectorySetTypeFromOptions_Private(PetscOptionItems *PetscOptionsObject,TSTrajectory tj,TS ts)
656 {
657   PetscBool      opt;
658   const char     *defaultType;
659   char           typeName[256];
660   PetscErrorCode ierr;
661 
662   PetscFunctionBegin;
663   if (((PetscObject)tj)->type_name) defaultType = ((PetscObject)tj)->type_name;
664   else defaultType = TSTRAJECTORYBASIC;
665 
666   ierr = TSTrajectoryRegisterAll();CHKERRQ(ierr);
667   ierr = PetscOptionsFList("-ts_trajectory_type","TSTrajectory method","TSTrajectorySetType",TSTrajectoryList,defaultType,typeName,256,&opt);CHKERRQ(ierr);
668   if (opt) {
669     ierr = TSTrajectorySetType(tj,ts,typeName);CHKERRQ(ierr);
670   } else {
671     ierr = TSTrajectorySetType(tj,ts,defaultType);CHKERRQ(ierr);
672   }
673   PetscFunctionReturn(0);
674 }
675 
676 /*@
677    TSTrajectorySetUseHistory - Use TSHistory in TSTrajectory
678 
679    Collective on TSTrajectory
680 
681    Input Arguments:
682 +  tj - the TSTrajectory context
683 -  flg - PETSC_TRUE to save, PETSC_FALSE to disable
684 
685    Options Database Keys:
686 .  -ts_trajectory_use_history - have it use TSHistory
687 
688    Level: advanced
689 
690 .keywords: TS, trajectory, set, TSHistory
691 
692 .seealso: TSTrajectoryCreate(), TSTrajectoryDestroy(), TSTrajectorySetUp()
693 @*/
694 PetscErrorCode TSTrajectorySetUseHistory(TSTrajectory tj,PetscBool flg)
695 {
696   PetscFunctionBegin;
697   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
698   PetscValidLogicalCollectiveBool(tj,flg,2);
699   tj->usehistory = flg;
700   PetscFunctionReturn(0);
701 }
702 
703 /*@
704    TSTrajectorySetMonitor - Monitor the schedules generated by the checkpointing controller
705 
706    Collective on TSTrajectory
707 
708    Input Arguments:
709 +  tj - the TSTrajectory context
710 -  flg - PETSC_TRUE to active a monitor, PETSC_FALSE to disable
711 
712    Options Database Keys:
713 .  -ts_trajectory_monitor - print TSTrajectory information
714 
715    Level: developer
716 
717 .keywords: TS, trajectory, set, monitor
718 
719 .seealso: TSTrajectoryCreate(), TSTrajectoryDestroy(), TSTrajectorySetUp()
720 @*/
721 PetscErrorCode TSTrajectorySetMonitor(TSTrajectory tj,PetscBool flg)
722 {
723   PetscFunctionBegin;
724   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
725   PetscValidLogicalCollectiveBool(tj,flg,2);
726   if (flg) tj->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)tj));
727   else tj->monitor = NULL;
728   PetscFunctionReturn(0);
729 }
730 
731 /*@
732    TSTrajectorySetKeepFiles - Keep the files generated by the TSTrajectory
733 
734    Collective on TSTrajectory
735 
736    Input Arguments:
737 +  tj - the TSTrajectory context
738 -  flg - PETSC_TRUE to save, PETSC_FALSE to disable
739 
740    Options Database Keys:
741 .  -ts_trajectory_keep_files - have it keep the files
742 
743    Notes:
744     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.
745 
746    Level: advanced
747 
748 .keywords: TS, trajectory, set, monitor
749 
750 .seealso: TSTrajectoryCreate(), TSTrajectoryDestroy(), TSTrajectorySetUp(), TSTrajectorySetMonitor()
751 @*/
752 PetscErrorCode TSTrajectorySetKeepFiles(TSTrajectory tj,PetscBool flg)
753 {
754   PetscFunctionBegin;
755   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
756   PetscValidLogicalCollectiveBool(tj,flg,2);
757   tj->keepfiles = flg;
758   PetscFunctionReturn(0);
759 }
760 
761 /*@C
762    TSTrajectorySetDirname - Specify the name of the directory where disk checkpoints are stored.
763 
764    Collective on TSTrajectory
765 
766    Input Arguments:
767 +  tj      - the TSTrajectory context
768 -  dirname - the directory name
769 
770    Options Database Keys:
771 .  -ts_trajectory_dirname - set the directory name
772 
773    Notes:
774     The final location of the files is determined by dirname/filetemplate where filetemplate was provided by TSTrajectorySetFiletemplate()
775 
776    Level: developer
777 
778 .keywords: TS, trajectory, set
779 
780 .seealso: TSTrajectorySetFiletemplate(),TSTrajectorySetUp()
781 @*/
782 PetscErrorCode TSTrajectorySetDirname(TSTrajectory tj,const char dirname[])
783 {
784   PetscErrorCode ierr;
785   PetscBool      flg;
786 
787   PetscFunctionBegin;
788   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
789   ierr = PetscStrcmp(tj->dirname,dirname,&flg);CHKERRQ(ierr);
790   if (!flg && tj->dirfiletemplate) {
791     SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_ARG_WRONGSTATE,"Cannot set directoryname after TSTrajectory has been setup");
792   }
793   ierr = PetscFree(tj->dirname);CHKERRQ(ierr);
794   ierr = PetscStrallocpy(dirname,&tj->dirname);CHKERRQ(ierr);
795   PetscFunctionReturn(0);
796 }
797 
798 /*@C
799    TSTrajectorySetFiletemplate - Specify the name template for the files storing checkpoints.
800 
801    Collective on TSTrajectory
802 
803    Input Arguments:
804 +  tj      - the TSTrajectory context
805 -  filetemplate - the template
806 
807    Options Database Keys:
808 .  -ts_trajectory_file_template - set the file name template
809 
810    Notes:
811     The name template should be of the form, for example filename-%06D.bin It should not begin with a leading /
812 
813    The final location of the files is determined by dirname/filetemplate where dirname was provided by TSTrajectorySetDirname(). The %06D is replaced by the
814    timestep counter
815 
816    Level: developer
817 
818 .keywords: TS, trajectory, set
819 
820 .seealso: TSTrajectorySetDirname(),TSTrajectorySetUp()
821 @*/
822 PetscErrorCode TSTrajectorySetFiletemplate(TSTrajectory tj,const char filetemplate[])
823 {
824   PetscErrorCode ierr;
825   const char     *ptr,*ptr2;
826 
827   PetscFunctionBegin;
828   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
829   if (tj->dirfiletemplate) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_ARG_WRONGSTATE,"Cannot set filetemplate after TSTrajectory has been setup");
830 
831   if (!filetemplate[0]) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_USER,"-ts_trajectory_file_template requires a file name template, e.g. filename-%%06D.bin");
832   /* Do some cursory validation of the input. */
833   ierr = PetscStrstr(filetemplate,"%",(char**)&ptr);CHKERRQ(ierr);
834   if (!ptr) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_USER,"-ts_trajectory_file_template requires a file name template, e.g. filename-%%06D.bin");
835   for (ptr++; ptr && *ptr; ptr++) {
836     ierr = PetscStrchr("DdiouxX",*ptr,(char**)&ptr2);CHKERRQ(ierr);
837     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");
838     if (ptr2) break;
839   }
840   ierr = PetscFree(tj->filetemplate);CHKERRQ(ierr);
841   ierr = PetscStrallocpy(filetemplate,&tj->filetemplate);CHKERRQ(ierr);
842   PetscFunctionReturn(0);
843 }
844 
845 /*@
846    TSTrajectorySetFromOptions - Sets various TSTrajectory parameters from user options.
847 
848    Collective on TSTrajectory
849 
850    Input Parameter:
851 +  tj - the TSTrajectory context obtained from TSTrajectoryCreate()
852 -  ts - the TS context
853 
854    Options Database Keys:
855 +  -ts_trajectory_type <type> - TSTRAJECTORYBASIC, TSTRAJECTORYMEMORY, TSTRAJECTORYSINGLEFILE, TSTRAJECTORYVISUALIZATION
856 .  -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
857 -  -ts_trajectory_monitor - print TSTrajectory information
858 
859    Level: developer
860 
861    Notes:
862     This is not normally called directly by users
863 
864 .keywords: TS, trajectory, timestep, set, options, database
865 
866 .seealso: TSSetSaveTrajectory(), TSTrajectorySetUp()
867 @*/
868 PetscErrorCode  TSTrajectorySetFromOptions(TSTrajectory tj,TS ts)
869 {
870   PetscBool      set,flg;
871   char           dirname[PETSC_MAX_PATH_LEN],filetemplate[PETSC_MAX_PATH_LEN];
872   PetscErrorCode ierr;
873 
874   PetscFunctionBegin;
875   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
876   if (ts) PetscValidHeaderSpecific(ts,TS_CLASSID,2);
877   ierr = PetscObjectOptionsBegin((PetscObject)tj);CHKERRQ(ierr);
878   ierr = TSTrajectorySetTypeFromOptions_Private(PetscOptionsObject,tj,ts);CHKERRQ(ierr);
879   ierr = PetscOptionsBool("-ts_trajectory_use_history","Turn on/off usage of TSHistory",NULL,tj->usehistory,&tj->usehistory,NULL);CHKERRQ(ierr);
880   ierr = PetscOptionsBool("-ts_trajectory_monitor","Print checkpointing schedules","TSTrajectorySetMonitor",tj->monitor ? PETSC_TRUE:PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
881   if (set) {ierr = TSTrajectorySetMonitor(tj,flg);CHKERRQ(ierr);}
882   ierr = PetscOptionsInt("-ts_trajectory_reconstruction_order","Interpolation order for reconstruction",NULL,tj->lag.order,&tj->lag.order,NULL);CHKERRQ(ierr);
883   ierr = PetscOptionsBool("-ts_trajectory_reconstruction_caching","Turn on/off caching of TSTrajectoryGetVecs input",NULL,tj->lag.caching,&tj->lag.caching,NULL);CHKERRQ(ierr);
884   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);
885   ierr = PetscOptionsBool("-ts_trajectory_solution_only","Checkpoint solution only","TSTrajectorySetSolutionOnly",tj->solution_only,&tj->solution_only,NULL);CHKERRQ(ierr);
886   ierr = PetscOptionsBool("-ts_trajectory_keep_files","Keep any trajectory files generated during the run","TSTrajectorySetKeepFiles",tj->keepfiles,&flg,&set);CHKERRQ(ierr);
887   if (set) {ierr = TSTrajectorySetKeepFiles(tj,flg);CHKERRQ(ierr);}
888 
889   ierr = PetscOptionsString("-ts_trajectory_dirname","Directory name for TSTrajectory file","TSTrajectorySetDirname",0,dirname,PETSC_MAX_PATH_LEN-14,&set);CHKERRQ(ierr);
890   if (set) {
891     ierr = TSTrajectorySetDirname(tj,dirname);CHKERRQ(ierr);
892   }
893 
894   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);
895   if (set) {
896     ierr = TSTrajectorySetFiletemplate(tj,filetemplate);CHKERRQ(ierr);
897   }
898 
899   /* Handle specific TSTrajectory options */
900   if (tj->ops->setfromoptions) {
901     ierr = (*tj->ops->setfromoptions)(PetscOptionsObject,tj);CHKERRQ(ierr);
902   }
903   ierr = PetscOptionsEnd();CHKERRQ(ierr);
904   PetscFunctionReturn(0);
905 }
906 
907 /*@
908    TSTrajectorySetUp - Sets up the internal data structures, e.g. stacks, for the later use
909    of a TS trajectory.
910 
911    Collective on TS
912 
913    Input Parameter:
914 +  ts - the TS context obtained from TSCreate()
915 -  tj - the TS trajectory context
916 
917    Level: developer
918 
919 .keywords: TS, trajectory, setup
920 
921 .seealso: TSSetSaveTrajectory(), TSTrajectoryCreate(), TSTrajectoryDestroy()
922 @*/
923 PetscErrorCode  TSTrajectorySetUp(TSTrajectory tj,TS ts)
924 {
925   PetscErrorCode ierr;
926   size_t         s1,s2;
927 
928   PetscFunctionBegin;
929   if (!tj) PetscFunctionReturn(0);
930   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
931   if (ts) PetscValidHeaderSpecific(ts,TS_CLASSID,2);
932   if (tj->setupcalled) PetscFunctionReturn(0);
933 
934   if (!((PetscObject)tj)->type_name) {
935     ierr = TSTrajectorySetType(tj,ts,TSTRAJECTORYBASIC);CHKERRQ(ierr);
936   }
937   if (tj->ops->setup) {
938     ierr = (*tj->ops->setup)(tj,ts);CHKERRQ(ierr);
939   }
940 
941   tj->setupcalled = PETSC_TRUE;
942 
943   /* Set the counters to zero */
944   tj->recomps    = 0;
945   tj->diskreads  = 0;
946   tj->diskwrites = 0;
947   ierr = PetscStrlen(tj->dirname,&s1);CHKERRQ(ierr);
948   ierr = PetscStrlen(tj->filetemplate,&s2);CHKERRQ(ierr);
949   ierr = PetscFree(tj->dirfiletemplate);CHKERRQ(ierr);
950   ierr = PetscMalloc((s1 + s2 + 10)*sizeof(char),&tj->dirfiletemplate);CHKERRQ(ierr);
951   ierr = PetscSNPrintf(tj->dirfiletemplate,s1+s2+10,"%s/%s",tj->dirname,tj->filetemplate);CHKERRQ(ierr);
952   PetscFunctionReturn(0);
953 }
954 
955 /*@
956    TSTrajectorySetSolutionOnly - Tells the trajectory to store just the solution, and not any intermediate stage also.
957 
958    Collective on TSTrajectory
959 
960    Input Parameter:
961 +  tj  - the TS trajectory context
962 -  flg - the boolean flag
963 
964    Level: developer
965 
966 .keywords: trajectory
967 
968 .seealso: TSSetSaveTrajectory(), TSTrajectoryCreate(), TSTrajectoryDestroy(), TSTrajectoryGetSolutionOnly()
969 @*/
970 PetscErrorCode TSTrajectorySetSolutionOnly(TSTrajectory tj,PetscBool solution_only)
971 {
972   PetscFunctionBegin;
973   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
974   PetscValidLogicalCollectiveBool(tj,solution_only,2);
975   tj->solution_only = solution_only;
976   PetscFunctionReturn(0);
977 }
978 
979 /*@
980    TSTrajectoryGetSolutionOnly - Gets the value set with TSTrajectorySetSolutionOnly.
981 
982    Logically collective on TSTrajectory
983 
984    Input Parameter:
985 .  tj  - the TS trajectory context
986 
987    Output Parameter:
988 -  flg - the boolean flag
989 
990    Level: developer
991 
992 .keywords: trajectory
993 
994 .seealso: TSSetSaveTrajectory(), TSTrajectoryCreate(), TSTrajectoryDestroy(), TSTrajectorySetSolutionOnly()
995 @*/
996 PetscErrorCode TSTrajectoryGetSolutionOnly(TSTrajectory tj,PetscBool *solution_only)
997 {
998   PetscFunctionBegin;
999   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
1000   PetscValidPointer(solution_only,2);
1001   *solution_only = tj->solution_only;
1002   PetscFunctionReturn(0);
1003 }
1004 
1005 /*@
1006    TSTrajectoryGetUpdatedHistoryVecs - Get updated state and time-derivative history vectors.
1007 
1008    Collective on TSTrajectory
1009 
1010    Input Parameter:
1011 +  tj   - the TS trajectory context
1012 .  ts   - the TS solver context
1013 -  time - the requested time
1014 
1015    Output Parameter:
1016 +  U    - state vector at given time (can be interpolated)
1017 -  Udot - time-derivative vector at given time (can be interpolated)
1018 
1019    Level: developer
1020 
1021    Notes: The vectors are interpolated if time does not match any time step stored in the TSTrajectory(). Pass NULL to not request a vector.
1022           This function differs from TSTrajectoryGetVecs since the vectors obtained cannot be modified, and they need to be returned by
1023           calling TSTrajectoryRestoreUpdatedHistoryVecs().
1024 
1025 .keywords: trajectory
1026 
1027 .seealso: TSSetSaveTrajectory(), TSTrajectoryCreate(), TSTrajectoryDestroy(), TSTrajectoryRestoreUpdatedHistoryVecs(), TSTrajectoryGetVecs()
1028 @*/
1029 PetscErrorCode TSTrajectoryGetUpdatedHistoryVecs(TSTrajectory tj, TS ts, PetscReal time, Vec *U, Vec *Udot)
1030 {
1031   PetscErrorCode ierr;
1032 
1033   PetscFunctionBegin;
1034   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
1035   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
1036   PetscValidLogicalCollectiveReal(tj,time,3);
1037   if (U) PetscValidPointer(U,4);
1038   if (Udot) PetscValidPointer(Udot,5);
1039   if (U && !tj->U) {
1040     DM dm;
1041 
1042     ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1043     ierr = DMCreateGlobalVector(dm,&tj->U);CHKERRQ(ierr);
1044   }
1045   if (Udot && !tj->Udot) {
1046     DM dm;
1047 
1048     ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1049     ierr = DMCreateGlobalVector(dm,&tj->Udot);CHKERRQ(ierr);
1050   }
1051   ierr = TSTrajectoryGetVecs(tj,ts,PETSC_DECIDE,&time,U ? tj->U : NULL,Udot ? tj->Udot : NULL);CHKERRQ(ierr);
1052   if (U) {
1053     ierr = VecLockReadPush(tj->U);CHKERRQ(ierr);
1054     *U   = tj->U;
1055   }
1056   if (Udot) {
1057     ierr  = VecLockReadPush(tj->Udot);CHKERRQ(ierr);
1058     *Udot = tj->Udot;
1059   }
1060   PetscFunctionReturn(0);
1061 }
1062 
1063 /*@
1064    TSTrajectoryRestoreUpdatedHistoryVecs - Restores updated state and time-derivative history vectors obtained with TSTrajectoryGetUpdatedHistoryVecs().
1065 
1066    Collective on TSTrajectory
1067 
1068    Input Parameter:
1069 +  tj   - the TS trajectory context
1070 .  U    - state vector at given time (can be interpolated)
1071 -  Udot - time-derivative vector at given time (can be interpolated)
1072 
1073    Level: developer
1074 
1075 .keywords: trajectory
1076 
1077 .seealso: TSTrajectoryGetUpdatedHistoryVecs()
1078 @*/
1079 PetscErrorCode TSTrajectoryRestoreUpdatedHistoryVecs(TSTrajectory tj, Vec *U, Vec *Udot)
1080 {
1081   PetscErrorCode ierr;
1082 
1083   PetscFunctionBegin;
1084   PetscValidHeaderSpecific(tj,TSTRAJECTORY_CLASSID,1);
1085   if (U) PetscValidHeaderSpecific(*U,VEC_CLASSID,2);
1086   if (Udot) PetscValidHeaderSpecific(*Udot,VEC_CLASSID,3);
1087   if (U && *U != tj->U) SETERRQ(PetscObjectComm((PetscObject)*U),PETSC_ERR_USER,"U was not obtained from TSTrajectoryGetUpdatedHistoryVecs()");
1088   if (Udot && *Udot != tj->Udot) SETERRQ(PetscObjectComm((PetscObject)*Udot),PETSC_ERR_USER,"Udot was not obtained from TSTrajectoryGetUpdatedHistoryVecs()");
1089   if (U) {
1090     ierr = VecLockReadPop(tj->U);CHKERRQ(ierr);
1091     *U   = NULL;
1092   }
1093   if (Udot) {
1094     ierr  = VecLockReadPop(tj->Udot);CHKERRQ(ierr);
1095     *Udot = NULL;
1096   }
1097   PetscFunctionReturn(0);
1098 }
1099