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