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