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: }