Actual source code: traj.c
1: #include <petsc/private/tsimpl.h>
2: #include <petsc/private/tshistoryimpl.h>
3: #include <petscdm.h>
5: PetscFunctionList TSTrajectoryList = NULL;
6: PetscBool TSTrajectoryRegisterAllCalled = PETSC_FALSE;
7: PetscClassId TSTRAJECTORY_CLASSID;
8: PetscLogEvent TSTrajectory_Set, TSTrajectory_Get, TSTrajectory_GetVecs, TSTrajectory_SetUp;
10: /*@C
11: TSTrajectoryRegister - Adds a way of storing trajectories to the `TS` package
13: Not Collective
15: Input Parameters:
16: + name - the name of a new user-defined creation routine
17: - create_func - the creation routine itself
19: Level: developer
21: Note:
22: `TSTrajectoryRegister()` may be called multiple times to add several user-defined tses.
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: }
33: /*@
34: TSTrajectorySet - Sets a vector of state in the trajectory object
36: Collective
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
45: Level: developer
47: Note:
48: Usually one does not call this routine, it is called automatically during `TSSolve()`
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);
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: }
71: /*@
72: TSTrajectoryGetNumSteps - Return the number of steps registered in the `TSTrajectory` via `TSTrajectorySet()`.
74: Not collective.
76: Input Parameters:
77: . tj - the trajectory object
79: Output Parameter:
80: . steps - the number of steps
82: Level: developer
84: .seealso: [](chapter_ts), `TS`, `TSTrajectorySet()`
85: @*/
86: PetscErrorCode TSTrajectoryGetNumSteps(TSTrajectory tj, PetscInt *steps)
87: {
88: PetscFunctionBegin;
91: PetscCall(TSHistoryGetNumSteps(tj->tsh, steps));
92: PetscFunctionReturn(PETSC_SUCCESS);
93: }
95: /*@
96: TSTrajectoryGet - Updates the solution vector of a time stepper object by querying the `TSTrajectory`
98: Collective
100: Input Parameters:
101: + tj - the trajectory object
102: . ts - the time stepper object
103: - stepnum - the step number
105: Output Parameter:
106: . time - the time associated with the step number
108: Level: developer
110: Note:
111: Usually one does not call this routine, it is called automatically during `TSSolve()`
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");
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: }
135: /*@
136: TSTrajectoryGetVecs - Reconstructs the vector of state and its time derivative using information from the `TSTrajectory` and, possibly, from the `TS`
138: Collective
140: Input Parameters:
141: + tj - the trajectory object
142: . ts - the time stepper object (optional)
143: - stepnum - the requested step number
145: Input/Output Parameter:
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)
152: Level: developer
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.
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");
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;
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;
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: }
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;
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: }
257: /*@C
258: TSTrajectoryViewFromOptions - View a `TSTrajectory` based on values in the options database
260: Collective
262: Input Parameters:
263: + A - the `TSTrajectory` context
264: . obj - Optional object that provides prefix used for option name
265: - name - command line option
267: Level: intermediate
269: .seealso: [](chapter_ts), `TSTrajectory`, `TSTrajectoryView`, `PetscObjectViewFromOptions()`, `TSTrajectoryCreate()`
270: @*/
271: PetscErrorCode TSTrajectoryViewFromOptions(TSTrajectory A, PetscObject obj, const char name[])
272: {
273: PetscFunctionBegin;
275: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
276: PetscFunctionReturn(PETSC_SUCCESS);
277: }
279: /*@C
280: TSTrajectoryView - Prints information about the trajectory object
282: Collective
284: Input Parameters:
285: + tj - the `TSTrajectory` context obtained from `TSTrajectoryCreate()`
286: - viewer - visualization context
288: Options Database Key:
289: . -ts_trajectory_view - calls `TSTrajectoryView()` at end of `TSAdjointStep()`
291: Level: developer
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.
301: The user can open an alternative visualization context with
302: `PetscViewerASCIIOpen()` - output to a specified file.
304: .seealso: [](chapter_ts), `TS`, `TSTrajectory`, `PetscViewer`, `PetscViewerASCIIOpen()`
305: @*/
306: PetscErrorCode TSTrajectoryView(TSTrajectory tj, PetscViewer viewer)
307: {
308: PetscBool iascii;
310: PetscFunctionBegin;
312: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)tj), &viewer));
314: PetscCheckSameComm(tj, 1, viewer, 2);
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: }
329: /*@C
330: TSTrajectorySetVariableNames - Sets the name of each component in the solution vector so that it may be saved with the trajectory
332: Collective
334: Input Parameters:
335: + tr - the trajectory context
336: - names - the names of the components, final string must be NULL
338: Level: intermediate
340: Fortran Note:
341: Fortran interface is not possible because of the string array argument
343: .seealso: [](chapter_ts), `TSTrajectory`, `TSGetTrajectory()`
344: @*/
345: PetscErrorCode TSTrajectorySetVariableNames(TSTrajectory ctx, const char *const *names)
346: {
347: PetscFunctionBegin;
350: PetscCall(PetscStrArrayDestroy(&ctx->names));
351: PetscCall(PetscStrArrayallocpy(names, &ctx->names));
352: PetscFunctionReturn(PETSC_SUCCESS);
353: }
355: /*@C
356: TSTrajectorySetTransform - Solution vector will be transformed by provided function before being saved to disk
358: Collective
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
366: Level: intermediate
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;
374: tj->transform = transform;
375: tj->transformdestroy = destroy;
376: tj->transformctx = tctx;
377: PetscFunctionReturn(PETSC_SUCCESS);
378: }
380: /*@
381: TSTrajectoryCreate - This function creates an empty trajectory object used to store the time dependent solution of an ODE/DAE
383: Collective
385: Input Parameter:
386: . comm - the communicator
388: Output Parameter:
389: . tj - the trajectory object
391: Level: developer
393: Notes:
394: Usually one does not call this routine, it is called automatically when one calls `TSSetSaveTrajectory()`.
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;
402: PetscFunctionBegin;
404: *tj = NULL;
405: PetscCall(TSInitializePackage());
407: PetscCall(PetscHeaderCreate(t, TSTRAJECTORY_CLASSID, "TSTrajectory", "Time stepping", "TS", comm, TSTrajectoryDestroy, TSTrajectoryView));
408: t->setupcalled = PETSC_FALSE;
409: PetscCall(TSHistoryCreate(comm, &t->tsh));
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: }
436: /*@C
437: TSTrajectorySetType - Sets the storage method to be used as in a trajectory
439: Collective
441: Input Parameters:
442: + tj - the `TSTrajectory` context
443: . ts - the `TS` context
444: - type - a known method
446: Options Database Key:
447: . -ts_trajectory_type <type> - Sets the method; use -help for a list of available methods (for instance, basic)
449: Level: developer
451: Developer Note:
452: Why does this option require access to the `TS`
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;
461: PetscFunctionBegin;
463: PetscCall(PetscObjectTypeCompare((PetscObject)tj, type, &match));
464: if (match) PetscFunctionReturn(PETSC_SUCCESS);
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));
471: tj->ops->destroy = NULL;
472: }
473: PetscCall(PetscMemzero(tj->ops, sizeof(*tj->ops)));
475: PetscCall(PetscObjectChangeTypeName((PetscObject)tj, type));
476: PetscCall((*r)(tj, ts));
477: PetscFunctionReturn(PETSC_SUCCESS);
478: }
480: /*@C
481: TSTrajectoryGetType - Gets the trajectory type
483: Collective
485: Input Parameters:
486: + tj - the `TSTrajectory` context
487: - ts - the `TS` context
489: Output Parameters:
490: . type - a known method
492: Level: developer
494: .seealso: [](chapter_ts), `TS`, `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectorySetFromOptions()`, `TSTrajectoryDestroy()`, `TSTrajectorySetType()`
495: @*/
496: PetscErrorCode TSTrajectoryGetType(TSTrajectory tj, TS ts, TSTrajectoryType *type)
497: {
498: PetscFunctionBegin;
500: if (type) *type = ((PetscObject)tj)->type_name;
501: PetscFunctionReturn(PETSC_SUCCESS);
502: }
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);
509: /*@C
510: TSTrajectoryRegisterAll - Registers all of the `TSTrajectory` storage schecmes in the `TS` package.
512: Not Collective
514: Level: developer
516: .seealso: [](chapter_ts), `TSTrajectory`, `TSTrajectoryRegister()`
517: @*/
518: PetscErrorCode TSTrajectoryRegisterAll(void)
519: {
520: PetscFunctionBegin;
521: if (TSTrajectoryRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
522: TSTrajectoryRegisterAllCalled = PETSC_TRUE;
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: }
531: /*@
532: TSTrajectoryReset - Resets a trajectory context
534: Collective
536: Input Parameter:
537: . tj - the `TSTrajectory` context obtained from `TSGetTrajectory()`
539: Level: developer
541: .seealso: [](chapter_ts), `TS`, `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectorySetUp()`
542: @*/
543: PetscErrorCode TSTrajectoryReset(TSTrajectory tj)
544: {
545: PetscFunctionBegin;
546: if (!tj) PetscFunctionReturn(PETSC_SUCCESS);
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: }
556: /*@
557: TSTrajectoryDestroy - Destroys a trajectory context
559: Collective
561: Input Parameter:
562: . tj - the `TSTrajectory` context obtained from `TSTrajectoryCreate()`
564: Level: developer
566: .seealso: [](chapter_ts), `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectorySetUp()`
567: @*/
568: PetscErrorCode TSTrajectoryDestroy(TSTrajectory *tj)
569: {
570: PetscFunctionBegin;
571: if (!*tj) PetscFunctionReturn(PETSC_SUCCESS);
573: if (--((PetscObject)(*tj))->refct > 0) {
574: *tj = NULL;
575: PetscFunctionReturn(PETSC_SUCCESS);
576: }
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));
585: if ((*tj)->transformdestroy) PetscCall((*(*tj)->transformdestroy)((*tj)->transformctx));
586: PetscTryTypeMethod((*tj), destroy);
587: if (!((*tj)->keepfiles)) {
588: PetscMPIInt rank;
589: MPI_Comm comm;
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: }
604: /*
605: TSTrajectorySetTypeFromOptions_Private - Sets the type of `TSTrajectory` from user options.
607: Collective
609: Input Parameter:
610: + tj - the `TSTrajectory` context
611: - ts - the TS context
613: Options Database Key:
614: . -ts_trajectory_type <type> - TSTRAJECTORYBASIC, TSTRAJECTORYMEMORY, TSTRAJECTORYSINGLEFILE, TSTRAJECTORYVISUALIZATION
616: Level: developer
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];
626: PetscFunctionBegin;
627: if (((PetscObject)tj)->type_name) defaultType = ((PetscObject)tj)->type_name;
628: else defaultType = TSTRAJECTORYBASIC;
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: }
640: /*@
641: TSTrajectorySetUseHistory - Use `TSHistory` in `TSTrajectory`
643: Collective
645: Input Parameters:
646: + tj - the `TSTrajectory` context
647: - flg - `PETSC_TRUE` to save, `PETSC_FALSE` to disable
649: Options Database Key:
650: . -ts_trajectory_use_history - have it use `TSHistory`
652: Level: advanced
654: .seealso: [](chapter_ts), `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetUp()`
655: @*/
656: PetscErrorCode TSTrajectorySetUseHistory(TSTrajectory tj, PetscBool flg)
657: {
658: PetscFunctionBegin;
661: tj->usehistory = flg;
662: PetscFunctionReturn(PETSC_SUCCESS);
663: }
665: /*@
666: TSTrajectorySetMonitor - Monitor the schedules generated by the `TSTrajectory` checkpointing controller
668: Collective
670: Input Parameters:
671: + tj - the `TSTrajectory` context
672: - flg - `PETSC_TRUE` to active a monitor, `PETSC_FALSE` to disable
674: Options Database Key:
675: . -ts_trajectory_monitor - print `TSTrajectory` information
677: Level: developer
679: .seealso: [](chapter_ts), `TSTrajectory`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetUp()`
680: @*/
681: PetscErrorCode TSTrajectorySetMonitor(TSTrajectory tj, PetscBool flg)
682: {
683: PetscFunctionBegin;
686: if (flg) tj->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)tj));
687: else tj->monitor = NULL;
688: PetscFunctionReturn(PETSC_SUCCESS);
689: }
691: /*@
692: TSTrajectorySetKeepFiles - Keep the files generated by the `TSTrajectory` once the program is done
694: Collective
696: Input Parameters:
697: + tj - the `TSTrajectory` context
698: - flg - `PETSC_TRUE` to save, `PETSC_FALSE` to disable
700: Options Database Key:
701: . -ts_trajectory_keep_files - have it keep the files
703: Level: advanced
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.
708: .seealso: [](chapter_ts), `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetUp()`, `TSTrajectorySetMonitor()`
709: @*/
710: PetscErrorCode TSTrajectorySetKeepFiles(TSTrajectory tj, PetscBool flg)
711: {
712: PetscFunctionBegin;
715: tj->keepfiles = flg;
716: PetscFunctionReturn(PETSC_SUCCESS);
717: }
719: /*@C
720: TSTrajectorySetDirname - Specify the name of the directory where `TSTrajectory` disk checkpoints are stored.
722: Collective
724: Input Parameters:
725: + tj - the `TSTrajectory` context
726: - dirname - the directory name
728: Options Database Key:
729: . -ts_trajectory_dirname - set the directory name
731: Level: developer
733: Notes:
734: The final location of the files is determined by dirname/filetemplate where filetemplate was provided by `TSTrajectorySetFiletemplate()`
736: If this is not called `TSTrajectory` selects a unique new name for the directory
738: .seealso: [](chapter_ts), `TSTrajectory`, `TSTrajectorySetFiletemplate()`, `TSTrajectorySetUp()`
739: @*/
740: PetscErrorCode TSTrajectorySetDirname(TSTrajectory tj, const char dirname[])
741: {
742: PetscBool flg;
744: PetscFunctionBegin;
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: }
753: /*@C
754: TSTrajectorySetFiletemplate - Specify the name template for the files storing `TSTrajectory` checkpoints.
756: Collective
758: Input Parameters:
759: + tj - the `TSTrajectory` context
760: - filetemplate - the template
762: Options Database Key:
763: . -ts_trajectory_file_template - set the file name template
765: Level: developer
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 /
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
773: .seealso: [](chapter_ts), `TSTrajectory`, `TSTrajectorySetDirname()`, `TSTrajectorySetUp()`
774: @*/
775: PetscErrorCode TSTrajectorySetFiletemplate(TSTrajectory tj, const char filetemplate[])
776: {
777: const char *ptr = NULL, *ptr2 = NULL;
779: PetscFunctionBegin;
782: PetscCheck(!tj->dirfiletemplate, PetscObjectComm((PetscObject)tj), PETSC_ERR_ARG_WRONGSTATE, "Cannot set filetemplate after TSTrajectory has been setup");
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: }
798: /*@
799: TSTrajectorySetFromOptions - Sets various `TSTrajectory` parameters from user options.
801: Collective
803: Input Parameters:
804: + tj - the `TSTrajectory` context obtained from `TSGetTrajectory()`
805: - ts - the `TS` context
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
812: Level: developer
814: Note:
815: This is not normally called directly by users
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];
824: PetscFunctionBegin;
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));
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));
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));
845: /* Handle specific TSTrajectory options */
846: PetscTryTypeMethod(tj, setfromoptions, PetscOptionsObject);
847: PetscOptionsEnd();
848: PetscFunctionReturn(PETSC_SUCCESS);
849: }
851: /*@
852: TSTrajectorySetUp - Sets up the internal data structures, e.g. stacks, for the later use
853: of a `TS` `TSTrajectory`.
855: Collective
857: Input Parameters:
858: + tj - the `TSTrajectory` context
859: - ts - the TS context obtained from `TSCreate()`
861: Level: developer
863: .seealso: [](chapter_ts), `TSTrajectory`, `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`
864: @*/
865: PetscErrorCode TSTrajectorySetUp(TSTrajectory tj, TS ts)
866: {
867: size_t s1, s2;
869: PetscFunctionBegin;
870: if (!tj) PetscFunctionReturn(PETSC_SUCCESS);
873: if (tj->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
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);
879: tj->setupcalled = PETSC_TRUE;
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: }
894: /*@
895: TSTrajectorySetSolutionOnly - Tells the trajectory to store just the solution, and not any intermediate stage information
897: Collective
899: Input Parameters:
900: + tj - the `TSTrajectory` context obtained with `TSGetTrajectory()`
901: - flg - the boolean flag
903: Level: developer
905: .seealso: [](chapter_ts), `TSTrajectory`, `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectoryGetSolutionOnly()`
906: @*/
907: PetscErrorCode TSTrajectorySetSolutionOnly(TSTrajectory tj, PetscBool solution_only)
908: {
909: PetscFunctionBegin;
912: tj->solution_only = solution_only;
913: PetscFunctionReturn(PETSC_SUCCESS);
914: }
916: /*@
917: TSTrajectoryGetSolutionOnly - Gets the value set with `TSTrajectorySetSolutionOnly()`.
919: Logically collective
921: Input Parameter:
922: . tj - the `TSTrajectory` context
924: Output Parameter:
925: . flg - the boolean flag
927: Level: developer
929: .seealso: [](chapter_ts), `TSTrajectory`, `TSSetSaveTrajectory()`, `TSTrajectoryCreate()`, `TSTrajectoryDestroy()`, `TSTrajectorySetSolutionOnly()`
930: @*/
931: PetscErrorCode TSTrajectoryGetSolutionOnly(TSTrajectory tj, PetscBool *solution_only)
932: {
933: PetscFunctionBegin;
936: *solution_only = tj->solution_only;
937: PetscFunctionReturn(PETSC_SUCCESS);
938: }
940: /*@
941: TSTrajectoryGetUpdatedHistoryVecs - Get updated state and time-derivative history vectors.
943: Collective
945: Input Parameters:
946: + tj - the `TSTrajectory` context
947: . ts - the `TS` solver context
948: - time - the requested time
950: Output Parameters:
951: + U - state vector at given time (can be interpolated)
952: - Udot - time-derivative vector at given time (can be interpolated)
954: Level: developer
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.
959: This function differs from `TSTrajectoryGetVecs()` since the vectors obtained cannot be modified, and they need to be returned by
960: calling `TSTrajectoryRestoreUpdatedHistoryVecs()`.
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;
972: if (U && !tj->U) {
973: DM dm;
975: PetscCall(TSGetDM(ts, &dm));
976: PetscCall(DMCreateGlobalVector(dm, &tj->U));
977: }
978: if (Udot && !tj->Udot) {
979: DM dm;
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: }
996: /*@
997: TSTrajectoryRestoreUpdatedHistoryVecs - Restores updated state and time-derivative history vectors obtained with `TSTrajectoryGetUpdatedHistoryVecs()`.
999: Collective
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)
1006: Level: developer
1008: .seealso: [](chapter_ts), `TSTrajectory`, `TSTrajectoryGetUpdatedHistoryVecs()`
1009: @*/
1010: PetscErrorCode TSTrajectoryRestoreUpdatedHistoryVecs(TSTrajectory tj, Vec *U, Vec *Udot)
1011: {
1012: PetscFunctionBegin;
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: }