1 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 2 #include <petscdmda.h> 3 #include <petscdmshell.h> 4 #include <petscdmplex.h> // For TSSetFromOptions() 5 #include <petscdmswarm.h> // For TSSetFromOptions() 6 #include <petscviewer.h> 7 #include <petscdraw.h> 8 #include <petscconvest.h> 9 10 /* Logging support */ 11 PetscClassId TS_CLASSID, DMTS_CLASSID; 12 PetscLogEvent TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval; 13 14 const char *const TSExactFinalTimeOptions[] = {"UNSPECIFIED", "STEPOVER", "INTERPOLATE", "MATCHSTEP", "TSExactFinalTimeOption", "TS_EXACTFINALTIME_", NULL}; 15 16 static PetscErrorCode TSAdaptSetDefaultType(TSAdapt adapt, TSAdaptType default_type) 17 { 18 PetscFunctionBegin; 19 PetscValidHeaderSpecific(adapt, TSADAPT_CLASSID, 1); 20 PetscAssertPointer(default_type, 2); 21 if (!((PetscObject)adapt)->type_name) PetscCall(TSAdaptSetType(adapt, default_type)); 22 PetscFunctionReturn(PETSC_SUCCESS); 23 } 24 25 /*@ 26 TSSetFromOptions - Sets various `TS` parameters from the options database 27 28 Collective 29 30 Input Parameter: 31 . ts - the `TS` context obtained from `TSCreate()` 32 33 Options Database Keys: 34 + -ts_type <type> - EULER, BEULER, SUNDIALS, PSEUDO, CN, RK, THETA, ALPHA, GLLE, SSP, GLEE, BSYMP, IRK, see `TSType` 35 . -ts_save_trajectory - checkpoint the solution at each time-step 36 . -ts_max_time <time> - maximum time to compute to 37 . -ts_time_span <t0,...tf> - sets the time span, solutions are computed and stored for each indicated time 38 . -ts_max_steps <steps> - maximum number of time-steps to take 39 . -ts_init_time <time> - initial time to start computation 40 . -ts_final_time <time> - final time to compute to (deprecated: use `-ts_max_time`) 41 . -ts_dt <dt> - initial time step 42 . -ts_exact_final_time <stepover,interpolate,matchstep> - whether to stop at the exact given final time and how to compute the solution at that time 43 . -ts_max_snes_failures <maxfailures> - Maximum number of nonlinear solve failures allowed 44 . -ts_max_reject <maxrejects> - Maximum number of step rejections before step fails 45 . -ts_error_if_step_fails <true,false> - Error if no step succeeds 46 . -ts_rtol <rtol> - relative tolerance for local truncation error 47 . -ts_atol <atol> - Absolute tolerance for local truncation error 48 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - test the Jacobian at each iteration against finite difference with RHS function 49 . -ts_rhs_jacobian_test_mult_transpose - test the Jacobian at each iteration against finite difference with RHS function 50 . -ts_adjoint_solve <yes,no> - After solving the ODE/DAE solve the adjoint problem (requires `-ts_save_trajectory`) 51 . -ts_fd_color - Use finite differences with coloring to compute IJacobian 52 . -ts_monitor - print information at each timestep 53 . -ts_monitor_cancel - Cancel all monitors 54 . -ts_monitor_lg_solution - Monitor solution graphically 55 . -ts_monitor_lg_error - Monitor error graphically 56 . -ts_monitor_error - Monitors norm of error 57 . -ts_monitor_lg_timestep - Monitor timestep size graphically 58 . -ts_monitor_lg_timestep_log - Monitor log timestep size graphically 59 . -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically 60 . -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically 61 . -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically 62 . -ts_monitor_draw_solution - Monitor solution graphically 63 . -ts_monitor_draw_solution_phase <xleft,yleft,xright,yright> - Monitor solution graphically with phase diagram, requires problem with exactly 2 degrees of freedom 64 . -ts_monitor_draw_error - Monitor error graphically, requires use to have provided TSSetSolutionFunction() 65 . -ts_monitor_solution [ascii binary draw][:filename][:viewerformat] - monitors the solution at each timestep 66 . -ts_monitor_solution_interval <interval> - output once every interval (default=1) time steps 67 . -ts_monitor_solution_vtk <filename.vts,filename.vtu> - Save each time step to a binary file, use filename-%%03" PetscInt_FMT ".vts (filename-%%03" PetscInt_FMT ".vtu) 68 - -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time 69 70 Level: beginner 71 72 Notes: 73 See `SNESSetFromOptions()` and `KSPSetFromOptions()` for how to control the nonlinear and linear solves used by the time-stepper. 74 75 Certain `SNES` options get reset for each new nonlinear solver, for example `-snes_lag_jacobian its` and `-snes_lag_preconditioner its`, in order 76 to retain them over the multiple nonlinear solves that `TS` uses you mush also provide `-snes_lag_jacobian_persists true` and 77 `-snes_lag_preconditioner_persists true` 78 79 Developer Notes: 80 We should unify all the -ts_monitor options in the way that -xxx_view has been unified 81 82 .seealso: [](ch_ts), `TS`, `TSGetType()` 83 @*/ 84 PetscErrorCode TSSetFromOptions(TS ts) 85 { 86 PetscBool opt, flg, tflg; 87 char monfilename[PETSC_MAX_PATH_LEN]; 88 PetscReal time_step, tspan[100]; 89 PetscInt nt = PETSC_STATIC_ARRAY_LENGTH(tspan); 90 TSExactFinalTimeOption eftopt; 91 char dir[16]; 92 TSIFunctionFn *ifun; 93 const char *defaultType; 94 char typeName[256]; 95 96 PetscFunctionBegin; 97 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 98 99 PetscCall(TSRegisterAll()); 100 PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL)); 101 102 PetscObjectOptionsBegin((PetscObject)ts); 103 if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name; 104 else defaultType = ifun ? TSBEULER : TSEULER; 105 PetscCall(PetscOptionsFList("-ts_type", "TS method", "TSSetType", TSList, defaultType, typeName, 256, &opt)); 106 if (opt) PetscCall(TSSetType(ts, typeName)); 107 else PetscCall(TSSetType(ts, defaultType)); 108 109 /* Handle generic TS options */ 110 PetscCall(PetscOptionsDeprecated("-ts_final_time", "-ts_max_time", "3.10", NULL)); 111 PetscCall(PetscOptionsReal("-ts_max_time", "Maximum time to run to", "TSSetMaxTime", ts->max_time, &ts->max_time, NULL)); 112 PetscCall(PetscOptionsRealArray("-ts_time_span", "Time span", "TSSetTimeSpan", tspan, &nt, &flg)); 113 if (flg) PetscCall(TSSetTimeSpan(ts, nt, tspan)); 114 PetscCall(PetscOptionsInt("-ts_max_steps", "Maximum number of time steps", "TSSetMaxSteps", ts->max_steps, &ts->max_steps, NULL)); 115 PetscCall(PetscOptionsReal("-ts_init_time", "Initial time", "TSSetTime", ts->ptime, &ts->ptime, NULL)); 116 PetscCall(PetscOptionsReal("-ts_dt", "Initial time step", "TSSetTimeStep", ts->time_step, &time_step, &flg)); 117 if (flg) PetscCall(TSSetTimeStep(ts, time_step)); 118 PetscCall(PetscOptionsEnum("-ts_exact_final_time", "Option for handling of final time step", "TSSetExactFinalTime", TSExactFinalTimeOptions, (PetscEnum)ts->exact_final_time, (PetscEnum *)&eftopt, &flg)); 119 if (flg) PetscCall(TSSetExactFinalTime(ts, eftopt)); 120 PetscCall(PetscOptionsInt("-ts_max_snes_failures", "Maximum number of nonlinear solve failures", "TSSetMaxSNESFailures", ts->max_snes_failures, &ts->max_snes_failures, &flg)); 121 if (flg) PetscCall(TSSetMaxSNESFailures(ts, ts->max_snes_failures)); 122 PetscCall(PetscOptionsInt("-ts_max_reject", "Maximum number of step rejections before step fails", "TSSetMaxStepRejections", ts->max_reject, &ts->max_reject, &flg)); 123 if (flg) PetscCall(TSSetMaxStepRejections(ts, ts->max_reject)); 124 PetscCall(PetscOptionsBool("-ts_error_if_step_fails", "Error if no step succeeds", "TSSetErrorIfStepFails", ts->errorifstepfailed, &ts->errorifstepfailed, NULL)); 125 PetscCall(PetscOptionsBoundedReal("-ts_rtol", "Relative tolerance for local truncation error", "TSSetTolerances", ts->rtol, &ts->rtol, NULL, 0)); 126 PetscCall(PetscOptionsBoundedReal("-ts_atol", "Absolute tolerance for local truncation error", "TSSetTolerances", ts->atol, &ts->atol, NULL, 0)); 127 128 PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult", "Test the RHS Jacobian for consistency with RHS at each solve ", "None", ts->testjacobian, &ts->testjacobian, NULL)); 129 PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult_transpose", "Test the RHS Jacobian transpose for consistency with RHS at each solve ", "None", ts->testjacobiantranspose, &ts->testjacobiantranspose, NULL)); 130 PetscCall(PetscOptionsBool("-ts_use_splitrhsfunction", "Use the split RHS function for multirate solvers ", "TSSetUseSplitRHSFunction", ts->use_splitrhsfunction, &ts->use_splitrhsfunction, NULL)); 131 #if defined(PETSC_HAVE_SAWS) 132 { 133 PetscBool set; 134 flg = PETSC_FALSE; 135 PetscCall(PetscOptionsBool("-ts_saws_block", "Block for SAWs memory snooper at end of TSSolve", "PetscObjectSAWsBlock", ((PetscObject)ts)->amspublishblock, &flg, &set)); 136 if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)ts, flg)); 137 } 138 #endif 139 140 /* Monitor options */ 141 PetscCall(PetscOptionsInt("-ts_monitor_frequency", "Number of time steps between monitor output", "TSMonitorSetFrequency", ts->monitorFrequency, &ts->monitorFrequency, NULL)); 142 PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor", "Monitor time and timestep size", "TSMonitorDefault", TSMonitorDefault, NULL)); 143 PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_extreme", "Monitor extreme values of the solution", "TSMonitorExtreme", TSMonitorExtreme, NULL)); 144 PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_solution", "View the solution at each timestep", "TSMonitorSolution", TSMonitorSolution, NULL)); 145 PetscCall(TSMonitorSetFromOptions(ts, "-ts_dmswarm_monitor_moments", "Monitor moments of particle distribution", "TSDMSwarmMonitorMoments", TSDMSwarmMonitorMoments, NULL)); 146 147 PetscCall(PetscOptionsString("-ts_monitor_python", "Use Python function", "TSMonitorSet", NULL, monfilename, sizeof(monfilename), &flg)); 148 if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts, monfilename)); 149 150 PetscCall(PetscOptionsName("-ts_monitor_lg_solution", "Monitor solution graphically", "TSMonitorLGSolution", &opt)); 151 if (opt) { 152 PetscInt howoften = 1; 153 DM dm; 154 PetscBool net; 155 156 PetscCall(PetscOptionsInt("-ts_monitor_lg_solution", "Monitor solution graphically", "TSMonitorLGSolution", howoften, &howoften, NULL)); 157 PetscCall(TSGetDM(ts, &dm)); 158 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMNETWORK, &net)); 159 if (net) { 160 TSMonitorLGCtxNetwork ctx; 161 PetscCall(TSMonitorLGCtxNetworkCreate(ts, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 600, 400, howoften, &ctx)); 162 PetscCall(TSMonitorSet(ts, TSMonitorLGCtxNetworkSolution, ctx, (PetscErrorCode(*)(void **))TSMonitorLGCtxNetworkDestroy)); 163 PetscCall(PetscOptionsBool("-ts_monitor_lg_solution_semilogy", "Plot the solution with a semi-log axis", "", ctx->semilogy, &ctx->semilogy, NULL)); 164 } else { 165 TSMonitorLGCtx ctx; 166 PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx)); 167 PetscCall(TSMonitorSet(ts, TSMonitorLGSolution, ctx, (PetscErrorCode(*)(void **))TSMonitorLGCtxDestroy)); 168 } 169 } 170 171 PetscCall(PetscOptionsName("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", &opt)); 172 if (opt) { 173 TSMonitorLGCtx ctx; 174 PetscInt howoften = 1; 175 176 PetscCall(PetscOptionsInt("-ts_monitor_lg_error", "Monitor error graphically", "TSMonitorLGError", howoften, &howoften, NULL)); 177 PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx)); 178 PetscCall(TSMonitorSet(ts, TSMonitorLGError, ctx, (PetscErrorCode(*)(void **))TSMonitorLGCtxDestroy)); 179 } 180 PetscCall(TSMonitorSetFromOptions(ts, "-ts_monitor_error", "View the error at each timestep", "TSMonitorError", TSMonitorError, NULL)); 181 182 PetscCall(PetscOptionsName("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", &opt)); 183 if (opt) { 184 TSMonitorLGCtx ctx; 185 PetscInt howoften = 1; 186 187 PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep", "Monitor timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL)); 188 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx)); 189 PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscErrorCode(*)(void **))TSMonitorLGCtxDestroy)); 190 } 191 PetscCall(PetscOptionsName("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", &opt)); 192 if (opt) { 193 TSMonitorLGCtx ctx; 194 PetscInt howoften = 1; 195 196 PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep_log", "Monitor log timestep size graphically", "TSMonitorLGTimeStep", howoften, &howoften, NULL)); 197 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx)); 198 PetscCall(TSMonitorSet(ts, TSMonitorLGTimeStep, ctx, (PetscErrorCode(*)(void **))TSMonitorLGCtxDestroy)); 199 ctx->semilogy = PETSC_TRUE; 200 } 201 202 PetscCall(PetscOptionsName("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", &opt)); 203 if (opt) { 204 TSMonitorLGCtx ctx; 205 PetscInt howoften = 1; 206 207 PetscCall(PetscOptionsInt("-ts_monitor_lg_snes_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGSNESIterations", howoften, &howoften, NULL)); 208 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx)); 209 PetscCall(TSMonitorSet(ts, TSMonitorLGSNESIterations, ctx, (PetscErrorCode(*)(void **))TSMonitorLGCtxDestroy)); 210 } 211 PetscCall(PetscOptionsName("-ts_monitor_lg_ksp_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGKSPIterations", &opt)); 212 if (opt) { 213 TSMonitorLGCtx ctx; 214 PetscInt howoften = 1; 215 216 PetscCall(PetscOptionsInt("-ts_monitor_lg_ksp_iterations", "Monitor number nonlinear iterations for each timestep graphically", "TSMonitorLGKSPIterations", howoften, &howoften, NULL)); 217 PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, howoften, &ctx)); 218 PetscCall(TSMonitorSet(ts, TSMonitorLGKSPIterations, ctx, (PetscErrorCode(*)(void **))TSMonitorLGCtxDestroy)); 219 } 220 PetscCall(PetscOptionsName("-ts_monitor_sp_eig", "Monitor eigenvalues of linearized operator graphically", "TSMonitorSPEig", &opt)); 221 if (opt) { 222 TSMonitorSPEigCtx ctx; 223 PetscInt howoften = 1; 224 225 PetscCall(PetscOptionsInt("-ts_monitor_sp_eig", "Monitor eigenvalues of linearized operator graphically", "TSMonitorSPEig", howoften, &howoften, NULL)); 226 PetscCall(TSMonitorSPEigCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx)); 227 PetscCall(TSMonitorSet(ts, TSMonitorSPEig, ctx, (PetscErrorCode(*)(void **))TSMonitorSPEigCtxDestroy)); 228 } 229 PetscCall(PetscOptionsName("-ts_monitor_sp_swarm", "Display particle phase space from the DMSwarm", "TSMonitorSPSwarm", &opt)); 230 if (opt) { 231 TSMonitorSPCtx ctx; 232 PetscInt howoften = 1, retain = 0; 233 PetscBool phase = PETSC_TRUE, create = PETSC_TRUE, multispecies = PETSC_FALSE; 234 235 for (PetscInt i = 0; i < ts->numbermonitors; ++i) 236 if (ts->monitor[i] == TSMonitorSPSwarmSolution) { 237 create = PETSC_FALSE; 238 break; 239 } 240 if (create) { 241 PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm", "Display particles phase space from the DMSwarm", "TSMonitorSPSwarm", howoften, &howoften, NULL)); 242 PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm_retain", "Retain n points plotted to show trajectory, -1 for all points", "TSMonitorSPSwarm", retain, &retain, NULL)); 243 PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_phase", "Plot in phase space rather than coordinate space", "TSMonitorSPSwarm", phase, &phase, NULL)); 244 PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_multi_species", "Color particles by particle species", "TSMonitorSPSwarm", multispecies, &multispecies, NULL)); 245 PetscCall(TSMonitorSPCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, retain, phase, multispecies, &ctx)); 246 PetscCall(TSMonitorSet(ts, TSMonitorSPSwarmSolution, ctx, (PetscErrorCode(*)(void **))TSMonitorSPCtxDestroy)); 247 } 248 } 249 PetscCall(PetscOptionsName("-ts_monitor_hg_swarm", "Display particle histogram from the DMSwarm", "TSMonitorHGSwarm", &opt)); 250 if (opt) { 251 TSMonitorHGCtx ctx; 252 PetscInt howoften = 1, Ns = 1; 253 PetscBool velocity = PETSC_FALSE, create = PETSC_TRUE; 254 255 for (PetscInt i = 0; i < ts->numbermonitors; ++i) 256 if (ts->monitor[i] == TSMonitorHGSwarmSolution) { 257 create = PETSC_FALSE; 258 break; 259 } 260 if (create) { 261 DM sw, dm; 262 PetscInt Nc, Nb; 263 264 PetscCall(TSGetDM(ts, &sw)); 265 PetscCall(DMSwarmGetCellDM(sw, &dm)); 266 PetscCall(DMPlexGetHeightStratum(dm, 0, NULL, &Nc)); 267 Nb = PetscMin(20, PetscMax(10, Nc)); 268 PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm", "Display particles histogram from the DMSwarm", "TSMonitorHGSwarm", howoften, &howoften, NULL)); 269 PetscCall(PetscOptionsBool("-ts_monitor_hg_swarm_velocity", "Plot in velocity space rather than coordinate space", "TSMonitorHGSwarm", velocity, &velocity, NULL)); 270 PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm_species", "Number of species to histogram", "TSMonitorHGSwarm", Ns, &Ns, NULL)); 271 PetscCall(PetscOptionsInt("-ts_monitor_hg_swarm_bins", "Number of histogram bins", "TSMonitorHGSwarm", Nb, &Nb, NULL)); 272 PetscCall(TSMonitorHGCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, Ns, Nb, velocity, &ctx)); 273 PetscCall(TSMonitorSet(ts, TSMonitorHGSwarmSolution, ctx, (PetscErrorCode(*)(void **))TSMonitorHGCtxDestroy)); 274 } 275 } 276 opt = PETSC_FALSE; 277 PetscCall(PetscOptionsName("-ts_monitor_draw_solution", "Monitor solution graphically", "TSMonitorDrawSolution", &opt)); 278 if (opt) { 279 TSMonitorDrawCtx ctx; 280 PetscInt howoften = 1; 281 282 PetscCall(PetscOptionsInt("-ts_monitor_draw_solution", "Monitor solution graphically", "TSMonitorDrawSolution", howoften, &howoften, NULL)); 283 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Computed Solution", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx)); 284 PetscCall(TSMonitorSet(ts, TSMonitorDrawSolution, ctx, (PetscErrorCode(*)(void **))TSMonitorDrawCtxDestroy)); 285 } 286 opt = PETSC_FALSE; 287 PetscCall(PetscOptionsName("-ts_monitor_draw_solution_phase", "Monitor solution graphically", "TSMonitorDrawSolutionPhase", &opt)); 288 if (opt) { 289 TSMonitorDrawCtx ctx; 290 PetscReal bounds[4]; 291 PetscInt n = 4; 292 PetscDraw draw; 293 PetscDrawAxis axis; 294 295 PetscCall(PetscOptionsRealArray("-ts_monitor_draw_solution_phase", "Monitor solution graphically", "TSMonitorDrawSolutionPhase", bounds, &n, NULL)); 296 PetscCheck(n == 4, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Must provide bounding box of phase field"); 297 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, 1, &ctx)); 298 PetscCall(PetscViewerDrawGetDraw(ctx->viewer, 0, &draw)); 299 PetscCall(PetscViewerDrawGetDrawAxis(ctx->viewer, 0, &axis)); 300 PetscCall(PetscDrawAxisSetLimits(axis, bounds[0], bounds[2], bounds[1], bounds[3])); 301 PetscCall(PetscDrawAxisSetLabels(axis, "Phase Diagram", "Variable 1", "Variable 2")); 302 PetscCall(TSMonitorSet(ts, TSMonitorDrawSolutionPhase, ctx, (PetscErrorCode(*)(void **))TSMonitorDrawCtxDestroy)); 303 } 304 opt = PETSC_FALSE; 305 PetscCall(PetscOptionsName("-ts_monitor_draw_error", "Monitor error graphically", "TSMonitorDrawError", &opt)); 306 if (opt) { 307 TSMonitorDrawCtx ctx; 308 PetscInt howoften = 1; 309 310 PetscCall(PetscOptionsInt("-ts_monitor_draw_error", "Monitor error graphically", "TSMonitorDrawError", howoften, &howoften, NULL)); 311 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Error", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx)); 312 PetscCall(TSMonitorSet(ts, TSMonitorDrawError, ctx, (PetscErrorCode(*)(void **))TSMonitorDrawCtxDestroy)); 313 } 314 opt = PETSC_FALSE; 315 PetscCall(PetscOptionsName("-ts_monitor_draw_solution_function", "Monitor solution provided by TSMonitorSetSolutionFunction() graphically", "TSMonitorDrawSolutionFunction", &opt)); 316 if (opt) { 317 TSMonitorDrawCtx ctx; 318 PetscInt howoften = 1; 319 320 PetscCall(PetscOptionsInt("-ts_monitor_draw_solution_function", "Monitor solution provided by TSMonitorSetSolutionFunction() graphically", "TSMonitorDrawSolutionFunction", howoften, &howoften, NULL)); 321 PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts), NULL, "Solution provided by user function", PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx)); 322 PetscCall(TSMonitorSet(ts, TSMonitorDrawSolutionFunction, ctx, (PetscErrorCode(*)(void **))TSMonitorDrawCtxDestroy)); 323 } 324 325 opt = PETSC_FALSE; 326 PetscCall(PetscOptionsString("-ts_monitor_solution_vtk", "Save each time step to a binary file, use filename-%%03" PetscInt_FMT ".vts", "TSMonitorSolutionVTK", NULL, monfilename, sizeof(monfilename), &flg)); 327 if (flg) { 328 const char *ptr = NULL, *ptr2 = NULL; 329 char *filetemplate; 330 PetscCheck(monfilename[0], PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03" PetscInt_FMT ".vts"); 331 /* Do some cursory validation of the input. */ 332 PetscCall(PetscStrstr(monfilename, "%", (char **)&ptr)); 333 PetscCheck(ptr, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03" PetscInt_FMT ".vts"); 334 for (ptr++; ptr && *ptr; ptr++) { 335 PetscCall(PetscStrchr("DdiouxX", *ptr, (char **)&ptr2)); 336 PetscCheck(ptr2 || (*ptr >= '0' && *ptr <= '9'), PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03" PetscInt_FMT ".vts"); 337 if (ptr2) break; 338 } 339 PetscCall(PetscStrallocpy(monfilename, &filetemplate)); 340 PetscCall(TSMonitorSet(ts, TSMonitorSolutionVTK, filetemplate, (PetscErrorCode(*)(void **))TSMonitorSolutionVTKDestroy)); 341 } 342 343 PetscCall(PetscOptionsString("-ts_monitor_dmda_ray", "Display a ray of the solution", "None", "y=0", dir, sizeof(dir), &flg)); 344 if (flg) { 345 TSMonitorDMDARayCtx *rayctx; 346 int ray = 0; 347 DMDirection ddir; 348 DM da; 349 PetscMPIInt rank; 350 351 PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir); 352 if (dir[0] == 'x') ddir = DM_X; 353 else if (dir[0] == 'y') ddir = DM_Y; 354 else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray %s", dir); 355 sscanf(dir + 2, "%d", &ray); 356 357 PetscCall(PetscInfo(((PetscObject)ts), "Displaying DMDA ray %c = %d\n", dir[0], ray)); 358 PetscCall(PetscNew(&rayctx)); 359 PetscCall(TSGetDM(ts, &da)); 360 PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter)); 361 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ts), &rank)); 362 if (rank == 0) PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF, NULL, NULL, 0, 0, 600, 300, &rayctx->viewer)); 363 rayctx->lgctx = NULL; 364 PetscCall(TSMonitorSet(ts, TSMonitorDMDARay, rayctx, TSMonitorDMDARayDestroy)); 365 } 366 PetscCall(PetscOptionsString("-ts_monitor_lg_dmda_ray", "Display a ray of the solution", "None", "x=0", dir, sizeof(dir), &flg)); 367 if (flg) { 368 TSMonitorDMDARayCtx *rayctx; 369 int ray = 0; 370 DMDirection ddir; 371 DM da; 372 PetscInt howoften = 1; 373 374 PetscCheck(dir[1] == '=', PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir); 375 if (dir[0] == 'x') ddir = DM_X; 376 else if (dir[0] == 'y') ddir = DM_Y; 377 else SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir); 378 sscanf(dir + 2, "%d", &ray); 379 380 PetscCall(PetscInfo(((PetscObject)ts), "Displaying LG DMDA ray %c = %d\n", dir[0], ray)); 381 PetscCall(PetscNew(&rayctx)); 382 PetscCall(TSGetDM(ts, &da)); 383 PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter)); 384 PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 600, 400, howoften, &rayctx->lgctx)); 385 PetscCall(TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy)); 386 } 387 388 PetscCall(PetscOptionsName("-ts_monitor_envelope", "Monitor maximum and minimum value of each component of the solution", "TSMonitorEnvelope", &opt)); 389 if (opt) { 390 TSMonitorEnvelopeCtx ctx; 391 392 PetscCall(TSMonitorEnvelopeCtxCreate(ts, &ctx)); 393 PetscCall(TSMonitorSet(ts, TSMonitorEnvelope, ctx, (PetscErrorCode(*)(void **))TSMonitorEnvelopeCtxDestroy)); 394 } 395 flg = PETSC_FALSE; 396 PetscCall(PetscOptionsBool("-ts_monitor_cancel", "Remove all monitors", "TSMonitorCancel", flg, &flg, &opt)); 397 if (opt && flg) PetscCall(TSMonitorCancel(ts)); 398 399 flg = PETSC_FALSE; 400 PetscCall(PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeIJacobianDefaultColor", flg, &flg, NULL)); 401 if (flg) { 402 DM dm; 403 404 PetscCall(TSGetDM(ts, &dm)); 405 PetscCall(DMTSUnsetIJacobianContext_Internal(dm)); 406 PetscCall(TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, NULL)); 407 PetscCall(PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n")); 408 } 409 410 /* Handle specific TS options */ 411 PetscTryTypeMethod(ts, setfromoptions, PetscOptionsObject); 412 413 /* Handle TSAdapt options */ 414 PetscCall(TSGetAdapt(ts, &ts->adapt)); 415 PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type)); 416 PetscCall(TSAdaptSetFromOptions(ts->adapt, PetscOptionsObject)); 417 418 /* TS trajectory must be set after TS, since it may use some TS options above */ 419 tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE; 420 PetscCall(PetscOptionsBool("-ts_save_trajectory", "Save the solution at each timestep", "TSSetSaveTrajectory", tflg, &tflg, NULL)); 421 if (tflg) PetscCall(TSSetSaveTrajectory(ts)); 422 423 PetscCall(TSAdjointSetFromOptions(ts, PetscOptionsObject)); 424 425 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 426 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)ts, PetscOptionsObject)); 427 PetscOptionsEnd(); 428 429 if (ts->trajectory) PetscCall(TSTrajectorySetFromOptions(ts->trajectory, ts)); 430 431 /* why do we have to do this here and not during TSSetUp? */ 432 PetscCall(TSGetSNES(ts, &ts->snes)); 433 if (ts->problem_type == TS_LINEAR) { 434 PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &flg, SNESKSPONLY, SNESKSPTRANSPOSEONLY, "")); 435 if (!flg) PetscCall(SNESSetType(ts->snes, SNESKSPONLY)); 436 } 437 PetscCall(SNESSetFromOptions(ts->snes)); 438 PetscFunctionReturn(PETSC_SUCCESS); 439 } 440 441 /*@ 442 TSGetTrajectory - Gets the trajectory from a `TS` if it exists 443 444 Collective 445 446 Input Parameter: 447 . ts - the `TS` context obtained from `TSCreate()` 448 449 Output Parameter: 450 . tr - the `TSTrajectory` object, if it exists 451 452 Level: advanced 453 454 Note: 455 This routine should be called after all `TS` options have been set 456 457 .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSAdjointSolve()`, `TSTrajectoryCreate()` 458 @*/ 459 PetscErrorCode TSGetTrajectory(TS ts, TSTrajectory *tr) 460 { 461 PetscFunctionBegin; 462 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 463 *tr = ts->trajectory; 464 PetscFunctionReturn(PETSC_SUCCESS); 465 } 466 467 /*@ 468 TSSetSaveTrajectory - Causes the `TS` to save its solutions as it iterates forward in time in a `TSTrajectory` object 469 470 Collective 471 472 Input Parameter: 473 . ts - the `TS` context obtained from `TSCreate()` 474 475 Options Database Keys: 476 + -ts_save_trajectory - saves the trajectory to a file 477 - -ts_trajectory_type type - set trajectory type 478 479 Level: intermediate 480 481 Notes: 482 This routine should be called after all `TS` options have been set 483 484 The `TSTRAJECTORYVISUALIZATION` files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and 485 MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m 486 487 .seealso: [](ch_ts), `TS`, `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()` 488 @*/ 489 PetscErrorCode TSSetSaveTrajectory(TS ts) 490 { 491 PetscFunctionBegin; 492 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 493 if (!ts->trajectory) PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory)); 494 PetscFunctionReturn(PETSC_SUCCESS); 495 } 496 497 /*@ 498 TSResetTrajectory - Destroys and recreates the internal `TSTrajectory` object 499 500 Collective 501 502 Input Parameter: 503 . ts - the `TS` context obtained from `TSCreate()` 504 505 Level: intermediate 506 507 .seealso: [](ch_ts), `TSTrajectory`, `TSGetTrajectory()`, `TSAdjointSolve()`, `TSRemoveTrajectory()` 508 @*/ 509 PetscErrorCode TSResetTrajectory(TS ts) 510 { 511 PetscFunctionBegin; 512 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 513 if (ts->trajectory) { 514 PetscCall(TSTrajectoryDestroy(&ts->trajectory)); 515 PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts), &ts->trajectory)); 516 } 517 PetscFunctionReturn(PETSC_SUCCESS); 518 } 519 520 /*@ 521 TSRemoveTrajectory - Destroys and removes the internal `TSTrajectory` object from a `TS` 522 523 Collective 524 525 Input Parameter: 526 . ts - the `TS` context obtained from `TSCreate()` 527 528 Level: intermediate 529 530 .seealso: [](ch_ts), `TSTrajectory`, `TSResetTrajectory()`, `TSAdjointSolve()` 531 @*/ 532 PetscErrorCode TSRemoveTrajectory(TS ts) 533 { 534 PetscFunctionBegin; 535 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 536 if (ts->trajectory) PetscCall(TSTrajectoryDestroy(&ts->trajectory)); 537 PetscFunctionReturn(PETSC_SUCCESS); 538 } 539 540 /*@ 541 TSComputeRHSJacobian - Computes the Jacobian matrix that has been 542 set with `TSSetRHSJacobian()`. 543 544 Collective 545 546 Input Parameters: 547 + ts - the `TS` context 548 . t - current timestep 549 - U - input vector 550 551 Output Parameters: 552 + A - Jacobian matrix 553 - B - optional preconditioning matrix 554 555 Level: developer 556 557 Note: 558 Most users should not need to explicitly call this routine, as it 559 is used internally within the nonlinear solvers. 560 561 .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `KSPSetOperators()` 562 @*/ 563 PetscErrorCode TSComputeRHSJacobian(TS ts, PetscReal t, Vec U, Mat A, Mat B) 564 { 565 PetscObjectState Ustate; 566 PetscObjectId Uid; 567 DM dm; 568 DMTS tsdm; 569 TSRHSJacobianFn *rhsjacobianfunc; 570 void *ctx; 571 TSRHSFunctionFn *rhsfunction; 572 573 PetscFunctionBegin; 574 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 575 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 576 PetscCheckSameComm(ts, 1, U, 3); 577 PetscCall(TSGetDM(ts, &dm)); 578 PetscCall(DMGetDMTS(dm, &tsdm)); 579 PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL)); 580 PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobianfunc, &ctx)); 581 PetscCall(PetscObjectStateGet((PetscObject)U, &Ustate)); 582 PetscCall(PetscObjectGetId((PetscObject)U, &Uid)); 583 584 if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && (rhsfunction != TSComputeRHSFunctionLinear)) PetscFunctionReturn(PETSC_SUCCESS); 585 586 PetscCheck(ts->rhsjacobian.shift == 0.0 || !ts->rhsjacobian.reuse, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Should not call TSComputeRHSJacobian() on a shifted matrix (shift=%lf) when RHSJacobian is reusable.", (double)ts->rhsjacobian.shift); 587 if (rhsjacobianfunc) { 588 PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, A, B)); 589 PetscCallBack("TS callback Jacobian", (*rhsjacobianfunc)(ts, t, U, A, B, ctx)); 590 ts->rhsjacs++; 591 PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, A, B)); 592 } else { 593 PetscCall(MatZeroEntries(A)); 594 if (B && A != B) PetscCall(MatZeroEntries(B)); 595 } 596 ts->rhsjacobian.time = t; 597 ts->rhsjacobian.shift = 0; 598 ts->rhsjacobian.scale = 1.; 599 PetscCall(PetscObjectGetId((PetscObject)U, &ts->rhsjacobian.Xid)); 600 PetscCall(PetscObjectStateGet((PetscObject)U, &ts->rhsjacobian.Xstate)); 601 PetscFunctionReturn(PETSC_SUCCESS); 602 } 603 604 /*@ 605 TSComputeRHSFunction - Evaluates the right-hand-side function for a `TS` 606 607 Collective 608 609 Input Parameters: 610 + ts - the `TS` context 611 . t - current time 612 - U - state vector 613 614 Output Parameter: 615 . y - right-hand side 616 617 Level: developer 618 619 Note: 620 Most users should not need to explicitly call this routine, as it 621 is used internally within the nonlinear solvers. 622 623 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()` 624 @*/ 625 PetscErrorCode TSComputeRHSFunction(TS ts, PetscReal t, Vec U, Vec y) 626 { 627 TSRHSFunctionFn *rhsfunction; 628 TSIFunctionFn *ifunction; 629 void *ctx; 630 DM dm; 631 632 PetscFunctionBegin; 633 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 634 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 635 PetscValidHeaderSpecific(y, VEC_CLASSID, 4); 636 PetscCall(TSGetDM(ts, &dm)); 637 PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, &ctx)); 638 PetscCall(DMTSGetIFunction(dm, &ifunction, NULL)); 639 640 PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()"); 641 642 if (rhsfunction) { 643 PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, y, 0)); 644 PetscCall(VecLockReadPush(U)); 645 PetscCallBack("TS callback right-hand-side", (*rhsfunction)(ts, t, U, y, ctx)); 646 PetscCall(VecLockReadPop(U)); 647 ts->rhsfuncs++; 648 PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, y, 0)); 649 } else PetscCall(VecZeroEntries(y)); 650 PetscFunctionReturn(PETSC_SUCCESS); 651 } 652 653 /*@ 654 TSComputeSolutionFunction - Evaluates the solution function. 655 656 Collective 657 658 Input Parameters: 659 + ts - the `TS` context 660 - t - current time 661 662 Output Parameter: 663 . U - the solution 664 665 Level: developer 666 667 .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()` 668 @*/ 669 PetscErrorCode TSComputeSolutionFunction(TS ts, PetscReal t, Vec U) 670 { 671 TSSolutionFn *solutionfunction; 672 void *ctx; 673 DM dm; 674 675 PetscFunctionBegin; 676 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 677 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 678 PetscCall(TSGetDM(ts, &dm)); 679 PetscCall(DMTSGetSolutionFunction(dm, &solutionfunction, &ctx)); 680 if (solutionfunction) PetscCallBack("TS callback solution", (*solutionfunction)(ts, t, U, ctx)); 681 PetscFunctionReturn(PETSC_SUCCESS); 682 } 683 /*@ 684 TSComputeForcingFunction - Evaluates the forcing function. 685 686 Collective 687 688 Input Parameters: 689 + ts - the `TS` context 690 - t - current time 691 692 Output Parameter: 693 . U - the function value 694 695 Level: developer 696 697 .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSSetRHSFunction()`, `TSComputeIFunction()` 698 @*/ 699 PetscErrorCode TSComputeForcingFunction(TS ts, PetscReal t, Vec U) 700 { 701 void *ctx; 702 DM dm; 703 TSForcingFn *forcing; 704 705 PetscFunctionBegin; 706 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 707 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 708 PetscCall(TSGetDM(ts, &dm)); 709 PetscCall(DMTSGetForcingFunction(dm, &forcing, &ctx)); 710 711 if (forcing) PetscCallBack("TS callback forcing function", (*forcing)(ts, t, U, ctx)); 712 PetscFunctionReturn(PETSC_SUCCESS); 713 } 714 715 PetscErrorCode TSGetRHSMats_Private(TS ts, Mat *Arhs, Mat *Brhs) 716 { 717 Mat A, B; 718 TSIJacobianFn *ijacobian; 719 720 PetscFunctionBegin; 721 if (Arhs) *Arhs = NULL; 722 if (Brhs) *Brhs = NULL; 723 PetscCall(TSGetIJacobian(ts, &A, &B, &ijacobian, NULL)); 724 if (Arhs) { 725 if (!ts->Arhs) { 726 if (ijacobian) { 727 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &ts->Arhs)); 728 PetscCall(TSSetMatStructure(ts, SAME_NONZERO_PATTERN)); 729 } else { 730 ts->Arhs = A; 731 PetscCall(PetscObjectReference((PetscObject)A)); 732 } 733 } else { 734 PetscBool flg; 735 PetscCall(SNESGetUseMatrixFree(ts->snes, NULL, &flg)); 736 /* Handle case where user provided only RHSJacobian and used -snes_mf_operator */ 737 if (flg && !ijacobian && ts->Arhs == ts->Brhs) { 738 PetscCall(PetscObjectDereference((PetscObject)ts->Arhs)); 739 ts->Arhs = A; 740 PetscCall(PetscObjectReference((PetscObject)A)); 741 } 742 } 743 *Arhs = ts->Arhs; 744 } 745 if (Brhs) { 746 if (!ts->Brhs) { 747 if (A != B) { 748 if (ijacobian) { 749 PetscCall(MatDuplicate(B, MAT_DO_NOT_COPY_VALUES, &ts->Brhs)); 750 } else { 751 ts->Brhs = B; 752 PetscCall(PetscObjectReference((PetscObject)B)); 753 } 754 } else { 755 PetscCall(PetscObjectReference((PetscObject)ts->Arhs)); 756 ts->Brhs = ts->Arhs; 757 } 758 } 759 *Brhs = ts->Brhs; 760 } 761 PetscFunctionReturn(PETSC_SUCCESS); 762 } 763 764 /*@ 765 TSComputeIFunction - Evaluates the DAE residual written in the implicit form F(t,U,Udot)=0 766 767 Collective 768 769 Input Parameters: 770 + ts - the `TS` context 771 . t - current time 772 . U - state vector 773 . Udot - time derivative of state vector 774 - imex - flag indicates if the method is `TSIMEX` so that the RHSFunction should be kept separate 775 776 Output Parameter: 777 . Y - right-hand side 778 779 Level: developer 780 781 Note: 782 Most users should not need to explicitly call this routine, as it 783 is used internally within the nonlinear solvers. 784 785 If the user did not write their equations in implicit form, this 786 function recasts them in implicit form. 787 788 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSComputeRHSFunction()` 789 @*/ 790 PetscErrorCode TSComputeIFunction(TS ts, PetscReal t, Vec U, Vec Udot, Vec Y, PetscBool imex) 791 { 792 TSIFunctionFn *ifunction; 793 TSRHSFunctionFn *rhsfunction; 794 void *ctx; 795 DM dm; 796 797 PetscFunctionBegin; 798 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 799 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 800 PetscValidHeaderSpecific(Udot, VEC_CLASSID, 4); 801 PetscValidHeaderSpecific(Y, VEC_CLASSID, 5); 802 803 PetscCall(TSGetDM(ts, &dm)); 804 PetscCall(DMTSGetIFunction(dm, &ifunction, &ctx)); 805 PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL)); 806 807 PetscCheck(rhsfunction || ifunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSFunction() and / or TSSetIFunction()"); 808 809 PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, Udot, Y)); 810 if (ifunction) { 811 PetscCallBack("TS callback implicit function", (*ifunction)(ts, t, U, Udot, Y, ctx)); 812 ts->ifuncs++; 813 } 814 if (imex) { 815 if (!ifunction) PetscCall(VecCopy(Udot, Y)); 816 } else if (rhsfunction) { 817 if (ifunction) { 818 Vec Frhs; 819 820 PetscCall(DMGetGlobalVector(dm, &Frhs)); 821 PetscCall(TSComputeRHSFunction(ts, t, U, Frhs)); 822 PetscCall(VecAXPY(Y, -1, Frhs)); 823 PetscCall(DMRestoreGlobalVector(dm, &Frhs)); 824 } else { 825 PetscCall(TSComputeRHSFunction(ts, t, U, Y)); 826 PetscCall(VecAYPX(Y, -1, Udot)); 827 } 828 } 829 PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, Udot, Y)); 830 PetscFunctionReturn(PETSC_SUCCESS); 831 } 832 833 /* 834 TSRecoverRHSJacobian - Recover the Jacobian matrix so that one can call `TSComputeRHSJacobian()` on it. 835 836 Note: 837 This routine is needed when one switches from `TSComputeIJacobian()` to `TSComputeRHSJacobian()` because the Jacobian matrix may be shifted or scaled in `TSComputeIJacobian()`. 838 839 */ 840 static PetscErrorCode TSRecoverRHSJacobian(TS ts, Mat A, Mat B) 841 { 842 PetscFunctionBegin; 843 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 844 PetscCheck(A == ts->Arhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Amat"); 845 PetscCheck(B == ts->Brhs, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Invalid Bmat"); 846 847 if (ts->rhsjacobian.shift) PetscCall(MatShift(A, -ts->rhsjacobian.shift)); 848 if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(A, -1)); 849 if (B && B == ts->Brhs && A != B) { 850 if (ts->rhsjacobian.shift) PetscCall(MatShift(B, -ts->rhsjacobian.shift)); 851 if (ts->rhsjacobian.scale == -1.) PetscCall(MatScale(B, -1)); 852 } 853 ts->rhsjacobian.shift = 0; 854 ts->rhsjacobian.scale = 1.; 855 PetscFunctionReturn(PETSC_SUCCESS); 856 } 857 858 /*@ 859 TSComputeIJacobian - Evaluates the Jacobian of the DAE 860 861 Collective 862 863 Input Parameters: 864 + ts - the `TS` context 865 . t - current timestep 866 . U - state vector 867 . Udot - time derivative of state vector 868 . shift - shift to apply, see note below 869 - imex - flag indicates if the method is `TSIMEX` so that the RHSJacobian should be kept separate 870 871 Output Parameters: 872 + A - Jacobian matrix 873 - B - matrix from which the preconditioner is constructed; often the same as `A` 874 875 Level: developer 876 877 Notes: 878 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 879 .vb 880 dF/dU + shift*dF/dUdot 881 .ve 882 Most users should not need to explicitly call this routine, as it 883 is used internally within the nonlinear solvers. 884 885 .seealso: [](ch_ts), `TS`, `TSSetIJacobian()` 886 @*/ 887 PetscErrorCode TSComputeIJacobian(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, PetscBool imex) 888 { 889 TSIJacobianFn *ijacobian; 890 TSRHSJacobianFn *rhsjacobian; 891 DM dm; 892 void *ctx; 893 894 PetscFunctionBegin; 895 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 896 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 897 PetscValidHeaderSpecific(Udot, VEC_CLASSID, 4); 898 PetscValidHeaderSpecific(A, MAT_CLASSID, 6); 899 PetscValidHeaderSpecific(B, MAT_CLASSID, 7); 900 901 PetscCall(TSGetDM(ts, &dm)); 902 PetscCall(DMTSGetIJacobian(dm, &ijacobian, &ctx)); 903 PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL)); 904 905 PetscCheck(rhsjacobian || ijacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_USER, "Must call TSSetRHSJacobian() and / or TSSetIJacobian()"); 906 907 PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, A, B)); 908 if (ijacobian) { 909 PetscCallBack("TS callback implicit Jacobian", (*ijacobian)(ts, t, U, Udot, shift, A, B, ctx)); 910 ts->ijacs++; 911 } 912 if (imex) { 913 if (!ijacobian) { /* system was written as Udot = G(t,U) */ 914 PetscBool assembled; 915 if (rhsjacobian) { 916 Mat Arhs = NULL; 917 PetscCall(TSGetRHSMats_Private(ts, &Arhs, NULL)); 918 if (A == Arhs) { 919 PetscCheck(rhsjacobian != TSComputeRHSJacobianConstant, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Unsupported operation! cannot use TSComputeRHSJacobianConstant"); /* there is no way to reconstruct shift*M-J since J cannot be reevaluated */ 920 ts->rhsjacobian.time = PETSC_MIN_REAL; 921 } 922 } 923 PetscCall(MatZeroEntries(A)); 924 PetscCall(MatAssembled(A, &assembled)); 925 if (!assembled) { 926 PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 927 PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 928 } 929 PetscCall(MatShift(A, shift)); 930 if (A != B) { 931 PetscCall(MatZeroEntries(B)); 932 PetscCall(MatAssembled(B, &assembled)); 933 if (!assembled) { 934 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 935 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 936 } 937 PetscCall(MatShift(B, shift)); 938 } 939 } 940 } else { 941 Mat Arhs = NULL, Brhs = NULL; 942 943 /* RHSJacobian needs to be converted to part of IJacobian if exists */ 944 if (rhsjacobian) PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs)); 945 if (Arhs == A) { /* No IJacobian matrix, so we only have the RHS matrix */ 946 PetscObjectState Ustate; 947 PetscObjectId Uid; 948 TSRHSFunctionFn *rhsfunction; 949 950 PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL)); 951 PetscCall(PetscObjectStateGet((PetscObject)U, &Ustate)); 952 PetscCall(PetscObjectGetId((PetscObject)U, &Uid)); 953 if ((rhsjacobian == TSComputeRHSJacobianConstant || (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && rhsfunction != TSComputeRHSFunctionLinear)) && 954 ts->rhsjacobian.scale == -1.) { /* No need to recompute RHSJacobian */ 955 PetscCall(MatShift(A, shift - ts->rhsjacobian.shift)); /* revert the old shift and add the new shift with a single call to MatShift */ 956 if (A != B) PetscCall(MatShift(B, shift - ts->rhsjacobian.shift)); 957 } else { 958 PetscBool flg; 959 960 if (ts->rhsjacobian.reuse) { /* Undo the damage */ 961 /* MatScale has a short path for this case. 962 However, this code path is taken the first time TSComputeRHSJacobian is called 963 and the matrices have not been assembled yet */ 964 PetscCall(TSRecoverRHSJacobian(ts, A, B)); 965 } 966 PetscCall(TSComputeRHSJacobian(ts, t, U, A, B)); 967 PetscCall(SNESGetUseMatrixFree(ts->snes, NULL, &flg)); 968 /* since -snes_mf_operator uses the full SNES function it does not need to be shifted or scaled here */ 969 if (!flg) { 970 PetscCall(MatScale(A, -1)); 971 PetscCall(MatShift(A, shift)); 972 } 973 if (A != B) { 974 PetscCall(MatScale(B, -1)); 975 PetscCall(MatShift(B, shift)); 976 } 977 } 978 ts->rhsjacobian.scale = -1; 979 ts->rhsjacobian.shift = shift; 980 } else if (Arhs) { /* Both IJacobian and RHSJacobian */ 981 if (!ijacobian) { /* No IJacobian provided, but we have a separate RHS matrix */ 982 PetscCall(MatZeroEntries(A)); 983 PetscCall(MatShift(A, shift)); 984 if (A != B) { 985 PetscCall(MatZeroEntries(B)); 986 PetscCall(MatShift(B, shift)); 987 } 988 } 989 PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs)); 990 PetscCall(MatAXPY(A, -1, Arhs, ts->axpy_pattern)); 991 if (A != B) PetscCall(MatAXPY(B, -1, Brhs, ts->axpy_pattern)); 992 } 993 } 994 PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, A, B)); 995 PetscFunctionReturn(PETSC_SUCCESS); 996 } 997 998 /*@C 999 TSSetRHSFunction - Sets the routine for evaluating the function, 1000 where U_t = G(t,u). 1001 1002 Logically Collective 1003 1004 Input Parameters: 1005 + ts - the `TS` context obtained from `TSCreate()` 1006 . r - vector to put the computed right-hand side (or `NULL` to have it created) 1007 . f - routine for evaluating the right-hand-side function 1008 - ctx - [optional] user-defined context for private data for the function evaluation routine (may be `NULL`) 1009 1010 Level: beginner 1011 1012 Note: 1013 You must call this function or `TSSetIFunction()` to define your ODE. You cannot use this function when solving a DAE. 1014 1015 .seealso: [](ch_ts), `TS`, `TSRHSFunctionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSSetIFunction()` 1016 @*/ 1017 PetscErrorCode TSSetRHSFunction(TS ts, Vec r, TSRHSFunctionFn *f, void *ctx) 1018 { 1019 SNES snes; 1020 Vec ralloc = NULL; 1021 DM dm; 1022 1023 PetscFunctionBegin; 1024 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1025 if (r) PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1026 1027 PetscCall(TSGetDM(ts, &dm)); 1028 PetscCall(DMTSSetRHSFunction(dm, f, ctx)); 1029 PetscCall(TSGetSNES(ts, &snes)); 1030 if (!r && !ts->dm && ts->vec_sol) { 1031 PetscCall(VecDuplicate(ts->vec_sol, &ralloc)); 1032 r = ralloc; 1033 } 1034 PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts)); 1035 PetscCall(VecDestroy(&ralloc)); 1036 PetscFunctionReturn(PETSC_SUCCESS); 1037 } 1038 1039 /*@C 1040 TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE 1041 1042 Logically Collective 1043 1044 Input Parameters: 1045 + ts - the `TS` context obtained from `TSCreate()` 1046 . f - routine for evaluating the solution 1047 - ctx - [optional] user-defined context for private data for the 1048 function evaluation routine (may be `NULL`) 1049 1050 Options Database Keys: 1051 + -ts_monitor_lg_error - create a graphical monitor of error history, requires user to have provided `TSSetSolutionFunction()` 1052 - -ts_monitor_draw_error - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()` 1053 1054 Level: intermediate 1055 1056 Notes: 1057 This routine is used for testing accuracy of time integration schemes when you already know the solution. 1058 If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to 1059 create closed-form solutions with non-physical forcing terms. 1060 1061 For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history. 1062 1063 .seealso: [](ch_ts), `TS`, `TSSolutionFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, `TSComputeSolutionFunction()`, `TSSetForcingFunction()`, `TSSetSolution()`, `TSGetSolution()`, `TSMonitorLGError()`, `TSMonitorDrawError()` 1064 @*/ 1065 PetscErrorCode TSSetSolutionFunction(TS ts, TSSolutionFn *f, void *ctx) 1066 { 1067 DM dm; 1068 1069 PetscFunctionBegin; 1070 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1071 PetscCall(TSGetDM(ts, &dm)); 1072 PetscCall(DMTSSetSolutionFunction(dm, f, ctx)); 1073 PetscFunctionReturn(PETSC_SUCCESS); 1074 } 1075 1076 /*@C 1077 TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE 1078 1079 Logically Collective 1080 1081 Input Parameters: 1082 + ts - the `TS` context obtained from `TSCreate()` 1083 . func - routine for evaluating the forcing function 1084 - ctx - [optional] user-defined context for private data for the function evaluation routine 1085 (may be `NULL`) 1086 1087 Level: intermediate 1088 1089 Notes: 1090 This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to 1091 create closed-form solutions with a non-physical forcing term. It allows you to use the Method of Manufactored Solution without directly editing the 1092 definition of the problem you are solving and hence possibly introducing bugs. 1093 1094 This replaces the ODE F(u,u_t,t) = 0 the `TS` is solving with F(u,u_t,t) - func(t) = 0 1095 1096 This forcing function does not depend on the solution to the equations, it can only depend on spatial location, time, and possibly parameters, the 1097 parameters can be passed in the ctx variable. 1098 1099 For low-dimensional problems solved in serial, such as small discrete systems, `TSMonitorLGError()` can be used to monitor the error history. 1100 1101 .seealso: [](ch_ts), `TS`, `TSForcingFn`, `TSSetRHSJacobian()`, `TSSetIJacobian()`, 1102 `TSComputeSolutionFunction()`, `TSSetSolutionFunction()` 1103 @*/ 1104 PetscErrorCode TSSetForcingFunction(TS ts, TSForcingFn *func, void *ctx) 1105 { 1106 DM dm; 1107 1108 PetscFunctionBegin; 1109 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1110 PetscCall(TSGetDM(ts, &dm)); 1111 PetscCall(DMTSSetForcingFunction(dm, func, ctx)); 1112 PetscFunctionReturn(PETSC_SUCCESS); 1113 } 1114 1115 /*@C 1116 TSSetRHSJacobian - Sets the function to compute the Jacobian of G, 1117 where U_t = G(U,t), as well as the location to store the matrix. 1118 1119 Logically Collective 1120 1121 Input Parameters: 1122 + ts - the `TS` context obtained from `TSCreate()` 1123 . Amat - (approximate) location to store Jacobian matrix entries computed by `f` 1124 . Pmat - matrix from which preconditioner is to be constructed (usually the same as `Amat`) 1125 . f - the Jacobian evaluation routine 1126 - ctx - [optional] user-defined context for private data for the Jacobian evaluation routine (may be `NULL`) 1127 1128 Level: beginner 1129 1130 Notes: 1131 You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value 1132 1133 The `TS` solver may modify the nonzero structure and the entries of the matrices `Amat` and `Pmat` between the calls to `f()` 1134 You should not assume the values are the same in the next call to f() as you set them in the previous call. 1135 1136 .seealso: [](ch_ts), `TS`, `TSRHSJacobianFn`, `SNESComputeJacobianDefaultColor()`, 1137 `TSSetRHSFunction()`, `TSRHSJacobianSetReuse()`, `TSSetIJacobian()`, `TSRHSFunctionFn`, `TSIFunctionFn` 1138 @*/ 1139 PetscErrorCode TSSetRHSJacobian(TS ts, Mat Amat, Mat Pmat, TSRHSJacobianFn *f, void *ctx) 1140 { 1141 SNES snes; 1142 DM dm; 1143 TSIJacobianFn *ijacobian; 1144 1145 PetscFunctionBegin; 1146 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1147 if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 1148 if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 1149 if (Amat) PetscCheckSameComm(ts, 1, Amat, 2); 1150 if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3); 1151 1152 PetscCall(TSGetDM(ts, &dm)); 1153 PetscCall(DMTSSetRHSJacobian(dm, f, ctx)); 1154 PetscCall(DMTSGetIJacobian(dm, &ijacobian, NULL)); 1155 PetscCall(TSGetSNES(ts, &snes)); 1156 if (!ijacobian) PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts)); 1157 if (Amat) { 1158 PetscCall(PetscObjectReference((PetscObject)Amat)); 1159 PetscCall(MatDestroy(&ts->Arhs)); 1160 ts->Arhs = Amat; 1161 } 1162 if (Pmat) { 1163 PetscCall(PetscObjectReference((PetscObject)Pmat)); 1164 PetscCall(MatDestroy(&ts->Brhs)); 1165 ts->Brhs = Pmat; 1166 } 1167 PetscFunctionReturn(PETSC_SUCCESS); 1168 } 1169 1170 /*@C 1171 TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved. 1172 1173 Logically Collective 1174 1175 Input Parameters: 1176 + ts - the `TS` context obtained from `TSCreate()` 1177 . r - vector to hold the residual (or `NULL` to have it created internally) 1178 . f - the function evaluation routine 1179 - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`) 1180 1181 Level: beginner 1182 1183 Note: 1184 The user MUST call either this routine or `TSSetRHSFunction()` to define the ODE. When solving DAEs you must use this function. 1185 1186 .seealso: [](ch_ts), `TS`, `TSIFunctionFn`, `TSSetRHSJacobian()`, `TSSetRHSFunction()`, 1187 `TSSetIJacobian()` 1188 @*/ 1189 PetscErrorCode TSSetIFunction(TS ts, Vec r, TSIFunctionFn *f, void *ctx) 1190 { 1191 SNES snes; 1192 Vec ralloc = NULL; 1193 DM dm; 1194 1195 PetscFunctionBegin; 1196 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1197 if (r) PetscValidHeaderSpecific(r, VEC_CLASSID, 2); 1198 1199 PetscCall(TSGetDM(ts, &dm)); 1200 PetscCall(DMTSSetIFunction(dm, f, ctx)); 1201 1202 PetscCall(TSGetSNES(ts, &snes)); 1203 if (!r && !ts->dm && ts->vec_sol) { 1204 PetscCall(VecDuplicate(ts->vec_sol, &ralloc)); 1205 r = ralloc; 1206 } 1207 PetscCall(SNESSetFunction(snes, r, SNESTSFormFunction, ts)); 1208 PetscCall(VecDestroy(&ralloc)); 1209 PetscFunctionReturn(PETSC_SUCCESS); 1210 } 1211 1212 /*@C 1213 TSGetIFunction - Returns the vector where the implicit residual is stored and the function/context to compute it. 1214 1215 Not Collective 1216 1217 Input Parameter: 1218 . ts - the `TS` context 1219 1220 Output Parameters: 1221 + r - vector to hold residual (or `NULL`) 1222 . func - the function to compute residual (or `NULL`) 1223 - ctx - the function context (or `NULL`) 1224 1225 Level: advanced 1226 1227 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()` 1228 @*/ 1229 PetscErrorCode TSGetIFunction(TS ts, Vec *r, TSIFunctionFn **func, void **ctx) 1230 { 1231 SNES snes; 1232 DM dm; 1233 1234 PetscFunctionBegin; 1235 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1236 PetscCall(TSGetSNES(ts, &snes)); 1237 PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 1238 PetscCall(TSGetDM(ts, &dm)); 1239 PetscCall(DMTSGetIFunction(dm, func, ctx)); 1240 PetscFunctionReturn(PETSC_SUCCESS); 1241 } 1242 1243 /*@C 1244 TSGetRHSFunction - Returns the vector where the right-hand side is stored and the function/context to compute it. 1245 1246 Not Collective 1247 1248 Input Parameter: 1249 . ts - the `TS` context 1250 1251 Output Parameters: 1252 + r - vector to hold computed right-hand side (or `NULL`) 1253 . func - the function to compute right-hand side (or `NULL`) 1254 - ctx - the function context (or `NULL`) 1255 1256 Level: advanced 1257 1258 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `SNESGetFunction()` 1259 @*/ 1260 PetscErrorCode TSGetRHSFunction(TS ts, Vec *r, TSRHSFunctionFn **func, void **ctx) 1261 { 1262 SNES snes; 1263 DM dm; 1264 1265 PetscFunctionBegin; 1266 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1267 PetscCall(TSGetSNES(ts, &snes)); 1268 PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 1269 PetscCall(TSGetDM(ts, &dm)); 1270 PetscCall(DMTSGetRHSFunction(dm, func, ctx)); 1271 PetscFunctionReturn(PETSC_SUCCESS); 1272 } 1273 1274 /*@C 1275 TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function 1276 provided with `TSSetIFunction()`. 1277 1278 Logically Collective 1279 1280 Input Parameters: 1281 + ts - the `TS` context obtained from `TSCreate()` 1282 . Amat - (approximate) matrix to store Jacobian entries computed by `f` 1283 . Pmat - matrix used to compute preconditioner (usually the same as `Amat`) 1284 . f - the Jacobian evaluation routine 1285 - ctx - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`) 1286 1287 Level: beginner 1288 1289 Notes: 1290 The matrices `Amat` and `Pmat` are exactly the matrices that are used by `SNES` for the nonlinear solve. 1291 1292 If you know the operator Amat has a null space you can use `MatSetNullSpace()` and `MatSetTransposeNullSpace()` to supply the null 1293 space to `Amat` and the `KSP` solvers will automatically use that null space as needed during the solution process. 1294 1295 The matrix dF/dU + a*dF/dU_t you provide turns out to be 1296 the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved. 1297 The time integrator internally approximates U_t by W+a*U where the positive "shift" 1298 a and vector W depend on the integration method, step size, and past states. For example with 1299 the backward Euler method a = 1/dt and W = -a*U(previous timestep) so 1300 W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt 1301 1302 You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value 1303 1304 The TS solver may modify the nonzero structure and the entries of the matrices `Amat` and `Pmat` between the calls to `f` 1305 You should not assume the values are the same in the next call to `f` as you set them in the previous call. 1306 1307 In case `TSSetRHSJacobian()` is also used in conjunction with a fully-implicit solver, 1308 multilevel linear solvers, e.g. `PCMG`, will likely not work due to the way `TS` handles rhs matrices. 1309 1310 .seealso: [](ch_ts), `TS`, `TSIJacobianFn`, `TSSetIFunction()`, `TSSetRHSJacobian()`, 1311 `SNESComputeJacobianDefaultColor()`, `SNESComputeJacobianDefault()`, `TSSetRHSFunction()` 1312 @*/ 1313 PetscErrorCode TSSetIJacobian(TS ts, Mat Amat, Mat Pmat, TSIJacobianFn *f, void *ctx) 1314 { 1315 SNES snes; 1316 DM dm; 1317 1318 PetscFunctionBegin; 1319 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1320 if (Amat) PetscValidHeaderSpecific(Amat, MAT_CLASSID, 2); 1321 if (Pmat) PetscValidHeaderSpecific(Pmat, MAT_CLASSID, 3); 1322 if (Amat) PetscCheckSameComm(ts, 1, Amat, 2); 1323 if (Pmat) PetscCheckSameComm(ts, 1, Pmat, 3); 1324 1325 PetscCall(TSGetDM(ts, &dm)); 1326 PetscCall(DMTSSetIJacobian(dm, f, ctx)); 1327 1328 PetscCall(TSGetSNES(ts, &snes)); 1329 PetscCall(SNESSetJacobian(snes, Amat, Pmat, SNESTSFormJacobian, ts)); 1330 PetscFunctionReturn(PETSC_SUCCESS); 1331 } 1332 1333 /*@ 1334 TSRHSJacobianSetReuse - restore the RHS Jacobian before calling the user-provided `TSRHSJacobianFn` function again 1335 1336 Logically Collective 1337 1338 Input Parameters: 1339 + ts - `TS` context obtained from `TSCreate()` 1340 - reuse - `PETSC_TRUE` if the RHS Jacobian 1341 1342 Level: intermediate 1343 1344 Notes: 1345 Without this flag, `TS` will change the sign and shift the RHS Jacobian for a 1346 finite-time-step implicit solve, in which case the user function will need to recompute the 1347 entire Jacobian. The `reuse `flag must be set if the evaluation function assumes that the 1348 matrix entries have not been changed by the `TS`. 1349 1350 .seealso: [](ch_ts), `TS`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 1351 @*/ 1352 PetscErrorCode TSRHSJacobianSetReuse(TS ts, PetscBool reuse) 1353 { 1354 PetscFunctionBegin; 1355 ts->rhsjacobian.reuse = reuse; 1356 PetscFunctionReturn(PETSC_SUCCESS); 1357 } 1358 1359 /*@C 1360 TSSetI2Function - Set the function to compute F(t,U,U_t,U_tt) where F = 0 is the DAE to be solved. 1361 1362 Logically Collective 1363 1364 Input Parameters: 1365 + ts - the `TS` context obtained from `TSCreate()` 1366 . F - vector to hold the residual (or `NULL` to have it created internally) 1367 . fun - the function evaluation routine 1368 - ctx - user-defined context for private data for the function evaluation routine (may be `NULL`) 1369 1370 Level: beginner 1371 1372 .seealso: [](ch_ts), `TS`, `TSI2FunctionFn`, `TSSetI2Jacobian()`, `TSSetIFunction()`, 1373 `TSCreate()`, `TSSetRHSFunction()` 1374 @*/ 1375 PetscErrorCode TSSetI2Function(TS ts, Vec F, TSI2FunctionFn *fun, void *ctx) 1376 { 1377 DM dm; 1378 1379 PetscFunctionBegin; 1380 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1381 if (F) PetscValidHeaderSpecific(F, VEC_CLASSID, 2); 1382 PetscCall(TSSetIFunction(ts, F, NULL, NULL)); 1383 PetscCall(TSGetDM(ts, &dm)); 1384 PetscCall(DMTSSetI2Function(dm, fun, ctx)); 1385 PetscFunctionReturn(PETSC_SUCCESS); 1386 } 1387 1388 /*@C 1389 TSGetI2Function - Returns the vector where the implicit residual is stored and the function/context to compute it. 1390 1391 Not Collective 1392 1393 Input Parameter: 1394 . ts - the `TS` context 1395 1396 Output Parameters: 1397 + r - vector to hold residual (or `NULL`) 1398 . fun - the function to compute residual (or `NULL`) 1399 - ctx - the function context (or `NULL`) 1400 1401 Level: advanced 1402 1403 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `SNESGetFunction()`, `TSCreate()` 1404 @*/ 1405 PetscErrorCode TSGetI2Function(TS ts, Vec *r, TSI2FunctionFn **fun, void **ctx) 1406 { 1407 SNES snes; 1408 DM dm; 1409 1410 PetscFunctionBegin; 1411 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1412 PetscCall(TSGetSNES(ts, &snes)); 1413 PetscCall(SNESGetFunction(snes, r, NULL, NULL)); 1414 PetscCall(TSGetDM(ts, &dm)); 1415 PetscCall(DMTSGetI2Function(dm, fun, ctx)); 1416 PetscFunctionReturn(PETSC_SUCCESS); 1417 } 1418 1419 /*@C 1420 TSSetI2Jacobian - Set the function to compute the matrix dF/dU + v*dF/dU_t + a*dF/dU_tt 1421 where F(t,U,U_t,U_tt) is the function you provided with `TSSetI2Function()`. 1422 1423 Logically Collective 1424 1425 Input Parameters: 1426 + ts - the `TS` context obtained from `TSCreate()` 1427 . J - matrix to hold the Jacobian values 1428 . P - matrix for constructing the preconditioner (may be same as `J`) 1429 . jac - the Jacobian evaluation routine, see `TSI2JacobianFn` for the calling sequence 1430 - ctx - user-defined context for private data for the Jacobian evaluation routine (may be `NULL`) 1431 1432 Level: beginner 1433 1434 Notes: 1435 The matrices `J` and `P` are exactly the matrices that are used by `SNES` for the nonlinear solve. 1436 1437 The matrix dF/dU + v*dF/dU_t + a*dF/dU_tt you provide turns out to be 1438 the Jacobian of G(U) = F(t,U,W+v*U,W'+a*U) where F(t,U,U_t,U_tt) = 0 is the DAE to be solved. 1439 The time integrator internally approximates U_t by W+v*U and U_tt by W'+a*U where the positive "shift" 1440 parameters 'v' and 'a' and vectors W, W' depend on the integration method, step size, and past states. 1441 1442 .seealso: [](ch_ts), `TS`, `TSI2JacobianFn`, `TSSetI2Function()`, `TSGetI2Jacobian()` 1443 @*/ 1444 PetscErrorCode TSSetI2Jacobian(TS ts, Mat J, Mat P, TSI2JacobianFn *jac, void *ctx) 1445 { 1446 DM dm; 1447 1448 PetscFunctionBegin; 1449 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1450 if (J) PetscValidHeaderSpecific(J, MAT_CLASSID, 2); 1451 if (P) PetscValidHeaderSpecific(P, MAT_CLASSID, 3); 1452 PetscCall(TSSetIJacobian(ts, J, P, NULL, NULL)); 1453 PetscCall(TSGetDM(ts, &dm)); 1454 PetscCall(DMTSSetI2Jacobian(dm, jac, ctx)); 1455 PetscFunctionReturn(PETSC_SUCCESS); 1456 } 1457 1458 /*@C 1459 TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep. 1460 1461 Not Collective, but parallel objects are returned if `TS` is parallel 1462 1463 Input Parameter: 1464 . ts - The `TS` context obtained from `TSCreate()` 1465 1466 Output Parameters: 1467 + J - The (approximate) Jacobian of F(t,U,U_t,U_tt) 1468 . P - The matrix from which the preconditioner is constructed, often the same as `J` 1469 . jac - The function to compute the Jacobian matrices 1470 - ctx - User-defined context for Jacobian evaluation routine 1471 1472 Level: advanced 1473 1474 Note: 1475 You can pass in `NULL` for any return argument you do not need. 1476 1477 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`, `TSSetI2Jacobian()`, `TSGetI2Function()`, `TSCreate()` 1478 @*/ 1479 PetscErrorCode TSGetI2Jacobian(TS ts, Mat *J, Mat *P, TSI2JacobianFn **jac, void **ctx) 1480 { 1481 SNES snes; 1482 DM dm; 1483 1484 PetscFunctionBegin; 1485 PetscCall(TSGetSNES(ts, &snes)); 1486 PetscCall(SNESSetUpMatrices(snes)); 1487 PetscCall(SNESGetJacobian(snes, J, P, NULL, NULL)); 1488 PetscCall(TSGetDM(ts, &dm)); 1489 PetscCall(DMTSGetI2Jacobian(dm, jac, ctx)); 1490 PetscFunctionReturn(PETSC_SUCCESS); 1491 } 1492 1493 /*@ 1494 TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0 1495 1496 Collective 1497 1498 Input Parameters: 1499 + ts - the `TS` context 1500 . t - current time 1501 . U - state vector 1502 . V - time derivative of state vector (U_t) 1503 - A - second time derivative of state vector (U_tt) 1504 1505 Output Parameter: 1506 . F - the residual vector 1507 1508 Level: developer 1509 1510 Note: 1511 Most users should not need to explicitly call this routine, as it 1512 is used internally within the nonlinear solvers. 1513 1514 .seealso: [](ch_ts), `TS`, `TSSetI2Function()`, `TSGetI2Function()` 1515 @*/ 1516 PetscErrorCode TSComputeI2Function(TS ts, PetscReal t, Vec U, Vec V, Vec A, Vec F) 1517 { 1518 DM dm; 1519 TSI2FunctionFn *I2Function; 1520 void *ctx; 1521 TSRHSFunctionFn *rhsfunction; 1522 1523 PetscFunctionBegin; 1524 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1525 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 1526 PetscValidHeaderSpecific(V, VEC_CLASSID, 4); 1527 PetscValidHeaderSpecific(A, VEC_CLASSID, 5); 1528 PetscValidHeaderSpecific(F, VEC_CLASSID, 6); 1529 1530 PetscCall(TSGetDM(ts, &dm)); 1531 PetscCall(DMTSGetI2Function(dm, &I2Function, &ctx)); 1532 PetscCall(DMTSGetRHSFunction(dm, &rhsfunction, NULL)); 1533 1534 if (!I2Function) { 1535 PetscCall(TSComputeIFunction(ts, t, U, A, F, PETSC_FALSE)); 1536 PetscFunctionReturn(PETSC_SUCCESS); 1537 } 1538 1539 PetscCall(PetscLogEventBegin(TS_FunctionEval, U, ts, V, F)); 1540 1541 PetscCallBack("TS callback implicit function", I2Function(ts, t, U, V, A, F, ctx)); 1542 1543 if (rhsfunction) { 1544 Vec Frhs; 1545 1546 PetscCall(DMGetGlobalVector(dm, &Frhs)); 1547 PetscCall(TSComputeRHSFunction(ts, t, U, Frhs)); 1548 PetscCall(VecAXPY(F, -1, Frhs)); 1549 PetscCall(DMRestoreGlobalVector(dm, &Frhs)); 1550 } 1551 1552 PetscCall(PetscLogEventEnd(TS_FunctionEval, U, ts, V, F)); 1553 PetscFunctionReturn(PETSC_SUCCESS); 1554 } 1555 1556 /*@ 1557 TSComputeI2Jacobian - Evaluates the Jacobian of the DAE 1558 1559 Collective 1560 1561 Input Parameters: 1562 + ts - the `TS` context 1563 . t - current timestep 1564 . U - state vector 1565 . V - time derivative of state vector 1566 . A - second time derivative of state vector 1567 . shiftV - shift to apply, see note below 1568 - shiftA - shift to apply, see note below 1569 1570 Output Parameters: 1571 + J - Jacobian matrix 1572 - P - optional preconditioning matrix 1573 1574 Level: developer 1575 1576 Notes: 1577 If F(t,U,V,A)=0 is the DAE, the required Jacobian is 1578 1579 dF/dU + shiftV*dF/dV + shiftA*dF/dA 1580 1581 Most users should not need to explicitly call this routine, as it 1582 is used internally within the nonlinear solvers. 1583 1584 .seealso: [](ch_ts), `TS`, `TSSetI2Jacobian()` 1585 @*/ 1586 PetscErrorCode TSComputeI2Jacobian(TS ts, PetscReal t, Vec U, Vec V, Vec A, PetscReal shiftV, PetscReal shiftA, Mat J, Mat P) 1587 { 1588 DM dm; 1589 TSI2JacobianFn *I2Jacobian; 1590 void *ctx; 1591 TSRHSJacobianFn *rhsjacobian; 1592 1593 PetscFunctionBegin; 1594 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1595 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 1596 PetscValidHeaderSpecific(V, VEC_CLASSID, 4); 1597 PetscValidHeaderSpecific(A, VEC_CLASSID, 5); 1598 PetscValidHeaderSpecific(J, MAT_CLASSID, 8); 1599 PetscValidHeaderSpecific(P, MAT_CLASSID, 9); 1600 1601 PetscCall(TSGetDM(ts, &dm)); 1602 PetscCall(DMTSGetI2Jacobian(dm, &I2Jacobian, &ctx)); 1603 PetscCall(DMTSGetRHSJacobian(dm, &rhsjacobian, NULL)); 1604 1605 if (!I2Jacobian) { 1606 PetscCall(TSComputeIJacobian(ts, t, U, A, shiftA, J, P, PETSC_FALSE)); 1607 PetscFunctionReturn(PETSC_SUCCESS); 1608 } 1609 1610 PetscCall(PetscLogEventBegin(TS_JacobianEval, U, ts, J, P)); 1611 PetscCallBack("TS callback implicit Jacobian", I2Jacobian(ts, t, U, V, A, shiftV, shiftA, J, P, ctx)); 1612 if (rhsjacobian) { 1613 Mat Jrhs, Prhs; 1614 PetscCall(TSGetRHSMats_Private(ts, &Jrhs, &Prhs)); 1615 PetscCall(TSComputeRHSJacobian(ts, t, U, Jrhs, Prhs)); 1616 PetscCall(MatAXPY(J, -1, Jrhs, ts->axpy_pattern)); 1617 if (P != J) PetscCall(MatAXPY(P, -1, Prhs, ts->axpy_pattern)); 1618 } 1619 1620 PetscCall(PetscLogEventEnd(TS_JacobianEval, U, ts, J, P)); 1621 PetscFunctionReturn(PETSC_SUCCESS); 1622 } 1623 1624 /*@C 1625 TSSetTransientVariable - sets function to transform from state to transient variables 1626 1627 Logically Collective 1628 1629 Input Parameters: 1630 + ts - time stepping context on which to change the transient variable 1631 . tvar - a function that transforms to transient variables, see `TSTransientVariableFn` for the calling sequence 1632 - ctx - a context for tvar 1633 1634 Level: advanced 1635 1636 Notes: 1637 This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., `TSBDF`) 1638 can be conservative. In this context, primitive variables P are used to model the state (e.g., because they lead to 1639 well-conditioned formulations even in limiting cases such as low-Mach or zero porosity). The transient variable is 1640 C(P), specified by calling this function. An IFunction thus receives arguments (P, Cdot) and the IJacobian must be 1641 evaluated via the chain rule, as in 1642 .vb 1643 dF/dP + shift * dF/dCdot dC/dP. 1644 .ve 1645 1646 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSTransientVariableFn`, `DMTSSetTransientVariable()`, `DMTSGetTransientVariable()`, `TSSetIFunction()`, `TSSetIJacobian()` 1647 @*/ 1648 PetscErrorCode TSSetTransientVariable(TS ts, TSTransientVariableFn *tvar, void *ctx) 1649 { 1650 DM dm; 1651 1652 PetscFunctionBegin; 1653 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1654 PetscCall(TSGetDM(ts, &dm)); 1655 PetscCall(DMTSSetTransientVariable(dm, tvar, ctx)); 1656 PetscFunctionReturn(PETSC_SUCCESS); 1657 } 1658 1659 /*@ 1660 TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables 1661 1662 Logically Collective 1663 1664 Input Parameters: 1665 + ts - TS on which to compute 1666 - U - state vector to be transformed to transient variables 1667 1668 Output Parameter: 1669 . C - transient (conservative) variable 1670 1671 Level: developer 1672 1673 Developer Notes: 1674 If `DMTSSetTransientVariable()` has not been called, then C is not modified in this routine and C = `NULL` is allowed. 1675 This makes it safe to call without a guard. One can use `TSHasTransientVariable()` to check if transient variables are 1676 being used. 1677 1678 .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeIFunction()`, `TSComputeIJacobian()` 1679 @*/ 1680 PetscErrorCode TSComputeTransientVariable(TS ts, Vec U, Vec C) 1681 { 1682 DM dm; 1683 DMTS dmts; 1684 1685 PetscFunctionBegin; 1686 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1687 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 1688 PetscCall(TSGetDM(ts, &dm)); 1689 PetscCall(DMGetDMTS(dm, &dmts)); 1690 if (dmts->ops->transientvar) { 1691 PetscValidHeaderSpecific(C, VEC_CLASSID, 3); 1692 PetscCall((*dmts->ops->transientvar)(ts, U, C, dmts->transientvarctx)); 1693 } 1694 PetscFunctionReturn(PETSC_SUCCESS); 1695 } 1696 1697 /*@ 1698 TSHasTransientVariable - determine whether transient variables have been set 1699 1700 Logically Collective 1701 1702 Input Parameter: 1703 . ts - `TS` on which to compute 1704 1705 Output Parameter: 1706 . has - `PETSC_TRUE` if transient variables have been set 1707 1708 Level: developer 1709 1710 .seealso: [](ch_ts), `TS`, `TSBDF`, `DMTSSetTransientVariable()`, `TSComputeTransientVariable()` 1711 @*/ 1712 PetscErrorCode TSHasTransientVariable(TS ts, PetscBool *has) 1713 { 1714 DM dm; 1715 DMTS dmts; 1716 1717 PetscFunctionBegin; 1718 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1719 PetscCall(TSGetDM(ts, &dm)); 1720 PetscCall(DMGetDMTS(dm, &dmts)); 1721 *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE; 1722 PetscFunctionReturn(PETSC_SUCCESS); 1723 } 1724 1725 /*@ 1726 TS2SetSolution - Sets the initial solution and time derivative vectors 1727 for use by the `TS` routines handling second order equations. 1728 1729 Logically Collective 1730 1731 Input Parameters: 1732 + ts - the `TS` context obtained from `TSCreate()` 1733 . u - the solution vector 1734 - v - the time derivative vector 1735 1736 Level: beginner 1737 1738 .seealso: [](ch_ts), `TS` 1739 @*/ 1740 PetscErrorCode TS2SetSolution(TS ts, Vec u, Vec v) 1741 { 1742 PetscFunctionBegin; 1743 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1744 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 1745 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 1746 PetscCall(TSSetSolution(ts, u)); 1747 PetscCall(PetscObjectReference((PetscObject)v)); 1748 PetscCall(VecDestroy(&ts->vec_dot)); 1749 ts->vec_dot = v; 1750 PetscFunctionReturn(PETSC_SUCCESS); 1751 } 1752 1753 /*@ 1754 TS2GetSolution - Returns the solution and time derivative at the present timestep 1755 for second order equations. 1756 1757 Not Collective 1758 1759 Input Parameter: 1760 . ts - the `TS` context obtained from `TSCreate()` 1761 1762 Output Parameters: 1763 + u - the vector containing the solution 1764 - v - the vector containing the time derivative 1765 1766 Level: intermediate 1767 1768 Notes: 1769 It is valid to call this routine inside the function 1770 that you are evaluating in order to move to the new timestep. This vector not 1771 changed until the solution at the next timestep has been calculated. 1772 1773 .seealso: [](ch_ts), `TS`, `TS2SetSolution()`, `TSGetTimeStep()`, `TSGetTime()` 1774 @*/ 1775 PetscErrorCode TS2GetSolution(TS ts, Vec *u, Vec *v) 1776 { 1777 PetscFunctionBegin; 1778 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1779 if (u) PetscAssertPointer(u, 2); 1780 if (v) PetscAssertPointer(v, 3); 1781 if (u) *u = ts->vec_sol; 1782 if (v) *v = ts->vec_dot; 1783 PetscFunctionReturn(PETSC_SUCCESS); 1784 } 1785 1786 /*@ 1787 TSLoad - Loads a `TS` that has been stored in binary with `TSView()`. 1788 1789 Collective 1790 1791 Input Parameters: 1792 + ts - the newly loaded `TS`, this needs to have been created with `TSCreate()` or 1793 some related function before a call to `TSLoad()`. 1794 - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` 1795 1796 Level: intermediate 1797 1798 Note: 1799 The type is determined by the data in the file, any type set into the `TS` before this call is ignored. 1800 1801 .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerBinaryOpen()`, `TSView()`, `MatLoad()`, `VecLoad()` 1802 @*/ 1803 PetscErrorCode TSLoad(TS ts, PetscViewer viewer) 1804 { 1805 PetscBool isbinary; 1806 PetscInt classid; 1807 char type[256]; 1808 DMTS sdm; 1809 DM dm; 1810 1811 PetscFunctionBegin; 1812 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1813 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1814 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 1815 PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 1816 1817 PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT)); 1818 PetscCheck(classid == TS_FILE_CLASSID, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Not TS next in file"); 1819 PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR)); 1820 PetscCall(TSSetType(ts, type)); 1821 PetscTryTypeMethod(ts, load, viewer); 1822 PetscCall(DMCreate(PetscObjectComm((PetscObject)ts), &dm)); 1823 PetscCall(DMLoad(dm, viewer)); 1824 PetscCall(TSSetDM(ts, dm)); 1825 PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol)); 1826 PetscCall(VecLoad(ts->vec_sol, viewer)); 1827 PetscCall(DMGetDMTS(ts->dm, &sdm)); 1828 PetscCall(DMTSLoad(sdm, viewer)); 1829 PetscFunctionReturn(PETSC_SUCCESS); 1830 } 1831 1832 #include <petscdraw.h> 1833 #if defined(PETSC_HAVE_SAWS) 1834 #include <petscviewersaws.h> 1835 #endif 1836 1837 /*@ 1838 TSViewFromOptions - View a `TS` based on values in the options database 1839 1840 Collective 1841 1842 Input Parameters: 1843 + ts - the `TS` context 1844 . obj - Optional object that provides the prefix for the options database keys 1845 - name - command line option string to be passed by user 1846 1847 Level: intermediate 1848 1849 .seealso: [](ch_ts), `TS`, `TSView`, `PetscObjectViewFromOptions()`, `TSCreate()` 1850 @*/ 1851 PetscErrorCode TSViewFromOptions(TS ts, PetscObject obj, const char name[]) 1852 { 1853 PetscFunctionBegin; 1854 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1855 PetscCall(PetscObjectViewFromOptions((PetscObject)ts, obj, name)); 1856 PetscFunctionReturn(PETSC_SUCCESS); 1857 } 1858 1859 /*@ 1860 TSView - Prints the `TS` data structure. 1861 1862 Collective 1863 1864 Input Parameters: 1865 + ts - the `TS` context obtained from `TSCreate()` 1866 - viewer - visualization context 1867 1868 Options Database Key: 1869 . -ts_view - calls `TSView()` at end of `TSStep()` 1870 1871 Level: beginner 1872 1873 Notes: 1874 The available visualization contexts include 1875 + `PETSC_VIEWER_STDOUT_SELF` - standard output (default) 1876 - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard 1877 output where only the first processor opens 1878 the file. All other processors send their 1879 data to the first processor to print. 1880 1881 The user can open an alternative visualization context with 1882 `PetscViewerASCIIOpen()` - output to a specified file. 1883 1884 In the debugger you can do call `TSView`(ts,0) to display the `TS` solver. (The same holds for any PETSc object viewer). 1885 1886 .seealso: [](ch_ts), `TS`, `PetscViewer`, `PetscViewerASCIIOpen()` 1887 @*/ 1888 PetscErrorCode TSView(TS ts, PetscViewer viewer) 1889 { 1890 TSType type; 1891 PetscBool iascii, isstring, isundials, isbinary, isdraw; 1892 DMTS sdm; 1893 #if defined(PETSC_HAVE_SAWS) 1894 PetscBool issaws; 1895 #endif 1896 1897 PetscFunctionBegin; 1898 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 1899 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts), &viewer)); 1900 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1901 PetscCheckSameComm(ts, 1, viewer, 2); 1902 1903 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 1904 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1905 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 1906 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 1907 #if defined(PETSC_HAVE_SAWS) 1908 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1909 #endif 1910 if (iascii) { 1911 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ts, viewer)); 1912 if (ts->ops->view) { 1913 PetscCall(PetscViewerASCIIPushTab(viewer)); 1914 PetscUseTypeMethod(ts, view, viewer); 1915 PetscCall(PetscViewerASCIIPopTab(viewer)); 1916 } 1917 if (ts->max_steps < PETSC_MAX_INT) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum steps=%" PetscInt_FMT "\n", ts->max_steps)); 1918 if (ts->max_time < PETSC_MAX_REAL) PetscCall(PetscViewerASCIIPrintf(viewer, " maximum time=%g\n", (double)ts->max_time)); 1919 if (ts->ifuncs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of I function evaluations=%" PetscInt_FMT "\n", ts->ifuncs)); 1920 if (ts->ijacs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of I Jacobian evaluations=%" PetscInt_FMT "\n", ts->ijacs)); 1921 if (ts->rhsfuncs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of RHS function evaluations=%" PetscInt_FMT "\n", ts->rhsfuncs)); 1922 if (ts->rhsjacs) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of RHS Jacobian evaluations=%" PetscInt_FMT "\n", ts->rhsjacs)); 1923 if (ts->usessnes) { 1924 PetscBool lin; 1925 if (ts->problem_type == TS_NONLINEAR) PetscCall(PetscViewerASCIIPrintf(viewer, " total number of nonlinear solver iterations=%" PetscInt_FMT "\n", ts->snes_its)); 1926 PetscCall(PetscViewerASCIIPrintf(viewer, " total number of linear solver iterations=%" PetscInt_FMT "\n", ts->ksp_its)); 1927 PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes, &lin, SNESKSPONLY, SNESKSPTRANSPOSEONLY, "")); 1928 PetscCall(PetscViewerASCIIPrintf(viewer, " total number of %slinear solve failures=%" PetscInt_FMT "\n", lin ? "" : "non", ts->num_snes_failures)); 1929 } 1930 PetscCall(PetscViewerASCIIPrintf(viewer, " total number of rejected steps=%" PetscInt_FMT "\n", ts->reject)); 1931 if (ts->vrtol) PetscCall(PetscViewerASCIIPrintf(viewer, " using vector of relative error tolerances, ")); 1932 else PetscCall(PetscViewerASCIIPrintf(viewer, " using relative error tolerance of %g, ", (double)ts->rtol)); 1933 if (ts->vatol) PetscCall(PetscViewerASCIIPrintf(viewer, " using vector of absolute error tolerances\n")); 1934 else PetscCall(PetscViewerASCIIPrintf(viewer, " using absolute error tolerance of %g\n", (double)ts->atol)); 1935 PetscCall(PetscViewerASCIIPushTab(viewer)); 1936 PetscCall(TSAdaptView(ts->adapt, viewer)); 1937 PetscCall(PetscViewerASCIIPopTab(viewer)); 1938 } else if (isstring) { 1939 PetscCall(TSGetType(ts, &type)); 1940 PetscCall(PetscViewerStringSPrintf(viewer, " TSType: %-7.7s", type)); 1941 PetscTryTypeMethod(ts, view, viewer); 1942 } else if (isbinary) { 1943 PetscInt classid = TS_FILE_CLASSID; 1944 MPI_Comm comm; 1945 PetscMPIInt rank; 1946 char type[256]; 1947 1948 PetscCall(PetscObjectGetComm((PetscObject)ts, &comm)); 1949 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1950 if (rank == 0) { 1951 PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT)); 1952 PetscCall(PetscStrncpy(type, ((PetscObject)ts)->type_name, 256)); 1953 PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR)); 1954 } 1955 PetscTryTypeMethod(ts, view, viewer); 1956 if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer)); 1957 PetscCall(DMView(ts->dm, viewer)); 1958 PetscCall(VecView(ts->vec_sol, viewer)); 1959 PetscCall(DMGetDMTS(ts->dm, &sdm)); 1960 PetscCall(DMTSView(sdm, viewer)); 1961 } else if (isdraw) { 1962 PetscDraw draw; 1963 char str[36]; 1964 PetscReal x, y, bottom, h; 1965 1966 PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 1967 PetscCall(PetscDrawGetCurrentPoint(draw, &x, &y)); 1968 PetscCall(PetscStrncpy(str, "TS: ", sizeof(str))); 1969 PetscCall(PetscStrlcat(str, ((PetscObject)ts)->type_name, sizeof(str))); 1970 PetscCall(PetscDrawStringBoxed(draw, x, y, PETSC_DRAW_BLACK, PETSC_DRAW_BLACK, str, NULL, &h)); 1971 bottom = y - h; 1972 PetscCall(PetscDrawPushCurrentPoint(draw, x, bottom)); 1973 PetscTryTypeMethod(ts, view, viewer); 1974 if (ts->adapt) PetscCall(TSAdaptView(ts->adapt, viewer)); 1975 if (ts->snes) PetscCall(SNESView(ts->snes, viewer)); 1976 PetscCall(PetscDrawPopCurrentPoint(draw)); 1977 #if defined(PETSC_HAVE_SAWS) 1978 } else if (issaws) { 1979 PetscMPIInt rank; 1980 const char *name; 1981 1982 PetscCall(PetscObjectGetName((PetscObject)ts, &name)); 1983 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1984 if (!((PetscObject)ts)->amsmem && rank == 0) { 1985 char dir[1024]; 1986 1987 PetscCall(PetscObjectViewSAWs((PetscObject)ts, viewer)); 1988 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time_step", name)); 1989 PetscCallSAWs(SAWs_Register, (dir, &ts->steps, 1, SAWs_READ, SAWs_INT)); 1990 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Objects/%s/time", name)); 1991 PetscCallSAWs(SAWs_Register, (dir, &ts->ptime, 1, SAWs_READ, SAWs_DOUBLE)); 1992 } 1993 PetscTryTypeMethod(ts, view, viewer); 1994 #endif 1995 } 1996 if (ts->snes && ts->usessnes) { 1997 PetscCall(PetscViewerASCIIPushTab(viewer)); 1998 PetscCall(SNESView(ts->snes, viewer)); 1999 PetscCall(PetscViewerASCIIPopTab(viewer)); 2000 } 2001 PetscCall(DMGetDMTS(ts->dm, &sdm)); 2002 PetscCall(DMTSView(sdm, viewer)); 2003 2004 PetscCall(PetscViewerASCIIPushTab(viewer)); 2005 PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSSUNDIALS, &isundials)); 2006 PetscCall(PetscViewerASCIIPopTab(viewer)); 2007 PetscFunctionReturn(PETSC_SUCCESS); 2008 } 2009 2010 /*@ 2011 TSSetApplicationContext - Sets an optional user-defined context for 2012 the timesteppers. 2013 2014 Logically Collective 2015 2016 Input Parameters: 2017 + ts - the `TS` context obtained from `TSCreate()` 2018 - usrP - user context 2019 2020 Level: intermediate 2021 2022 Fortran Notes: 2023 You must write a Fortran interface definition for this 2024 function that tells Fortran the Fortran derived data type that you are passing in as the `ctx` argument. 2025 2026 .seealso: [](ch_ts), `TS`, `TSGetApplicationContext()` 2027 @*/ 2028 PetscErrorCode TSSetApplicationContext(TS ts, void *usrP) 2029 { 2030 PetscFunctionBegin; 2031 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2032 ts->user = usrP; 2033 PetscFunctionReturn(PETSC_SUCCESS); 2034 } 2035 2036 /*@ 2037 TSGetApplicationContext - Gets the user-defined context for the 2038 timestepper that was set with `TSSetApplicationContext()` 2039 2040 Not Collective 2041 2042 Input Parameter: 2043 . ts - the `TS` context obtained from `TSCreate()` 2044 2045 Output Parameter: 2046 . usrP - user context 2047 2048 Level: intermediate 2049 2050 Fortran Notes: 2051 You must write a Fortran interface definition for this 2052 function that tells Fortran the Fortran derived data type that you are passing in as the `ctx` argument. 2053 2054 .seealso: [](ch_ts), `TS`, `TSSetApplicationContext()` 2055 @*/ 2056 PetscErrorCode TSGetApplicationContext(TS ts, void *usrP) 2057 { 2058 PetscFunctionBegin; 2059 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2060 *(void **)usrP = ts->user; 2061 PetscFunctionReturn(PETSC_SUCCESS); 2062 } 2063 2064 /*@ 2065 TSGetStepNumber - Gets the number of time steps completed. 2066 2067 Not Collective 2068 2069 Input Parameter: 2070 . ts - the `TS` context obtained from `TSCreate()` 2071 2072 Output Parameter: 2073 . steps - number of steps completed so far 2074 2075 Level: intermediate 2076 2077 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetTimeStep()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()` 2078 @*/ 2079 PetscErrorCode TSGetStepNumber(TS ts, PetscInt *steps) 2080 { 2081 PetscFunctionBegin; 2082 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2083 PetscAssertPointer(steps, 2); 2084 *steps = ts->steps; 2085 PetscFunctionReturn(PETSC_SUCCESS); 2086 } 2087 2088 /*@ 2089 TSSetStepNumber - Sets the number of steps completed. 2090 2091 Logically Collective 2092 2093 Input Parameters: 2094 + ts - the `TS` context 2095 - steps - number of steps completed so far 2096 2097 Level: developer 2098 2099 Note: 2100 For most uses of the `TS` solvers the user need not explicitly call 2101 `TSSetStepNumber()`, as the step counter is appropriately updated in 2102 `TSSolve()`/`TSStep()`/`TSRollBack()`. Power users may call this routine to 2103 reinitialize timestepping by setting the step counter to zero (and time 2104 to the initial time) to solve a similar problem with different initial 2105 conditions or parameters. Other possible use case is to continue 2106 timestepping from a previously interrupted run in such a way that `TS` 2107 monitors will be called with a initial nonzero step counter. 2108 2109 .seealso: [](ch_ts), `TS`, `TSGetStepNumber()`, `TSSetTime()`, `TSSetTimeStep()`, `TSSetSolution()` 2110 @*/ 2111 PetscErrorCode TSSetStepNumber(TS ts, PetscInt steps) 2112 { 2113 PetscFunctionBegin; 2114 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2115 PetscValidLogicalCollectiveInt(ts, steps, 2); 2116 PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Step number must be non-negative"); 2117 ts->steps = steps; 2118 PetscFunctionReturn(PETSC_SUCCESS); 2119 } 2120 2121 /*@ 2122 TSSetTimeStep - Allows one to reset the timestep at any time, 2123 useful for simple pseudo-timestepping codes. 2124 2125 Logically Collective 2126 2127 Input Parameters: 2128 + ts - the `TS` context obtained from `TSCreate()` 2129 - time_step - the size of the timestep 2130 2131 Level: intermediate 2132 2133 .seealso: [](ch_ts), `TS`, `TSPSEUDO`, `TSGetTimeStep()`, `TSSetTime()` 2134 @*/ 2135 PetscErrorCode TSSetTimeStep(TS ts, PetscReal time_step) 2136 { 2137 PetscFunctionBegin; 2138 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2139 PetscValidLogicalCollectiveReal(ts, time_step, 2); 2140 ts->time_step = time_step; 2141 PetscFunctionReturn(PETSC_SUCCESS); 2142 } 2143 2144 /*@ 2145 TSSetExactFinalTime - Determines whether to adapt the final time step to 2146 match the exact final time, interpolate solution to the exact final time, 2147 or just return at the final time `TS` computed. 2148 2149 Logically Collective 2150 2151 Input Parameters: 2152 + ts - the time-step context 2153 - eftopt - exact final time option 2154 .vb 2155 TS_EXACTFINALTIME_STEPOVER - Don't do anything if final time is exceeded 2156 TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time 2157 TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to match the final time 2158 .ve 2159 2160 Options Database Key: 2161 . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step at runtime 2162 2163 Level: beginner 2164 2165 Note: 2166 If you use the option `TS_EXACTFINALTIME_STEPOVER` the solution may be at a very different time 2167 then the final time you selected. 2168 2169 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSGetExactFinalTime()` 2170 @*/ 2171 PetscErrorCode TSSetExactFinalTime(TS ts, TSExactFinalTimeOption eftopt) 2172 { 2173 PetscFunctionBegin; 2174 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2175 PetscValidLogicalCollectiveEnum(ts, eftopt, 2); 2176 ts->exact_final_time = eftopt; 2177 PetscFunctionReturn(PETSC_SUCCESS); 2178 } 2179 2180 /*@ 2181 TSGetExactFinalTime - Gets the exact final time option set with `TSSetExactFinalTime()` 2182 2183 Not Collective 2184 2185 Input Parameter: 2186 . ts - the `TS` context 2187 2188 Output Parameter: 2189 . eftopt - exact final time option 2190 2191 Level: beginner 2192 2193 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSSetExactFinalTime()` 2194 @*/ 2195 PetscErrorCode TSGetExactFinalTime(TS ts, TSExactFinalTimeOption *eftopt) 2196 { 2197 PetscFunctionBegin; 2198 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2199 PetscAssertPointer(eftopt, 2); 2200 *eftopt = ts->exact_final_time; 2201 PetscFunctionReturn(PETSC_SUCCESS); 2202 } 2203 2204 /*@ 2205 TSGetTimeStep - Gets the current timestep size. 2206 2207 Not Collective 2208 2209 Input Parameter: 2210 . ts - the `TS` context obtained from `TSCreate()` 2211 2212 Output Parameter: 2213 . dt - the current timestep size 2214 2215 Level: intermediate 2216 2217 .seealso: [](ch_ts), `TS`, `TSSetTimeStep()`, `TSGetTime()` 2218 @*/ 2219 PetscErrorCode TSGetTimeStep(TS ts, PetscReal *dt) 2220 { 2221 PetscFunctionBegin; 2222 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2223 PetscAssertPointer(dt, 2); 2224 *dt = ts->time_step; 2225 PetscFunctionReturn(PETSC_SUCCESS); 2226 } 2227 2228 /*@ 2229 TSGetSolution - Returns the solution at the present timestep. It 2230 is valid to call this routine inside the function that you are evaluating 2231 in order to move to the new timestep. This vector not changed until 2232 the solution at the next timestep has been calculated. 2233 2234 Not Collective, but v returned is parallel if ts is parallel 2235 2236 Input Parameter: 2237 . ts - the `TS` context obtained from `TSCreate()` 2238 2239 Output Parameter: 2240 . v - the vector containing the solution 2241 2242 Level: intermediate 2243 2244 Note: 2245 If you used `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`); this does not return the solution at the requested 2246 final time. It returns the solution at the next timestep. 2247 2248 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()` 2249 @*/ 2250 PetscErrorCode TSGetSolution(TS ts, Vec *v) 2251 { 2252 PetscFunctionBegin; 2253 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2254 PetscAssertPointer(v, 2); 2255 *v = ts->vec_sol; 2256 PetscFunctionReturn(PETSC_SUCCESS); 2257 } 2258 2259 /*@ 2260 TSGetSolutionComponents - Returns any solution components at the present 2261 timestep, if available for the time integration method being used. 2262 Solution components are quantities that share the same size and 2263 structure as the solution vector. 2264 2265 Not Collective, but v returned is parallel if ts is parallel 2266 2267 Input Parameters: 2268 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2269 . n - If v is `NULL`, then the number of solution components is 2270 returned through n, else the n-th solution component is 2271 returned in v. 2272 - v - the vector containing the n-th solution component 2273 (may be `NULL` to use this function to find out 2274 the number of solutions components). 2275 2276 Level: advanced 2277 2278 .seealso: [](ch_ts), `TS`, `TSGetSolution()` 2279 @*/ 2280 PetscErrorCode TSGetSolutionComponents(TS ts, PetscInt *n, Vec *v) 2281 { 2282 PetscFunctionBegin; 2283 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2284 if (!ts->ops->getsolutioncomponents) *n = 0; 2285 else PetscUseTypeMethod(ts, getsolutioncomponents, n, v); 2286 PetscFunctionReturn(PETSC_SUCCESS); 2287 } 2288 2289 /*@ 2290 TSGetAuxSolution - Returns an auxiliary solution at the present 2291 timestep, if available for the time integration method being used. 2292 2293 Not Collective, but v returned is parallel if ts is parallel 2294 2295 Input Parameters: 2296 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2297 - v - the vector containing the auxiliary solution 2298 2299 Level: intermediate 2300 2301 .seealso: [](ch_ts), `TS`, `TSGetSolution()` 2302 @*/ 2303 PetscErrorCode TSGetAuxSolution(TS ts, Vec *v) 2304 { 2305 PetscFunctionBegin; 2306 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2307 if (ts->ops->getauxsolution) PetscUseTypeMethod(ts, getauxsolution, v); 2308 else PetscCall(VecZeroEntries(*v)); 2309 PetscFunctionReturn(PETSC_SUCCESS); 2310 } 2311 2312 /*@ 2313 TSGetTimeError - Returns the estimated error vector, if the chosen 2314 `TSType` has an error estimation functionality and `TSSetTimeError()` was called 2315 2316 Not Collective, but v returned is parallel if ts is parallel 2317 2318 Input Parameters: 2319 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2320 . n - current estimate (n=0) or previous one (n=-1) 2321 - v - the vector containing the error (same size as the solution). 2322 2323 Level: intermediate 2324 2325 Note: 2326 MUST call after `TSSetUp()` 2327 2328 .seealso: [](ch_ts), `TSGetSolution()`, `TSSetTimeError()` 2329 @*/ 2330 PetscErrorCode TSGetTimeError(TS ts, PetscInt n, Vec *v) 2331 { 2332 PetscFunctionBegin; 2333 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2334 if (ts->ops->gettimeerror) PetscUseTypeMethod(ts, gettimeerror, n, v); 2335 else PetscCall(VecZeroEntries(*v)); 2336 PetscFunctionReturn(PETSC_SUCCESS); 2337 } 2338 2339 /*@ 2340 TSSetTimeError - Sets the estimated error vector, if the chosen 2341 `TSType` has an error estimation functionality. This can be used 2342 to restart such a time integrator with a given error vector. 2343 2344 Not Collective, but v returned is parallel if ts is parallel 2345 2346 Input Parameters: 2347 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2348 - v - the vector containing the error (same size as the solution). 2349 2350 Level: intermediate 2351 2352 .seealso: [](ch_ts), `TS`, `TSSetSolution()`, `TSGetTimeError()` 2353 @*/ 2354 PetscErrorCode TSSetTimeError(TS ts, Vec v) 2355 { 2356 PetscFunctionBegin; 2357 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2358 PetscCheck(ts->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetUp() first"); 2359 PetscTryTypeMethod(ts, settimeerror, v); 2360 PetscFunctionReturn(PETSC_SUCCESS); 2361 } 2362 2363 /* ----- Routines to initialize and destroy a timestepper ---- */ 2364 /*@ 2365 TSSetProblemType - Sets the type of problem to be solved. 2366 2367 Not collective 2368 2369 Input Parameters: 2370 + ts - The `TS` 2371 - type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms 2372 .vb 2373 U_t - A U = 0 (linear) 2374 U_t - A(t) U = 0 (linear) 2375 F(t,U,U_t) = 0 (nonlinear) 2376 .ve 2377 2378 Level: beginner 2379 2380 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS` 2381 @*/ 2382 PetscErrorCode TSSetProblemType(TS ts, TSProblemType type) 2383 { 2384 PetscFunctionBegin; 2385 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2386 ts->problem_type = type; 2387 if (type == TS_LINEAR) { 2388 SNES snes; 2389 PetscCall(TSGetSNES(ts, &snes)); 2390 PetscCall(SNESSetType(snes, SNESKSPONLY)); 2391 } 2392 PetscFunctionReturn(PETSC_SUCCESS); 2393 } 2394 2395 /*@ 2396 TSGetProblemType - Gets the type of problem to be solved. 2397 2398 Not collective 2399 2400 Input Parameter: 2401 . ts - The `TS` 2402 2403 Output Parameter: 2404 . type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms 2405 .vb 2406 M U_t = A U 2407 M(t) U_t = A(t) U 2408 F(t,U,U_t) 2409 .ve 2410 2411 Level: beginner 2412 2413 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS` 2414 @*/ 2415 PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type) 2416 { 2417 PetscFunctionBegin; 2418 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2419 PetscAssertPointer(type, 2); 2420 *type = ts->problem_type; 2421 PetscFunctionReturn(PETSC_SUCCESS); 2422 } 2423 2424 /* 2425 Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp() 2426 */ 2427 static PetscErrorCode TSSetExactFinalTimeDefault(TS ts) 2428 { 2429 PetscBool isnone; 2430 2431 PetscFunctionBegin; 2432 PetscCall(TSGetAdapt(ts, &ts->adapt)); 2433 PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type)); 2434 2435 PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &isnone)); 2436 if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP; 2437 else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE; 2438 PetscFunctionReturn(PETSC_SUCCESS); 2439 } 2440 2441 /*@ 2442 TSSetUp - Sets up the internal data structures for the later use of a timestepper. 2443 2444 Collective 2445 2446 Input Parameter: 2447 . ts - the `TS` context obtained from `TSCreate()` 2448 2449 Level: advanced 2450 2451 Note: 2452 For basic use of the `TS` solvers the user need not explicitly call 2453 `TSSetUp()`, since these actions will automatically occur during 2454 the call to `TSStep()` or `TSSolve()`. However, if one wishes to control this 2455 phase separately, `TSSetUp()` should be called after `TSCreate()` 2456 and optional routines of the form TSSetXXX(), but before `TSStep()` and `TSSolve()`. 2457 2458 .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSStep()`, `TSDestroy()`, `TSSolve()` 2459 @*/ 2460 PetscErrorCode TSSetUp(TS ts) 2461 { 2462 DM dm; 2463 PetscErrorCode (*func)(SNES, Vec, Vec, void *); 2464 PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *); 2465 TSIFunctionFn *ifun; 2466 TSIJacobianFn *ijac; 2467 TSI2JacobianFn *i2jac; 2468 TSRHSJacobianFn *rhsjac; 2469 2470 PetscFunctionBegin; 2471 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2472 if (ts->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 2473 2474 if (!((PetscObject)ts)->type_name) { 2475 PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL)); 2476 PetscCall(TSSetType(ts, ifun ? TSBEULER : TSEULER)); 2477 } 2478 2479 if (!ts->vec_sol) { 2480 PetscCheck(ts->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetSolution() first"); 2481 PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol)); 2482 } 2483 2484 if (ts->tspan) { 2485 if (!ts->tspan->vecs_sol) PetscCall(VecDuplicateVecs(ts->vec_sol, ts->tspan->num_span_times, &ts->tspan->vecs_sol)); 2486 } 2487 if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */ 2488 PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs)); 2489 ts->Jacp = ts->Jacprhs; 2490 } 2491 2492 if (ts->quadraturets) { 2493 PetscCall(TSSetUp(ts->quadraturets)); 2494 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2495 PetscCall(VecDuplicate(ts->quadraturets->vec_sol, &ts->vec_costintegrand)); 2496 } 2497 2498 PetscCall(TSGetRHSJacobian(ts, NULL, NULL, &rhsjac, NULL)); 2499 if (rhsjac == TSComputeRHSJacobianConstant) { 2500 Mat Amat, Pmat; 2501 SNES snes; 2502 PetscCall(TSGetSNES(ts, &snes)); 2503 PetscCall(SNESGetJacobian(snes, &Amat, &Pmat, NULL, NULL)); 2504 /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would 2505 * have displaced the RHS matrix */ 2506 if (Amat && Amat == ts->Arhs) { 2507 /* we need to copy the values of the matrix because for the constant Jacobian case the user will never set the numerical values in this new location */ 2508 PetscCall(MatDuplicate(ts->Arhs, MAT_COPY_VALUES, &Amat)); 2509 PetscCall(SNESSetJacobian(snes, Amat, NULL, NULL, NULL)); 2510 PetscCall(MatDestroy(&Amat)); 2511 } 2512 if (Pmat && Pmat == ts->Brhs) { 2513 PetscCall(MatDuplicate(ts->Brhs, MAT_COPY_VALUES, &Pmat)); 2514 PetscCall(SNESSetJacobian(snes, NULL, Pmat, NULL, NULL)); 2515 PetscCall(MatDestroy(&Pmat)); 2516 } 2517 } 2518 2519 PetscCall(TSGetAdapt(ts, &ts->adapt)); 2520 PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type)); 2521 2522 PetscTryTypeMethod(ts, setup); 2523 2524 PetscCall(TSSetExactFinalTimeDefault(ts)); 2525 2526 /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction 2527 to be set right but can't do it elsewhere due to the overreliance on ctx=ts. 2528 */ 2529 PetscCall(TSGetDM(ts, &dm)); 2530 PetscCall(DMSNESGetFunction(dm, &func, NULL)); 2531 if (!func) PetscCall(DMSNESSetFunction(dm, SNESTSFormFunction, ts)); 2532 2533 /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it. 2534 Otherwise, the SNES will use coloring internally to form the Jacobian. 2535 */ 2536 PetscCall(DMSNESGetJacobian(dm, &jac, NULL)); 2537 PetscCall(DMTSGetIJacobian(dm, &ijac, NULL)); 2538 PetscCall(DMTSGetI2Jacobian(dm, &i2jac, NULL)); 2539 PetscCall(DMTSGetRHSJacobian(dm, &rhsjac, NULL)); 2540 if (!jac && (ijac || i2jac || rhsjac)) PetscCall(DMSNESSetJacobian(dm, SNESTSFormJacobian, ts)); 2541 2542 /* if time integration scheme has a starting method, call it */ 2543 PetscTryTypeMethod(ts, startingmethod); 2544 2545 ts->setupcalled = PETSC_TRUE; 2546 PetscFunctionReturn(PETSC_SUCCESS); 2547 } 2548 2549 /*@ 2550 TSReset - Resets a `TS` context and removes any allocated `Vec`s and `Mat`s. 2551 2552 Collective 2553 2554 Input Parameter: 2555 . ts - the `TS` context obtained from `TSCreate()` 2556 2557 Level: beginner 2558 2559 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetup()`, `TSDestroy()` 2560 @*/ 2561 PetscErrorCode TSReset(TS ts) 2562 { 2563 TS_RHSSplitLink ilink = ts->tsrhssplit, next; 2564 2565 PetscFunctionBegin; 2566 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2567 2568 PetscTryTypeMethod(ts, reset); 2569 if (ts->snes) PetscCall(SNESReset(ts->snes)); 2570 if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt)); 2571 2572 PetscCall(MatDestroy(&ts->Arhs)); 2573 PetscCall(MatDestroy(&ts->Brhs)); 2574 PetscCall(VecDestroy(&ts->Frhs)); 2575 PetscCall(VecDestroy(&ts->vec_sol)); 2576 PetscCall(VecDestroy(&ts->vec_sol0)); 2577 PetscCall(VecDestroy(&ts->vec_dot)); 2578 PetscCall(VecDestroy(&ts->vatol)); 2579 PetscCall(VecDestroy(&ts->vrtol)); 2580 PetscCall(VecDestroyVecs(ts->nwork, &ts->work)); 2581 2582 PetscCall(MatDestroy(&ts->Jacprhs)); 2583 PetscCall(MatDestroy(&ts->Jacp)); 2584 if (ts->forward_solve) PetscCall(TSForwardReset(ts)); 2585 if (ts->quadraturets) { 2586 PetscCall(TSReset(ts->quadraturets)); 2587 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2588 } 2589 while (ilink) { 2590 next = ilink->next; 2591 PetscCall(TSDestroy(&ilink->ts)); 2592 PetscCall(PetscFree(ilink->splitname)); 2593 PetscCall(ISDestroy(&ilink->is)); 2594 PetscCall(PetscFree(ilink)); 2595 ilink = next; 2596 } 2597 ts->tsrhssplit = NULL; 2598 ts->num_rhs_splits = 0; 2599 if (ts->tspan) { 2600 PetscCall(PetscFree(ts->tspan->span_times)); 2601 PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol)); 2602 PetscCall(PetscFree(ts->tspan)); 2603 } 2604 ts->rhsjacobian.time = PETSC_MIN_REAL; 2605 ts->rhsjacobian.scale = 1.0; 2606 ts->ijacobian.shift = 1.0; 2607 ts->setupcalled = PETSC_FALSE; 2608 PetscFunctionReturn(PETSC_SUCCESS); 2609 } 2610 2611 static PetscErrorCode TSResizeReset(TS); 2612 2613 /*@ 2614 TSDestroy - Destroys the timestepper context that was created 2615 with `TSCreate()`. 2616 2617 Collective 2618 2619 Input Parameter: 2620 . ts - the `TS` context obtained from `TSCreate()` 2621 2622 Level: beginner 2623 2624 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSSolve()` 2625 @*/ 2626 PetscErrorCode TSDestroy(TS *ts) 2627 { 2628 PetscFunctionBegin; 2629 if (!*ts) PetscFunctionReturn(PETSC_SUCCESS); 2630 PetscValidHeaderSpecific(*ts, TS_CLASSID, 1); 2631 if (--((PetscObject)*ts)->refct > 0) { 2632 *ts = NULL; 2633 PetscFunctionReturn(PETSC_SUCCESS); 2634 } 2635 2636 PetscCall(TSReset(*ts)); 2637 PetscCall(TSAdjointReset(*ts)); 2638 if ((*ts)->forward_solve) PetscCall(TSForwardReset(*ts)); 2639 PetscCall(TSResizeReset(*ts)); 2640 2641 /* if memory was published with SAWs then destroy it */ 2642 PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts)); 2643 PetscTryTypeMethod(*ts, destroy); 2644 2645 PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory)); 2646 2647 PetscCall(TSAdaptDestroy(&(*ts)->adapt)); 2648 PetscCall(TSEventDestroy(&(*ts)->event)); 2649 2650 PetscCall(SNESDestroy(&(*ts)->snes)); 2651 PetscCall(DMDestroy(&(*ts)->dm)); 2652 PetscCall(TSMonitorCancel(*ts)); 2653 PetscCall(TSAdjointMonitorCancel(*ts)); 2654 2655 PetscCall(TSDestroy(&(*ts)->quadraturets)); 2656 PetscCall(PetscHeaderDestroy(ts)); 2657 PetscFunctionReturn(PETSC_SUCCESS); 2658 } 2659 2660 /*@ 2661 TSGetSNES - Returns the `SNES` (nonlinear solver) associated with 2662 a `TS` (timestepper) context. Valid only for nonlinear problems. 2663 2664 Not Collective, but snes is parallel if ts is parallel 2665 2666 Input Parameter: 2667 . ts - the `TS` context obtained from `TSCreate()` 2668 2669 Output Parameter: 2670 . snes - the nonlinear solver context 2671 2672 Level: beginner 2673 2674 Notes: 2675 The user can then directly manipulate the `SNES` context to set various 2676 options, etc. Likewise, the user can then extract and manipulate the 2677 `KSP`, and `PC` contexts as well. 2678 2679 `TSGetSNES()` does not work for integrators that do not use `SNES`; in 2680 this case `TSGetSNES()` returns `NULL` in `snes`. 2681 2682 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()` 2683 @*/ 2684 PetscErrorCode TSGetSNES(TS ts, SNES *snes) 2685 { 2686 PetscFunctionBegin; 2687 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2688 PetscAssertPointer(snes, 2); 2689 if (!ts->snes) { 2690 PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts), &ts->snes)); 2691 PetscCall(PetscObjectSetOptions((PetscObject)ts->snes, ((PetscObject)ts)->options)); 2692 PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts)); 2693 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1)); 2694 if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm)); 2695 if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY)); 2696 } 2697 *snes = ts->snes; 2698 PetscFunctionReturn(PETSC_SUCCESS); 2699 } 2700 2701 /*@ 2702 TSSetSNES - Set the `SNES` (nonlinear solver) to be used by the timestepping context 2703 2704 Collective 2705 2706 Input Parameters: 2707 + ts - the `TS` context obtained from `TSCreate()` 2708 - snes - the nonlinear solver context 2709 2710 Level: developer 2711 2712 Note: 2713 Most users should have the `TS` created by calling `TSGetSNES()` 2714 2715 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()` 2716 @*/ 2717 PetscErrorCode TSSetSNES(TS ts, SNES snes) 2718 { 2719 PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *); 2720 2721 PetscFunctionBegin; 2722 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2723 PetscValidHeaderSpecific(snes, SNES_CLASSID, 2); 2724 PetscCall(PetscObjectReference((PetscObject)snes)); 2725 PetscCall(SNESDestroy(&ts->snes)); 2726 2727 ts->snes = snes; 2728 2729 PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts)); 2730 PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL)); 2731 if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts)); 2732 PetscFunctionReturn(PETSC_SUCCESS); 2733 } 2734 2735 /*@ 2736 TSGetKSP - Returns the `KSP` (linear solver) associated with 2737 a `TS` (timestepper) context. 2738 2739 Not Collective, but `ksp` is parallel if `ts` is parallel 2740 2741 Input Parameter: 2742 . ts - the `TS` context obtained from `TSCreate()` 2743 2744 Output Parameter: 2745 . ksp - the nonlinear solver context 2746 2747 Level: beginner 2748 2749 Notes: 2750 The user can then directly manipulate the `KSP` context to set various 2751 options, etc. Likewise, the user can then extract and manipulate the 2752 `PC` context as well. 2753 2754 `TSGetKSP()` does not work for integrators that do not use `KSP`; 2755 in this case `TSGetKSP()` returns `NULL` in `ksp`. 2756 2757 .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()` 2758 @*/ 2759 PetscErrorCode TSGetKSP(TS ts, KSP *ksp) 2760 { 2761 SNES snes; 2762 2763 PetscFunctionBegin; 2764 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2765 PetscAssertPointer(ksp, 2); 2766 PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first"); 2767 PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()"); 2768 PetscCall(TSGetSNES(ts, &snes)); 2769 PetscCall(SNESGetKSP(snes, ksp)); 2770 PetscFunctionReturn(PETSC_SUCCESS); 2771 } 2772 2773 /* ----------- Routines to set solver parameters ---------- */ 2774 2775 /*@ 2776 TSSetMaxSteps - Sets the maximum number of steps to use. 2777 2778 Logically Collective 2779 2780 Input Parameters: 2781 + ts - the `TS` context obtained from `TSCreate()` 2782 - maxsteps - maximum number of steps to use 2783 2784 Options Database Key: 2785 . -ts_max_steps <maxsteps> - Sets maxsteps 2786 2787 Level: intermediate 2788 2789 Note: 2790 Use `PETSC_DETERMINE` to reset the maximum number of steps to the default from when the object's type was set 2791 2792 The default maximum number of steps is 5,000 2793 2794 Fortran Note: 2795 Use `PETSC_DETERMINE_INTEGER` 2796 2797 .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()` 2798 @*/ 2799 PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps) 2800 { 2801 PetscFunctionBegin; 2802 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2803 PetscValidLogicalCollectiveInt(ts, maxsteps, 2); 2804 if (maxsteps == PETSC_DETERMINE) { 2805 ts->max_steps = ts->default_max_steps; 2806 } else { 2807 PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative"); 2808 ts->max_steps = maxsteps; 2809 } 2810 PetscFunctionReturn(PETSC_SUCCESS); 2811 } 2812 2813 /*@ 2814 TSGetMaxSteps - Gets the maximum number of steps to use. 2815 2816 Not Collective 2817 2818 Input Parameter: 2819 . ts - the `TS` context obtained from `TSCreate()` 2820 2821 Output Parameter: 2822 . maxsteps - maximum number of steps to use 2823 2824 Level: advanced 2825 2826 .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()` 2827 @*/ 2828 PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps) 2829 { 2830 PetscFunctionBegin; 2831 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2832 PetscAssertPointer(maxsteps, 2); 2833 *maxsteps = ts->max_steps; 2834 PetscFunctionReturn(PETSC_SUCCESS); 2835 } 2836 2837 /*@ 2838 TSSetMaxTime - Sets the maximum (or final) time for timestepping. 2839 2840 Logically Collective 2841 2842 Input Parameters: 2843 + ts - the `TS` context obtained from `TSCreate()` 2844 - maxtime - final time to step to 2845 2846 Options Database Key: 2847 . -ts_max_time <maxtime> - Sets maxtime 2848 2849 Level: intermediate 2850 2851 Notes: 2852 Use `PETSC_DETERMINE` to reset the maximum time to the default from when the object's type was set 2853 2854 The default maximum time is 5.0 2855 2856 Fortran Note: 2857 Use `PETSC_DETERMINE_REAL` 2858 2859 .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()` 2860 @*/ 2861 PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime) 2862 { 2863 PetscFunctionBegin; 2864 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2865 PetscValidLogicalCollectiveReal(ts, maxtime, 2); 2866 if (maxtime == PETSC_DETERMINE) { 2867 ts->max_time = ts->default_max_time; 2868 } else { 2869 ts->max_time = maxtime; 2870 } 2871 PetscFunctionReturn(PETSC_SUCCESS); 2872 } 2873 2874 /*@ 2875 TSGetMaxTime - Gets the maximum (or final) time for timestepping. 2876 2877 Not Collective 2878 2879 Input Parameter: 2880 . ts - the `TS` context obtained from `TSCreate()` 2881 2882 Output Parameter: 2883 . maxtime - final time to step to 2884 2885 Level: advanced 2886 2887 .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()` 2888 @*/ 2889 PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime) 2890 { 2891 PetscFunctionBegin; 2892 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2893 PetscAssertPointer(maxtime, 2); 2894 *maxtime = ts->max_time; 2895 PetscFunctionReturn(PETSC_SUCCESS); 2896 } 2897 2898 // PetscClangLinter pragma disable: -fdoc-* 2899 /*@ 2900 TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`. 2901 2902 Level: deprecated 2903 2904 @*/ 2905 PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step) 2906 { 2907 PetscFunctionBegin; 2908 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2909 PetscCall(TSSetTime(ts, initial_time)); 2910 PetscCall(TSSetTimeStep(ts, time_step)); 2911 PetscFunctionReturn(PETSC_SUCCESS); 2912 } 2913 2914 // PetscClangLinter pragma disable: -fdoc-* 2915 /*@ 2916 TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`. 2917 2918 Level: deprecated 2919 2920 @*/ 2921 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime) 2922 { 2923 PetscFunctionBegin; 2924 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2925 if (maxsteps) { 2926 PetscAssertPointer(maxsteps, 2); 2927 *maxsteps = ts->max_steps; 2928 } 2929 if (maxtime) { 2930 PetscAssertPointer(maxtime, 3); 2931 *maxtime = ts->max_time; 2932 } 2933 PetscFunctionReturn(PETSC_SUCCESS); 2934 } 2935 2936 // PetscClangLinter pragma disable: -fdoc-* 2937 /*@ 2938 TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`. 2939 2940 Level: deprecated 2941 2942 @*/ 2943 PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime) 2944 { 2945 PetscFunctionBegin; 2946 if (maxsteps != (PetscInt)PETSC_CURRENT) PetscCall(TSSetMaxSteps(ts, maxsteps)); 2947 if (maxtime != (PetscReal)PETSC_CURRENT) PetscCall(TSSetMaxTime(ts, maxtime)); 2948 PetscFunctionReturn(PETSC_SUCCESS); 2949 } 2950 2951 // PetscClangLinter pragma disable: -fdoc-* 2952 /*@ 2953 TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`. 2954 2955 Level: deprecated 2956 2957 @*/ 2958 PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps) 2959 { 2960 return TSGetStepNumber(ts, steps); 2961 } 2962 2963 // PetscClangLinter pragma disable: -fdoc-* 2964 /*@ 2965 TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`. 2966 2967 Level: deprecated 2968 2969 @*/ 2970 PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps) 2971 { 2972 return TSGetStepNumber(ts, steps); 2973 } 2974 2975 /*@ 2976 TSSetSolution - Sets the initial solution vector 2977 for use by the `TS` routines. 2978 2979 Logically Collective 2980 2981 Input Parameters: 2982 + ts - the `TS` context obtained from `TSCreate()` 2983 - u - the solution vector 2984 2985 Level: beginner 2986 2987 .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()` 2988 @*/ 2989 PetscErrorCode TSSetSolution(TS ts, Vec u) 2990 { 2991 DM dm; 2992 2993 PetscFunctionBegin; 2994 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2995 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 2996 PetscCall(PetscObjectReference((PetscObject)u)); 2997 PetscCall(VecDestroy(&ts->vec_sol)); 2998 ts->vec_sol = u; 2999 3000 PetscCall(TSGetDM(ts, &dm)); 3001 PetscCall(DMShellSetGlobalVector(dm, u)); 3002 PetscFunctionReturn(PETSC_SUCCESS); 3003 } 3004 3005 /*@C 3006 TSSetPreStep - Sets the general-purpose function 3007 called once at the beginning of each time step. 3008 3009 Logically Collective 3010 3011 Input Parameters: 3012 + ts - The `TS` context obtained from `TSCreate()` 3013 - func - The function 3014 3015 Calling sequence of `func`: 3016 . ts - the `TS` context 3017 3018 Level: intermediate 3019 3020 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()` 3021 @*/ 3022 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS ts)) 3023 { 3024 PetscFunctionBegin; 3025 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3026 ts->prestep = func; 3027 PetscFunctionReturn(PETSC_SUCCESS); 3028 } 3029 3030 /*@ 3031 TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()` 3032 3033 Collective 3034 3035 Input Parameter: 3036 . ts - The `TS` context obtained from `TSCreate()` 3037 3038 Level: developer 3039 3040 Note: 3041 `TSPreStep()` is typically used within time stepping implementations, 3042 so most users would not generally call this routine themselves. 3043 3044 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()` 3045 @*/ 3046 PetscErrorCode TSPreStep(TS ts) 3047 { 3048 PetscFunctionBegin; 3049 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3050 if (ts->prestep) { 3051 Vec U; 3052 PetscObjectId idprev; 3053 PetscBool sameObject; 3054 PetscObjectState sprev, spost; 3055 3056 PetscCall(TSGetSolution(ts, &U)); 3057 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3058 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3059 PetscCallBack("TS callback preset", (*ts->prestep)(ts)); 3060 PetscCall(TSGetSolution(ts, &U)); 3061 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3062 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3063 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3064 } 3065 PetscFunctionReturn(PETSC_SUCCESS); 3066 } 3067 3068 /*@C 3069 TSSetPreStage - Sets the general-purpose function 3070 called once at the beginning of each stage. 3071 3072 Logically Collective 3073 3074 Input Parameters: 3075 + ts - The `TS` context obtained from `TSCreate()` 3076 - func - The function 3077 3078 Calling sequence of `func`: 3079 + ts - the `TS` context 3080 - stagetime - the stage time 3081 3082 Level: intermediate 3083 3084 Note: 3085 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3086 The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being 3087 attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`. 3088 3089 .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3090 @*/ 3091 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime)) 3092 { 3093 PetscFunctionBegin; 3094 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3095 ts->prestage = func; 3096 PetscFunctionReturn(PETSC_SUCCESS); 3097 } 3098 3099 /*@C 3100 TSSetPostStage - Sets the general-purpose function, provided with `TSSetPostStep()`, 3101 called once at the end of each stage. 3102 3103 Logically Collective 3104 3105 Input Parameters: 3106 + ts - The `TS` context obtained from `TSCreate()` 3107 - func - The function 3108 3109 Calling sequence of `func`: 3110 + ts - the `TS` context 3111 . stagetime - the stage time 3112 . stageindex - the stage index 3113 - Y - Array of vectors (of size = total number of stages) with the stage solutions 3114 3115 Level: intermediate 3116 3117 Note: 3118 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3119 The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being 3120 attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`. 3121 3122 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3123 @*/ 3124 PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)) 3125 { 3126 PetscFunctionBegin; 3127 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3128 ts->poststage = func; 3129 PetscFunctionReturn(PETSC_SUCCESS); 3130 } 3131 3132 /*@C 3133 TSSetPostEvaluate - Sets the general-purpose function 3134 called once at the end of each step evaluation. 3135 3136 Logically Collective 3137 3138 Input Parameters: 3139 + ts - The `TS` context obtained from `TSCreate()` 3140 - func - The function 3141 3142 Calling sequence of `func`: 3143 . ts - the `TS` context 3144 3145 Level: intermediate 3146 3147 Note: 3148 Semantically, `TSSetPostEvaluate()` differs from `TSSetPostStep()` since the function it sets is called before event-handling 3149 thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, `TSPostStep()` 3150 may be passed a different solution, possibly changed by the event handler. `TSPostEvaluate()` is called after the next step 3151 solution is evaluated allowing to modify it, if need be. The solution can be obtained with `TSGetSolution()`, the time step 3152 with `TSGetTimeStep()`, and the time at the start of the step is available via `TSGetTime()` 3153 3154 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3155 @*/ 3156 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS ts)) 3157 { 3158 PetscFunctionBegin; 3159 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3160 ts->postevaluate = func; 3161 PetscFunctionReturn(PETSC_SUCCESS); 3162 } 3163 3164 /*@ 3165 TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()` 3166 3167 Collective 3168 3169 Input Parameters: 3170 + ts - The `TS` context obtained from `TSCreate()` 3171 - stagetime - The absolute time of the current stage 3172 3173 Level: developer 3174 3175 Note: 3176 `TSPreStage()` is typically used within time stepping implementations, 3177 most users would not generally call this routine themselves. 3178 3179 .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3180 @*/ 3181 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime) 3182 { 3183 PetscFunctionBegin; 3184 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3185 if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime)); 3186 PetscFunctionReturn(PETSC_SUCCESS); 3187 } 3188 3189 /*@ 3190 TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()` 3191 3192 Collective 3193 3194 Input Parameters: 3195 + ts - The `TS` context obtained from `TSCreate()` 3196 . stagetime - The absolute time of the current stage 3197 . stageindex - Stage number 3198 - Y - Array of vectors (of size = total number of stages) with the stage solutions 3199 3200 Level: developer 3201 3202 Note: 3203 `TSPostStage()` is typically used within time stepping implementations, 3204 most users would not generally call this routine themselves. 3205 3206 .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3207 @*/ 3208 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y) 3209 { 3210 PetscFunctionBegin; 3211 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3212 if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y)); 3213 PetscFunctionReturn(PETSC_SUCCESS); 3214 } 3215 3216 /*@ 3217 TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()` 3218 3219 Collective 3220 3221 Input Parameter: 3222 . ts - The `TS` context obtained from `TSCreate()` 3223 3224 Level: developer 3225 3226 Note: 3227 `TSPostEvaluate()` is typically used within time stepping implementations, 3228 most users would not generally call this routine themselves. 3229 3230 .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3231 @*/ 3232 PetscErrorCode TSPostEvaluate(TS ts) 3233 { 3234 PetscFunctionBegin; 3235 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3236 if (ts->postevaluate) { 3237 Vec U; 3238 PetscObjectState sprev, spost; 3239 3240 PetscCall(TSGetSolution(ts, &U)); 3241 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3242 PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts)); 3243 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3244 if (sprev != spost) PetscCall(TSRestartStep(ts)); 3245 } 3246 PetscFunctionReturn(PETSC_SUCCESS); 3247 } 3248 3249 /*@C 3250 TSSetPostStep - Sets the general-purpose function 3251 called once at the end of each time step. 3252 3253 Logically Collective 3254 3255 Input Parameters: 3256 + ts - The `TS` context obtained from `TSCreate()` 3257 - func - The function 3258 3259 Calling sequence of `func`: 3260 . ts - the `TS` context 3261 3262 Level: intermediate 3263 3264 Note: 3265 The function set by `TSSetPostStep()` is called after each successful step. The solution vector 3266 obtained by `TSGetSolution()` may be different than that computed at the step end if the event handler 3267 locates an event and `TSPostEvent()` modifies it. Use `TSSetPostEvaluate()` if an unmodified solution is needed instead. 3268 3269 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()` 3270 @*/ 3271 PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS ts)) 3272 { 3273 PetscFunctionBegin; 3274 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3275 ts->poststep = func; 3276 PetscFunctionReturn(PETSC_SUCCESS); 3277 } 3278 3279 /*@ 3280 TSPostStep - Runs the user-defined post-step function that was set with `TSSetPostStep()` 3281 3282 Collective 3283 3284 Input Parameter: 3285 . ts - The `TS` context obtained from `TSCreate()` 3286 3287 Note: 3288 `TSPostStep()` is typically used within time stepping implementations, 3289 so most users would not generally call this routine themselves. 3290 3291 Level: developer 3292 3293 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPotsStep()` 3294 @*/ 3295 PetscErrorCode TSPostStep(TS ts) 3296 { 3297 PetscFunctionBegin; 3298 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3299 if (ts->poststep) { 3300 Vec U; 3301 PetscObjectId idprev; 3302 PetscBool sameObject; 3303 PetscObjectState sprev, spost; 3304 3305 PetscCall(TSGetSolution(ts, &U)); 3306 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3307 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3308 PetscCallBack("TS callback poststep", (*ts->poststep)(ts)); 3309 PetscCall(TSGetSolution(ts, &U)); 3310 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3311 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3312 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3313 } 3314 PetscFunctionReturn(PETSC_SUCCESS); 3315 } 3316 3317 /*@ 3318 TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval 3319 3320 Collective 3321 3322 Input Parameters: 3323 + ts - time stepping context 3324 - t - time to interpolate to 3325 3326 Output Parameter: 3327 . U - state at given time 3328 3329 Level: intermediate 3330 3331 Developer Notes: 3332 `TSInterpolate()` and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints. 3333 3334 .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()` 3335 @*/ 3336 PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U) 3337 { 3338 PetscFunctionBegin; 3339 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3340 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3341 PetscCheck(t >= ts->ptime_prev && t <= ts->ptime, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Requested time %g not in last time steps [%g,%g]", (double)t, (double)ts->ptime_prev, (double)ts->ptime); 3342 PetscUseTypeMethod(ts, interpolate, t, U); 3343 PetscFunctionReturn(PETSC_SUCCESS); 3344 } 3345 3346 /*@ 3347 TSStep - Steps one time step 3348 3349 Collective 3350 3351 Input Parameter: 3352 . ts - the `TS` context obtained from `TSCreate()` 3353 3354 Level: developer 3355 3356 Notes: 3357 The public interface for the ODE/DAE solvers is `TSSolve()`, you should almost for sure be using that routine and not this routine. 3358 3359 The hook set using `TSSetPreStep()` is called before each attempt to take the step. In general, the time step size may 3360 be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages. 3361 3362 This may over-step the final time provided in `TSSetMaxTime()` depending on the time-step used. `TSSolve()` interpolates to exactly the 3363 time provided in `TSSetMaxTime()`. One can use `TSInterpolate()` to determine an interpolated solution within the final timestep. 3364 3365 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()` 3366 @*/ 3367 PetscErrorCode TSStep(TS ts) 3368 { 3369 static PetscBool cite = PETSC_FALSE; 3370 PetscReal ptime; 3371 3372 PetscFunctionBegin; 3373 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3374 PetscCall(PetscCitationsRegister("@article{tspaper,\n" 3375 " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n" 3376 " author = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n" 3377 " journal = {arXiv e-preprints},\n" 3378 " eprint = {1806.01437},\n" 3379 " archivePrefix = {arXiv},\n" 3380 " year = {2018}\n}\n", 3381 &cite)); 3382 PetscCall(TSSetUp(ts)); 3383 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 3384 if (ts->tspan) 3385 ts->tspan->worktol = 0; /* In each step of TSSolve() 'tspan->worktol' will be meaningfully defined (later) only once: 3386 in TSAdaptChoose() or TSEvent_dt_cap(), and then reused till the end of the step */ 3387 3388 PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->max_steps != PETSC_MAX_INT, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetMaxTime() or TSSetMaxSteps(), or use -ts_max_time <time> or -ts_max_steps <steps>"); 3389 PetscCheck(ts->exact_final_time != TS_EXACTFINALTIME_UNSPECIFIED, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetExactFinalTime() or use -ts_exact_final_time <stepover,interpolate,matchstep> before calling TSStep()"); 3390 PetscCheck(ts->exact_final_time != TS_EXACTFINALTIME_MATCHSTEP || ts->adapt, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Since TS is not adaptive you cannot use TS_EXACTFINALTIME_MATCHSTEP, suggest TS_EXACTFINALTIME_INTERPOLATE"); 3391 3392 if (!ts->vec_sol0) PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sol0)); 3393 PetscCall(VecCopy(ts->vec_sol, ts->vec_sol0)); 3394 ts->time_step0 = ts->time_step; 3395 3396 if (!ts->steps) ts->ptime_prev = ts->ptime; 3397 ptime = ts->ptime; 3398 3399 ts->ptime_prev_rollback = ts->ptime_prev; 3400 ts->reason = TS_CONVERGED_ITERATING; 3401 3402 PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0)); 3403 PetscUseTypeMethod(ts, step); 3404 PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0)); 3405 3406 if (ts->reason >= 0) { 3407 ts->ptime_prev = ptime; 3408 ts->steps++; 3409 ts->steprollback = PETSC_FALSE; 3410 ts->steprestart = PETSC_FALSE; 3411 ts->stepresize = PETSC_FALSE; 3412 } 3413 3414 if (ts->reason < 0 && ts->errorifstepfailed) { 3415 PetscCall(TSMonitorCancel(ts)); 3416 PetscCheck(ts->reason != TS_DIVERGED_NONLINEAR_SOLVE, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s, increase -ts_max_snes_failures or use unlimited to attempt recovery", TSConvergedReasons[ts->reason]); 3417 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]); 3418 } 3419 PetscFunctionReturn(PETSC_SUCCESS); 3420 } 3421 3422 /*@ 3423 TSEvaluateWLTE - Evaluate the weighted local truncation error norm 3424 at the end of a time step with a given order of accuracy. 3425 3426 Collective 3427 3428 Input Parameters: 3429 + ts - time stepping context 3430 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 3431 3432 Input/Output Parameter: 3433 . order - optional, desired order for the error evaluation or `PETSC_DECIDE`; 3434 on output, the actual order of the error evaluation 3435 3436 Output Parameter: 3437 . wlte - the weighted local truncation error norm 3438 3439 Level: advanced 3440 3441 Note: 3442 If the timestepper cannot evaluate the error in a particular step 3443 (eg. in the first step or restart steps after event handling), 3444 this routine returns wlte=-1.0 . 3445 3446 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()` 3447 @*/ 3448 PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte) 3449 { 3450 PetscFunctionBegin; 3451 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3452 PetscValidType(ts, 1); 3453 PetscValidLogicalCollectiveEnum(ts, wnormtype, 2); 3454 if (order) PetscAssertPointer(order, 3); 3455 if (order) PetscValidLogicalCollectiveInt(ts, *order, 3); 3456 PetscAssertPointer(wlte, 4); 3457 PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 3458 PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte); 3459 PetscFunctionReturn(PETSC_SUCCESS); 3460 } 3461 3462 /*@ 3463 TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy. 3464 3465 Collective 3466 3467 Input Parameters: 3468 + ts - time stepping context 3469 . order - desired order of accuracy 3470 - done - whether the step was evaluated at this order (pass `NULL` to generate an error if not available) 3471 3472 Output Parameter: 3473 . U - state at the end of the current step 3474 3475 Level: advanced 3476 3477 Notes: 3478 This function cannot be called until all stages have been evaluated. 3479 3480 It is normally called by adaptive controllers before a step has been accepted and may also be called by the user after `TSStep()` has returned. 3481 3482 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt` 3483 @*/ 3484 PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done) 3485 { 3486 PetscFunctionBegin; 3487 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3488 PetscValidType(ts, 1); 3489 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3490 PetscUseTypeMethod(ts, evaluatestep, order, U, done); 3491 PetscFunctionReturn(PETSC_SUCCESS); 3492 } 3493 3494 /*@C 3495 TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping. 3496 3497 Not collective 3498 3499 Input Parameter: 3500 . ts - time stepping context 3501 3502 Output Parameter: 3503 . initCondition - The function which computes an initial condition 3504 3505 Calling sequence of `initCondition`: 3506 + ts - The timestepping context 3507 - u - The input vector in which the initial condition is stored 3508 3509 Level: advanced 3510 3511 .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()` 3512 @*/ 3513 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS ts, Vec u)) 3514 { 3515 PetscFunctionBegin; 3516 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3517 PetscAssertPointer(initCondition, 2); 3518 *initCondition = ts->ops->initcondition; 3519 PetscFunctionReturn(PETSC_SUCCESS); 3520 } 3521 3522 /*@C 3523 TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping. 3524 3525 Logically collective 3526 3527 Input Parameters: 3528 + ts - time stepping context 3529 - initCondition - The function which computes an initial condition 3530 3531 Calling sequence of `initCondition`: 3532 + ts - The timestepping context 3533 - e - The input vector in which the initial condition is to be stored 3534 3535 Level: advanced 3536 3537 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()` 3538 @*/ 3539 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS ts, Vec e)) 3540 { 3541 PetscFunctionBegin; 3542 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3543 PetscValidFunction(initCondition, 2); 3544 ts->ops->initcondition = initCondition; 3545 PetscFunctionReturn(PETSC_SUCCESS); 3546 } 3547 3548 /*@ 3549 TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()` 3550 3551 Collective 3552 3553 Input Parameters: 3554 + ts - time stepping context 3555 - u - The `Vec` to store the condition in which will be used in `TSSolve()` 3556 3557 Level: advanced 3558 3559 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3560 @*/ 3561 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u) 3562 { 3563 PetscFunctionBegin; 3564 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3565 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3566 PetscTryTypeMethod(ts, initcondition, u); 3567 PetscFunctionReturn(PETSC_SUCCESS); 3568 } 3569 3570 /*@C 3571 TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping. 3572 3573 Not collective 3574 3575 Input Parameter: 3576 . ts - time stepping context 3577 3578 Output Parameter: 3579 . exactError - The function which computes the solution error 3580 3581 Calling sequence of `exactError`: 3582 + ts - The timestepping context 3583 . u - The approximate solution vector 3584 - e - The vector in which the error is stored 3585 3586 Level: advanced 3587 3588 .seealso: [](ch_ts), `TS`, `TSComputeExactError()` 3589 @*/ 3590 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS ts, Vec u, Vec e)) 3591 { 3592 PetscFunctionBegin; 3593 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3594 PetscAssertPointer(exactError, 2); 3595 *exactError = ts->ops->exacterror; 3596 PetscFunctionReturn(PETSC_SUCCESS); 3597 } 3598 3599 /*@C 3600 TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping. 3601 3602 Logically collective 3603 3604 Input Parameters: 3605 + ts - time stepping context 3606 - exactError - The function which computes the solution error 3607 3608 Calling sequence of `exactError`: 3609 + ts - The timestepping context 3610 . u - The approximate solution vector 3611 - e - The vector in which the error is stored 3612 3613 Level: advanced 3614 3615 .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()` 3616 @*/ 3617 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS ts, Vec u, Vec e)) 3618 { 3619 PetscFunctionBegin; 3620 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3621 PetscValidFunction(exactError, 2); 3622 ts->ops->exacterror = exactError; 3623 PetscFunctionReturn(PETSC_SUCCESS); 3624 } 3625 3626 /*@ 3627 TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()` 3628 3629 Collective 3630 3631 Input Parameters: 3632 + ts - time stepping context 3633 . u - The approximate solution 3634 - e - The `Vec` used to store the error 3635 3636 Level: advanced 3637 3638 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3639 @*/ 3640 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e) 3641 { 3642 PetscFunctionBegin; 3643 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3644 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3645 PetscValidHeaderSpecific(e, VEC_CLASSID, 3); 3646 PetscTryTypeMethod(ts, exacterror, u, e); 3647 PetscFunctionReturn(PETSC_SUCCESS); 3648 } 3649 3650 /*@C 3651 TSSetResize - Sets the resize callbacks. 3652 3653 Logically Collective 3654 3655 Input Parameters: 3656 + ts - The `TS` context obtained from `TSCreate()` 3657 . rollback - Whether a resize will restart the step 3658 . setup - The setup function 3659 . transfer - The transfer function 3660 - ctx - [optional] The user-defined context 3661 3662 Calling sequence of `setup`: 3663 + ts - the `TS` context 3664 . step - the current step 3665 . time - the current time 3666 . state - the current vector of state 3667 . resize - (output parameter) `PETSC_TRUE` if need resizing, `PETSC_FALSE` otherwise 3668 - ctx - user defined context 3669 3670 Calling sequence of `transfer`: 3671 + ts - the `TS` context 3672 . nv - the number of vectors to be transferred 3673 . vecsin - array of vectors to be transferred 3674 . vecsout - array of transferred vectors 3675 - ctx - user defined context 3676 3677 Notes: 3678 The `setup` function is called inside `TSSolve()` after `TSEventHandler()` or after `TSPostStep()` 3679 depending on the `rollback` value: if `rollback` is true, then these callbacks behave as error indicators 3680 and will flag the need to remesh and restart the current step. Otherwise, they will simply flag the solver 3681 that the size of the discrete problem has changed. 3682 In both cases, the solver will collect the needed vectors that will be 3683 transferred from the old to the new sizes using the `transfer` callback. These vectors will include the 3684 current solution vector, and other vectors needed by the specific solver used. 3685 For example, `TSBDF` uses previous solutions vectors to solve for the next time step. 3686 Other application specific objects associated with the solver, i.e. Jacobian matrices and `DM`, 3687 will be automatically reset if the sizes are changed and they must be specified again by the user 3688 inside the `transfer` function. 3689 The input and output arrays passed to `transfer` are allocated by PETSc. 3690 Vectors in `vecsout` must be created by the user. 3691 Ownership of vectors in `vecsout` is transferred to PETSc. 3692 3693 Level: advanced 3694 3695 .seealso: [](ch_ts), `TS`, `TSSetDM()`, `TSSetIJacobian()`, `TSSetRHSJacobian()` 3696 @*/ 3697 PetscErrorCode TSSetResize(TS ts, PetscBool rollback, PetscErrorCode (*setup)(TS ts, PetscInt step, PetscReal time, Vec state, PetscBool *resize, void *ctx), PetscErrorCode (*transfer)(TS ts, PetscInt nv, Vec vecsin[], Vec vecsout[], void *ctx), void *ctx) 3698 { 3699 PetscFunctionBegin; 3700 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3701 ts->resizerollback = rollback; 3702 ts->resizesetup = setup; 3703 ts->resizetransfer = transfer; 3704 ts->resizectx = ctx; 3705 PetscFunctionReturn(PETSC_SUCCESS); 3706 } 3707 3708 /* 3709 TSResizeRegisterOrRetrieve - Register or import vectors transferred with `TSResize()`. 3710 3711 Collective 3712 3713 Input Parameters: 3714 + ts - The `TS` context obtained from `TSCreate()` 3715 - flg - If `PETSC_TRUE` each TS implementation (e.g. `TSBDF`) will register vectors to be transferred, if `PETSC_FALSE` vectors will be imported from transferred vectors. 3716 3717 Level: developer 3718 3719 Note: 3720 `TSResizeRegisterOrRetrieve()` is declared PETSC_INTERN since it is 3721 used within time stepping implementations, 3722 so most users would not generally call this routine themselves. 3723 3724 .seealso: [](ch_ts), `TS`, `TSSetResize()` 3725 @*/ 3726 static PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg) 3727 { 3728 PetscFunctionBegin; 3729 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3730 PetscTryTypeMethod(ts, resizeregister, flg); 3731 /* PetscTryTypeMethod(adapt, resizeregister, flg); */ 3732 PetscFunctionReturn(PETSC_SUCCESS); 3733 } 3734 3735 static PetscErrorCode TSResizeReset(TS ts) 3736 { 3737 PetscFunctionBegin; 3738 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3739 PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs)); 3740 PetscFunctionReturn(PETSC_SUCCESS); 3741 } 3742 3743 static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[]) 3744 { 3745 PetscFunctionBegin; 3746 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3747 PetscValidLogicalCollectiveInt(ts, cnt, 2); 3748 for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPush(vecsin[i])); 3749 if (ts->resizetransfer) { 3750 PetscCall(PetscInfo(ts, "Transferring %" PetscInt_FMT " vectors\n", cnt)); 3751 PetscCallBack("TS callback resize transfer", (*ts->resizetransfer)(ts, cnt, vecsin, vecsout, ts->resizectx)); 3752 } 3753 for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPop(vecsin[i])); 3754 PetscFunctionReturn(PETSC_SUCCESS); 3755 } 3756 3757 /*@C 3758 TSResizeRegisterVec - Register a vector to be transferred with `TSResize()`. 3759 3760 Collective 3761 3762 Input Parameters: 3763 + ts - The `TS` context obtained from `TSCreate()` 3764 . name - A string identifying the vector 3765 - vec - The vector 3766 3767 Level: developer 3768 3769 Note: 3770 `TSResizeRegisterVec()` is typically used within time stepping implementations, 3771 so most users would not generally call this routine themselves. 3772 3773 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()` 3774 @*/ 3775 PetscErrorCode TSResizeRegisterVec(TS ts, const char name[], Vec vec) 3776 { 3777 PetscFunctionBegin; 3778 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3779 PetscAssertPointer(name, 2); 3780 if (vec) PetscValidHeaderSpecific(vec, VEC_CLASSID, 3); 3781 PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec)); 3782 PetscFunctionReturn(PETSC_SUCCESS); 3783 } 3784 3785 /*@C 3786 TSResizeRetrieveVec - Retrieve a vector registered with `TSResizeRegisterVec()`. 3787 3788 Collective 3789 3790 Input Parameters: 3791 + ts - The `TS` context obtained from `TSCreate()` 3792 . name - A string identifying the vector 3793 - vec - The vector 3794 3795 Level: developer 3796 3797 Note: 3798 `TSResizeRetrieveVec()` is typically used within time stepping implementations, 3799 so most users would not generally call this routine themselves. 3800 3801 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()` 3802 @*/ 3803 PetscErrorCode TSResizeRetrieveVec(TS ts, const char name[], Vec *vec) 3804 { 3805 PetscFunctionBegin; 3806 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3807 PetscAssertPointer(name, 2); 3808 PetscAssertPointer(vec, 3); 3809 PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec)); 3810 PetscFunctionReturn(PETSC_SUCCESS); 3811 } 3812 3813 static PetscErrorCode TSResizeGetVecArray(TS ts, PetscInt *nv, const char **names[], Vec *vecs[]) 3814 { 3815 PetscInt cnt; 3816 PetscObjectList tmp; 3817 Vec *vecsin = NULL; 3818 const char **namesin = NULL; 3819 3820 PetscFunctionBegin; 3821 for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) 3822 if (tmp->obj && tmp->obj->classid == VEC_CLASSID) cnt++; 3823 if (names) PetscCall(PetscMalloc1(cnt, &namesin)); 3824 if (vecs) PetscCall(PetscMalloc1(cnt, &vecsin)); 3825 for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) { 3826 if (tmp->obj && tmp->obj->classid == VEC_CLASSID) { 3827 if (vecs) vecsin[cnt] = (Vec)tmp->obj; 3828 if (names) namesin[cnt] = tmp->name; 3829 cnt++; 3830 } 3831 } 3832 if (nv) *nv = cnt; 3833 if (names) *names = namesin; 3834 if (vecs) *vecs = vecsin; 3835 PetscFunctionReturn(PETSC_SUCCESS); 3836 } 3837 3838 /*@ 3839 TSResize - Runs the user-defined transfer functions provided with `TSSetResize()` 3840 3841 Collective 3842 3843 Input Parameter: 3844 . ts - The `TS` context obtained from `TSCreate()` 3845 3846 Level: developer 3847 3848 Note: 3849 `TSResize()` is typically used within time stepping implementations, 3850 so most users would not generally call this routine themselves. 3851 3852 .seealso: [](ch_ts), `TS`, `TSSetResize()` 3853 @*/ 3854 PetscErrorCode TSResize(TS ts) 3855 { 3856 PetscInt nv = 0; 3857 const char **names = NULL; 3858 Vec *vecsin = NULL; 3859 const char *solname = "ts:vec_sol"; 3860 3861 PetscFunctionBegin; 3862 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3863 if (!ts->resizesetup) PetscFunctionReturn(PETSC_SUCCESS); 3864 if (ts->resizesetup) { 3865 PetscCall(VecLockReadPush(ts->vec_sol)); 3866 PetscCallBack("TS callback resize setup", (*ts->resizesetup)(ts, ts->steps, ts->ptime, ts->vec_sol, &ts->stepresize, ts->resizectx)); 3867 PetscCall(VecLockReadPop(ts->vec_sol)); 3868 if (ts->stepresize) { 3869 if (ts->resizerollback) { 3870 PetscCall(TSRollBack(ts)); 3871 ts->time_step = ts->time_step0; 3872 } 3873 PetscCall(TSResizeRegisterVec(ts, solname, ts->vec_sol)); 3874 PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_TRUE)); /* specific impls register their own objects */ 3875 } 3876 } 3877 3878 PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin)); 3879 if (nv) { 3880 Vec *vecsout, vecsol; 3881 3882 /* Reset internal objects */ 3883 PetscCall(TSReset(ts)); 3884 3885 /* Transfer needed vectors (users can call SetJacobian, SetDM, etc. here) */ 3886 PetscCall(PetscCalloc1(nv, &vecsout)); 3887 PetscCall(TSResizeTransferVecs(ts, nv, vecsin, vecsout)); 3888 for (PetscInt i = 0; i < nv; i++) { 3889 const char *name; 3890 char *oname; 3891 3892 PetscCall(PetscObjectGetName((PetscObject)vecsin[i], &name)); 3893 PetscCall(PetscStrallocpy(name, &oname)); 3894 PetscCall(TSResizeRegisterVec(ts, names[i], vecsout[i])); 3895 if (vecsout[i]) PetscCall(PetscObjectSetName((PetscObject)vecsout[i], oname)); 3896 PetscCall(PetscFree(oname)); 3897 PetscCall(VecDestroy(&vecsout[i])); 3898 } 3899 PetscCall(PetscFree(vecsout)); 3900 PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_FALSE)); /* specific impls import the transferred objects */ 3901 3902 PetscCall(TSResizeRetrieveVec(ts, solname, &vecsol)); 3903 if (vecsol) PetscCall(TSSetSolution(ts, vecsol)); 3904 PetscAssert(ts->vec_sol, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_NULL, "Missing TS solution"); 3905 } 3906 3907 PetscCall(PetscFree(names)); 3908 PetscCall(PetscFree(vecsin)); 3909 PetscCall(TSResizeReset(ts)); 3910 PetscFunctionReturn(PETSC_SUCCESS); 3911 } 3912 3913 /*@ 3914 TSSolve - Steps the requested number of timesteps. 3915 3916 Collective 3917 3918 Input Parameters: 3919 + ts - the `TS` context obtained from `TSCreate()` 3920 - u - the solution vector (can be null if `TSSetSolution()` was used and `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`) was not used, 3921 otherwise must contain the initial conditions and will contain the solution at the final requested time 3922 3923 Level: beginner 3924 3925 Notes: 3926 The final time returned by this function may be different from the time of the internally 3927 held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have 3928 stepped over the final time. 3929 3930 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()` 3931 @*/ 3932 PetscErrorCode TSSolve(TS ts, Vec u) 3933 { 3934 Vec solution; 3935 3936 PetscFunctionBegin; 3937 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3938 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3939 3940 PetscCall(TSSetExactFinalTimeDefault(ts)); 3941 if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && u) { /* Need ts->vec_sol to be distinct so it is not overwritten when we interpolate at the end */ 3942 if (!ts->vec_sol || u == ts->vec_sol) { 3943 PetscCall(VecDuplicate(u, &solution)); 3944 PetscCall(TSSetSolution(ts, solution)); 3945 PetscCall(VecDestroy(&solution)); /* grant ownership */ 3946 } 3947 PetscCall(VecCopy(u, ts->vec_sol)); 3948 PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE"); 3949 } else if (u) PetscCall(TSSetSolution(ts, u)); 3950 PetscCall(TSSetUp(ts)); 3951 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 3952 3953 PetscCheck(ts->max_time < PETSC_MAX_REAL || ts->max_steps != PETSC_MAX_INT, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetMaxTime() or TSSetMaxSteps(), or use -ts_max_time <time> or -ts_max_steps <steps>"); 3954 PetscCheck(ts->exact_final_time != TS_EXACTFINALTIME_UNSPECIFIED, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "You must call TSSetExactFinalTime() or use -ts_exact_final_time <stepover,interpolate,matchstep> before calling TSSolve()"); 3955 PetscCheck(ts->exact_final_time != TS_EXACTFINALTIME_MATCHSTEP || ts->adapt, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Since TS is not adaptive you cannot use TS_EXACTFINALTIME_MATCHSTEP, suggest TS_EXACTFINALTIME_INTERPOLATE"); 3956 PetscCheck(!(ts->tspan && ts->exact_final_time != TS_EXACTFINALTIME_MATCHSTEP), PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "You must use TS_EXACTFINALTIME_MATCHSTEP when using time span"); 3957 3958 if (ts->tspan && PetscIsCloseAtTol(ts->ptime, ts->tspan->span_times[0], ts->tspan->reltol * ts->time_step + ts->tspan->abstol, 0)) { /* starting point in time span */ 3959 PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[0])); 3960 ts->tspan->spanctr = 1; 3961 } 3962 3963 if (ts->forward_solve) PetscCall(TSForwardSetUp(ts)); 3964 3965 /* reset number of steps only when the step is not restarted. ARKIMEX 3966 restarts the step after an event. Resetting these counters in such case causes 3967 TSTrajectory to incorrectly save the output files 3968 */ 3969 /* reset time step and iteration counters */ 3970 if (!ts->steps) { 3971 ts->ksp_its = 0; 3972 ts->snes_its = 0; 3973 ts->num_snes_failures = 0; 3974 ts->reject = 0; 3975 ts->steprestart = PETSC_TRUE; 3976 ts->steprollback = PETSC_FALSE; 3977 ts->stepresize = PETSC_FALSE; 3978 ts->rhsjacobian.time = PETSC_MIN_REAL; 3979 } 3980 3981 /* make sure initial time step does not overshoot final time or the next point in tspan */ 3982 if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 3983 PetscReal maxdt; 3984 PetscReal dt = ts->time_step; 3985 3986 if (ts->tspan) maxdt = ts->tspan->span_times[ts->tspan->spanctr] - ts->ptime; 3987 else maxdt = ts->max_time - ts->ptime; 3988 ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt); 3989 } 3990 ts->reason = TS_CONVERGED_ITERATING; 3991 3992 { 3993 PetscViewer viewer; 3994 PetscViewerFormat format; 3995 PetscBool flg; 3996 static PetscBool incall = PETSC_FALSE; 3997 3998 if (!incall) { 3999 /* Estimate the convergence rate of the time discretization */ 4000 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg)); 4001 if (flg) { 4002 PetscConvEst conv; 4003 DM dm; 4004 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4005 PetscInt Nf; 4006 PetscBool checkTemporal = PETSC_TRUE; 4007 4008 incall = PETSC_TRUE; 4009 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg)); 4010 PetscCall(TSGetDM(ts, &dm)); 4011 PetscCall(DMGetNumFields(dm, &Nf)); 4012 PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha)); 4013 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv)); 4014 PetscCall(PetscConvEstUseTS(conv, checkTemporal)); 4015 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts)); 4016 PetscCall(PetscConvEstSetFromOptions(conv)); 4017 PetscCall(PetscConvEstSetUp(conv)); 4018 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 4019 PetscCall(PetscViewerPushFormat(viewer, format)); 4020 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 4021 PetscCall(PetscViewerPopFormat(viewer)); 4022 PetscCall(PetscViewerDestroy(&viewer)); 4023 PetscCall(PetscConvEstDestroy(&conv)); 4024 PetscCall(PetscFree(alpha)); 4025 incall = PETSC_FALSE; 4026 } 4027 } 4028 } 4029 4030 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre")); 4031 4032 if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */ 4033 PetscUseTypeMethod(ts, solve); 4034 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 4035 ts->solvetime = ts->ptime; 4036 solution = ts->vec_sol; 4037 } else { /* Step the requested number of timesteps. */ 4038 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 4039 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 4040 4041 if (!ts->steps) { 4042 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 4043 PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol)); 4044 } 4045 4046 while (!ts->reason) { 4047 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 4048 if (!ts->steprollback || (ts->stepresize && ts->resizerollback)) PetscCall(TSPreStep(ts)); 4049 PetscCall(TSStep(ts)); 4050 if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL)); 4051 if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL)); 4052 if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */ 4053 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 4054 PetscCall(TSForwardCostIntegral(ts)); 4055 if (ts->reason >= 0) ts->steps++; 4056 } 4057 if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */ 4058 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 4059 PetscCall(TSForwardStep(ts)); 4060 if (ts->reason >= 0) ts->steps++; 4061 } 4062 PetscCall(TSPostEvaluate(ts)); 4063 PetscCall(TSEventHandler(ts)); /* The right-hand side may be changed due to event. Be careful with Any computation using the RHS information after this point. */ 4064 if (ts->steprollback) PetscCall(TSPostEvaluate(ts)); 4065 if (!ts->steprollback && ts->resizerollback) PetscCall(TSResize(ts)); 4066 /* check convergence */ 4067 if (!ts->reason) { 4068 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 4069 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 4070 } 4071 if (!ts->steprollback) { 4072 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 4073 PetscCall(TSPostStep(ts)); 4074 if (!ts->resizerollback) PetscCall(TSResize(ts)); 4075 4076 if (ts->tspan && ts->tspan->spanctr < ts->tspan->num_span_times) { 4077 PetscCheck(ts->tspan->worktol > 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Unexpected state !(tspan->worktol > 0) in TSSolve()"); 4078 if (PetscIsCloseAtTol(ts->ptime, ts->tspan->span_times[ts->tspan->spanctr], ts->tspan->worktol, 0)) PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[ts->tspan->spanctr++])); 4079 } 4080 } 4081 } 4082 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 4083 4084 if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) { 4085 if (!u) u = ts->vec_sol; 4086 PetscCall(TSInterpolate(ts, ts->max_time, u)); 4087 ts->solvetime = ts->max_time; 4088 solution = u; 4089 PetscCall(TSMonitor(ts, -1, ts->solvetime, solution)); 4090 } else { 4091 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 4092 ts->solvetime = ts->ptime; 4093 solution = ts->vec_sol; 4094 } 4095 } 4096 4097 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view")); 4098 PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution")); 4099 PetscCall(PetscObjectSAWsBlock((PetscObject)ts)); 4100 if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts)); 4101 PetscFunctionReturn(PETSC_SUCCESS); 4102 } 4103 4104 /*@ 4105 TSGetTime - Gets the time of the most recently completed step. 4106 4107 Not Collective 4108 4109 Input Parameter: 4110 . ts - the `TS` context obtained from `TSCreate()` 4111 4112 Output Parameter: 4113 . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`. 4114 4115 Level: beginner 4116 4117 Note: 4118 When called during time step evaluation (e.g. during residual evaluation or via hooks set using `TSSetPreStep()`, 4119 `TSSetPreStage()`, `TSSetPostStage()`, or `TSSetPostStep()`), the time is the time at the start of the step being evaluated. 4120 4121 .seealso: [](ch_ts), `TS`, `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()` 4122 @*/ 4123 PetscErrorCode TSGetTime(TS ts, PetscReal *t) 4124 { 4125 PetscFunctionBegin; 4126 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4127 PetscAssertPointer(t, 2); 4128 *t = ts->ptime; 4129 PetscFunctionReturn(PETSC_SUCCESS); 4130 } 4131 4132 /*@ 4133 TSGetPrevTime - Gets the starting time of the previously completed step. 4134 4135 Not Collective 4136 4137 Input Parameter: 4138 . ts - the `TS` context obtained from `TSCreate()` 4139 4140 Output Parameter: 4141 . t - the previous time 4142 4143 Level: beginner 4144 4145 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()` 4146 @*/ 4147 PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t) 4148 { 4149 PetscFunctionBegin; 4150 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4151 PetscAssertPointer(t, 2); 4152 *t = ts->ptime_prev; 4153 PetscFunctionReturn(PETSC_SUCCESS); 4154 } 4155 4156 /*@ 4157 TSSetTime - Allows one to reset the time. 4158 4159 Logically Collective 4160 4161 Input Parameters: 4162 + ts - the `TS` context obtained from `TSCreate()` 4163 - t - the time 4164 4165 Level: intermediate 4166 4167 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()` 4168 @*/ 4169 PetscErrorCode TSSetTime(TS ts, PetscReal t) 4170 { 4171 PetscFunctionBegin; 4172 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4173 PetscValidLogicalCollectiveReal(ts, t, 2); 4174 ts->ptime = t; 4175 PetscFunctionReturn(PETSC_SUCCESS); 4176 } 4177 4178 /*@ 4179 TSSetOptionsPrefix - Sets the prefix used for searching for all 4180 TS options in the database. 4181 4182 Logically Collective 4183 4184 Input Parameters: 4185 + ts - The `TS` context 4186 - prefix - The prefix to prepend to all option names 4187 4188 Level: advanced 4189 4190 Note: 4191 A hyphen (-) must NOT be given at the beginning of the prefix name. 4192 The first character of all runtime options is AUTOMATICALLY the 4193 hyphen. 4194 4195 .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()` 4196 @*/ 4197 PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[]) 4198 { 4199 SNES snes; 4200 4201 PetscFunctionBegin; 4202 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4203 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix)); 4204 PetscCall(TSGetSNES(ts, &snes)); 4205 PetscCall(SNESSetOptionsPrefix(snes, prefix)); 4206 PetscFunctionReturn(PETSC_SUCCESS); 4207 } 4208 4209 /*@ 4210 TSAppendOptionsPrefix - Appends to the prefix used for searching for all 4211 TS options in the database. 4212 4213 Logically Collective 4214 4215 Input Parameters: 4216 + ts - The `TS` context 4217 - prefix - The prefix to prepend to all option names 4218 4219 Level: advanced 4220 4221 Note: 4222 A hyphen (-) must NOT be given at the beginning of the prefix name. 4223 The first character of all runtime options is AUTOMATICALLY the 4224 hyphen. 4225 4226 .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()` 4227 @*/ 4228 PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[]) 4229 { 4230 SNES snes; 4231 4232 PetscFunctionBegin; 4233 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4234 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix)); 4235 PetscCall(TSGetSNES(ts, &snes)); 4236 PetscCall(SNESAppendOptionsPrefix(snes, prefix)); 4237 PetscFunctionReturn(PETSC_SUCCESS); 4238 } 4239 4240 /*@ 4241 TSGetOptionsPrefix - Sets the prefix used for searching for all 4242 `TS` options in the database. 4243 4244 Not Collective 4245 4246 Input Parameter: 4247 . ts - The `TS` context 4248 4249 Output Parameter: 4250 . prefix - A pointer to the prefix string used 4251 4252 Level: intermediate 4253 4254 Fortran Notes: 4255 The user should pass in a string 'prefix' of 4256 sufficient length to hold the prefix. 4257 4258 .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()` 4259 @*/ 4260 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[]) 4261 { 4262 PetscFunctionBegin; 4263 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4264 PetscAssertPointer(prefix, 2); 4265 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix)); 4266 PetscFunctionReturn(PETSC_SUCCESS); 4267 } 4268 4269 /*@C 4270 TSGetRHSJacobian - Returns the Jacobian J at the present timestep. 4271 4272 Not Collective, but parallel objects are returned if ts is parallel 4273 4274 Input Parameter: 4275 . ts - The `TS` context obtained from `TSCreate()` 4276 4277 Output Parameters: 4278 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or `NULL`) 4279 . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat` (or `NULL`) 4280 . func - Function to compute the Jacobian of the RHS (or `NULL`) 4281 - ctx - User-defined context for Jacobian evaluation routine (or `NULL`) 4282 4283 Level: intermediate 4284 4285 Note: 4286 You can pass in `NULL` for any return argument you do not need. 4287 4288 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4289 4290 @*/ 4291 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, void **ctx) 4292 { 4293 DM dm; 4294 4295 PetscFunctionBegin; 4296 if (Amat || Pmat) { 4297 SNES snes; 4298 PetscCall(TSGetSNES(ts, &snes)); 4299 PetscCall(SNESSetUpMatrices(snes)); 4300 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4301 } 4302 PetscCall(TSGetDM(ts, &dm)); 4303 PetscCall(DMTSGetRHSJacobian(dm, func, ctx)); 4304 PetscFunctionReturn(PETSC_SUCCESS); 4305 } 4306 4307 /*@C 4308 TSGetIJacobian - Returns the implicit Jacobian at the present timestep. 4309 4310 Not Collective, but parallel objects are returned if ts is parallel 4311 4312 Input Parameter: 4313 . ts - The `TS` context obtained from `TSCreate()` 4314 4315 Output Parameters: 4316 + Amat - The (approximate) Jacobian of F(t,U,U_t) 4317 . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat` 4318 . f - The function to compute the matrices 4319 - ctx - User-defined context for Jacobian evaluation routine 4320 4321 Level: advanced 4322 4323 Note: 4324 You can pass in `NULL` for any return argument you do not need. 4325 4326 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4327 @*/ 4328 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, void **ctx) 4329 { 4330 DM dm; 4331 4332 PetscFunctionBegin; 4333 if (Amat || Pmat) { 4334 SNES snes; 4335 PetscCall(TSGetSNES(ts, &snes)); 4336 PetscCall(SNESSetUpMatrices(snes)); 4337 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4338 } 4339 PetscCall(TSGetDM(ts, &dm)); 4340 PetscCall(DMTSGetIJacobian(dm, f, ctx)); 4341 PetscFunctionReturn(PETSC_SUCCESS); 4342 } 4343 4344 #include <petsc/private/dmimpl.h> 4345 /*@ 4346 TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS` 4347 4348 Logically Collective 4349 4350 Input Parameters: 4351 + ts - the `TS` integrator object 4352 - dm - the dm, cannot be `NULL` 4353 4354 Level: intermediate 4355 4356 Notes: 4357 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 4358 even when not using interfaces like `DMTSSetIFunction()`. Use `DMClone()` to get a distinct `DM` when solving 4359 different problems using the same function space. 4360 4361 .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()` 4362 @*/ 4363 PetscErrorCode TSSetDM(TS ts, DM dm) 4364 { 4365 SNES snes; 4366 DMTS tsdm; 4367 4368 PetscFunctionBegin; 4369 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4370 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 4371 PetscCall(PetscObjectReference((PetscObject)dm)); 4372 if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */ 4373 if (ts->dm->dmts && !dm->dmts) { 4374 PetscCall(DMCopyDMTS(ts->dm, dm)); 4375 PetscCall(DMGetDMTS(ts->dm, &tsdm)); 4376 /* Grant write privileges to the replacement DM */ 4377 if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm; 4378 } 4379 PetscCall(DMDestroy(&ts->dm)); 4380 } 4381 ts->dm = dm; 4382 4383 PetscCall(TSGetSNES(ts, &snes)); 4384 PetscCall(SNESSetDM(snes, dm)); 4385 PetscFunctionReturn(PETSC_SUCCESS); 4386 } 4387 4388 /*@ 4389 TSGetDM - Gets the `DM` that may be used by some preconditioners 4390 4391 Not Collective 4392 4393 Input Parameter: 4394 . ts - the `TS` 4395 4396 Output Parameter: 4397 . dm - the `DM` 4398 4399 Level: intermediate 4400 4401 .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()` 4402 @*/ 4403 PetscErrorCode TSGetDM(TS ts, DM *dm) 4404 { 4405 PetscFunctionBegin; 4406 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4407 if (!ts->dm) { 4408 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm)); 4409 if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm)); 4410 } 4411 *dm = ts->dm; 4412 PetscFunctionReturn(PETSC_SUCCESS); 4413 } 4414 4415 /*@ 4416 SNESTSFormFunction - Function to evaluate nonlinear residual 4417 4418 Logically Collective 4419 4420 Input Parameters: 4421 + snes - nonlinear solver 4422 . U - the current state at which to evaluate the residual 4423 - ctx - user context, must be a TS 4424 4425 Output Parameter: 4426 . F - the nonlinear residual 4427 4428 Level: advanced 4429 4430 Note: 4431 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4432 It is most frequently passed to `MatFDColoringSetFunction()`. 4433 4434 .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()` 4435 @*/ 4436 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx) 4437 { 4438 TS ts = (TS)ctx; 4439 4440 PetscFunctionBegin; 4441 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4442 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4443 PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 4444 PetscValidHeaderSpecific(ts, TS_CLASSID, 4); 4445 PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name); 4446 PetscCall((*ts->ops->snesfunction)(snes, U, F, ts)); 4447 PetscFunctionReturn(PETSC_SUCCESS); 4448 } 4449 4450 /*@ 4451 SNESTSFormJacobian - Function to evaluate the Jacobian 4452 4453 Collective 4454 4455 Input Parameters: 4456 + snes - nonlinear solver 4457 . U - the current state at which to evaluate the residual 4458 - ctx - user context, must be a `TS` 4459 4460 Output Parameters: 4461 + A - the Jacobian 4462 - B - the preconditioning matrix (may be the same as A) 4463 4464 Level: developer 4465 4466 Note: 4467 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4468 4469 .seealso: [](ch_ts), `SNESSetJacobian()` 4470 @*/ 4471 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx) 4472 { 4473 TS ts = (TS)ctx; 4474 4475 PetscFunctionBegin; 4476 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4477 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4478 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 4479 PetscValidHeaderSpecific(B, MAT_CLASSID, 4); 4480 PetscValidHeaderSpecific(ts, TS_CLASSID, 5); 4481 PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name); 4482 PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts)); 4483 PetscFunctionReturn(PETSC_SUCCESS); 4484 } 4485 4486 /*@C 4487 TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only 4488 4489 Collective 4490 4491 Input Parameters: 4492 + ts - time stepping context 4493 . t - time at which to evaluate 4494 . U - state at which to evaluate 4495 - ctx - context 4496 4497 Output Parameter: 4498 . F - right-hand side 4499 4500 Level: intermediate 4501 4502 Note: 4503 This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems. 4504 The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`. 4505 4506 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 4507 @*/ 4508 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx) 4509 { 4510 Mat Arhs, Brhs; 4511 4512 PetscFunctionBegin; 4513 PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs)); 4514 /* undo the damage caused by shifting */ 4515 PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs)); 4516 PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs)); 4517 PetscCall(MatMult(Arhs, U, F)); 4518 PetscFunctionReturn(PETSC_SUCCESS); 4519 } 4520 4521 /*@C 4522 TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent. 4523 4524 Collective 4525 4526 Input Parameters: 4527 + ts - time stepping context 4528 . t - time at which to evaluate 4529 . U - state at which to evaluate 4530 - ctx - context 4531 4532 Output Parameters: 4533 + A - pointer to operator 4534 - B - pointer to preconditioning matrix 4535 4536 Level: intermediate 4537 4538 Note: 4539 This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems. 4540 4541 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()` 4542 @*/ 4543 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx) 4544 { 4545 PetscFunctionBegin; 4546 PetscFunctionReturn(PETSC_SUCCESS); 4547 } 4548 4549 /*@C 4550 TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only 4551 4552 Collective 4553 4554 Input Parameters: 4555 + ts - time stepping context 4556 . t - time at which to evaluate 4557 . U - state at which to evaluate 4558 . Udot - time derivative of state vector 4559 - ctx - context 4560 4561 Output Parameter: 4562 . F - left hand side 4563 4564 Level: intermediate 4565 4566 Notes: 4567 The assumption here is that the left hand side is of the form A*Udot (and not A*Udot + B*U). For other cases, the 4568 user is required to write their own `TSComputeIFunction()`. 4569 This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems. 4570 The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`. 4571 4572 Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U 4573 4574 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()` 4575 @*/ 4576 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx) 4577 { 4578 Mat A, B; 4579 4580 PetscFunctionBegin; 4581 PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL)); 4582 PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE)); 4583 PetscCall(MatMult(A, Udot, F)); 4584 PetscFunctionReturn(PETSC_SUCCESS); 4585 } 4586 4587 /*@C 4588 TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE 4589 4590 Collective 4591 4592 Input Parameters: 4593 + ts - time stepping context 4594 . t - time at which to evaluate 4595 . U - state at which to evaluate 4596 . Udot - time derivative of state vector 4597 . shift - shift to apply 4598 - ctx - context 4599 4600 Output Parameters: 4601 + A - pointer to operator 4602 - B - pointer to matrix from which the preconditioner is built (often `A`) 4603 4604 Level: advanced 4605 4606 Notes: 4607 This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems. 4608 4609 It is only appropriate for problems of the form 4610 4611 $$ 4612 M \dot{U} = F(U,t) 4613 $$ 4614 4615 where M is constant and F is non-stiff. The user must pass M to `TSSetIJacobian()`. The current implementation only 4616 works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing 4617 an implicit operator of the form 4618 4619 $$ 4620 shift*M + J 4621 $$ 4622 4623 where J is the Jacobian of -F(U). Support may be added in a future version of PETSc, but for now, the user must store 4624 a copy of M or reassemble it when requested. 4625 4626 .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()` 4627 @*/ 4628 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx) 4629 { 4630 PetscFunctionBegin; 4631 PetscCall(MatScale(A, shift / ts->ijacobian.shift)); 4632 ts->ijacobian.shift = shift; 4633 PetscFunctionReturn(PETSC_SUCCESS); 4634 } 4635 4636 /*@ 4637 TSGetEquationType - Gets the type of the equation that `TS` is solving. 4638 4639 Not Collective 4640 4641 Input Parameter: 4642 . ts - the `TS` context 4643 4644 Output Parameter: 4645 . equation_type - see `TSEquationType` 4646 4647 Level: beginner 4648 4649 .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType` 4650 @*/ 4651 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type) 4652 { 4653 PetscFunctionBegin; 4654 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4655 PetscAssertPointer(equation_type, 2); 4656 *equation_type = ts->equation_type; 4657 PetscFunctionReturn(PETSC_SUCCESS); 4658 } 4659 4660 /*@ 4661 TSSetEquationType - Sets the type of the equation that `TS` is solving. 4662 4663 Not Collective 4664 4665 Input Parameters: 4666 + ts - the `TS` context 4667 - equation_type - see `TSEquationType` 4668 4669 Level: advanced 4670 4671 .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType` 4672 @*/ 4673 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type) 4674 { 4675 PetscFunctionBegin; 4676 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4677 ts->equation_type = equation_type; 4678 PetscFunctionReturn(PETSC_SUCCESS); 4679 } 4680 4681 /*@ 4682 TSGetConvergedReason - Gets the reason the `TS` iteration was stopped. 4683 4684 Not Collective 4685 4686 Input Parameter: 4687 . ts - the `TS` context 4688 4689 Output Parameter: 4690 . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4691 manual pages for the individual convergence tests for complete lists 4692 4693 Level: beginner 4694 4695 Note: 4696 Can only be called after the call to `TSSolve()` is complete. 4697 4698 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4699 @*/ 4700 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason) 4701 { 4702 PetscFunctionBegin; 4703 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4704 PetscAssertPointer(reason, 2); 4705 *reason = ts->reason; 4706 PetscFunctionReturn(PETSC_SUCCESS); 4707 } 4708 4709 /*@ 4710 TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`. 4711 4712 Logically Collective; reason must contain common value 4713 4714 Input Parameters: 4715 + ts - the `TS` context 4716 - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4717 manual pages for the individual convergence tests for complete lists 4718 4719 Level: advanced 4720 4721 Note: 4722 Can only be called while `TSSolve()` is active. 4723 4724 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4725 @*/ 4726 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason) 4727 { 4728 PetscFunctionBegin; 4729 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4730 ts->reason = reason; 4731 PetscFunctionReturn(PETSC_SUCCESS); 4732 } 4733 4734 /*@ 4735 TSGetSolveTime - Gets the time after a call to `TSSolve()` 4736 4737 Not Collective 4738 4739 Input Parameter: 4740 . ts - the `TS` context 4741 4742 Output Parameter: 4743 . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()` 4744 4745 Level: beginner 4746 4747 Note: 4748 Can only be called after the call to `TSSolve()` is complete. 4749 4750 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4751 @*/ 4752 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime) 4753 { 4754 PetscFunctionBegin; 4755 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4756 PetscAssertPointer(ftime, 2); 4757 *ftime = ts->solvetime; 4758 PetscFunctionReturn(PETSC_SUCCESS); 4759 } 4760 4761 /*@ 4762 TSGetSNESIterations - Gets the total number of nonlinear iterations 4763 used by the time integrator. 4764 4765 Not Collective 4766 4767 Input Parameter: 4768 . ts - `TS` context 4769 4770 Output Parameter: 4771 . nits - number of nonlinear iterations 4772 4773 Level: intermediate 4774 4775 Note: 4776 This counter is reset to zero for each successive call to `TSSolve()`. 4777 4778 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()` 4779 @*/ 4780 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits) 4781 { 4782 PetscFunctionBegin; 4783 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4784 PetscAssertPointer(nits, 2); 4785 *nits = ts->snes_its; 4786 PetscFunctionReturn(PETSC_SUCCESS); 4787 } 4788 4789 /*@ 4790 TSGetKSPIterations - Gets the total number of linear iterations 4791 used by the time integrator. 4792 4793 Not Collective 4794 4795 Input Parameter: 4796 . ts - `TS` context 4797 4798 Output Parameter: 4799 . lits - number of linear iterations 4800 4801 Level: intermediate 4802 4803 Note: 4804 This counter is reset to zero for each successive call to `TSSolve()`. 4805 4806 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `SNESGetKSPIterations()` 4807 @*/ 4808 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits) 4809 { 4810 PetscFunctionBegin; 4811 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4812 PetscAssertPointer(lits, 2); 4813 *lits = ts->ksp_its; 4814 PetscFunctionReturn(PETSC_SUCCESS); 4815 } 4816 4817 /*@ 4818 TSGetStepRejections - Gets the total number of rejected steps. 4819 4820 Not Collective 4821 4822 Input Parameter: 4823 . ts - `TS` context 4824 4825 Output Parameter: 4826 . rejects - number of steps rejected 4827 4828 Level: intermediate 4829 4830 Note: 4831 This counter is reset to zero for each successive call to `TSSolve()`. 4832 4833 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()` 4834 @*/ 4835 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects) 4836 { 4837 PetscFunctionBegin; 4838 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4839 PetscAssertPointer(rejects, 2); 4840 *rejects = ts->reject; 4841 PetscFunctionReturn(PETSC_SUCCESS); 4842 } 4843 4844 /*@ 4845 TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS` 4846 4847 Not Collective 4848 4849 Input Parameter: 4850 . ts - `TS` context 4851 4852 Output Parameter: 4853 . fails - number of failed nonlinear solves 4854 4855 Level: intermediate 4856 4857 Note: 4858 This counter is reset to zero for each successive call to `TSSolve()`. 4859 4860 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()` 4861 @*/ 4862 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails) 4863 { 4864 PetscFunctionBegin; 4865 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4866 PetscAssertPointer(fails, 2); 4867 *fails = ts->num_snes_failures; 4868 PetscFunctionReturn(PETSC_SUCCESS); 4869 } 4870 4871 /*@ 4872 TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails 4873 4874 Not Collective 4875 4876 Input Parameters: 4877 + ts - `TS` context 4878 - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited 4879 4880 Options Database Key: 4881 . -ts_max_reject - Maximum number of step rejections before a step fails 4882 4883 Level: intermediate 4884 4885 Developer Note: 4886 The options database name is incorrect. 4887 4888 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4889 @*/ 4890 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects) 4891 { 4892 PetscFunctionBegin; 4893 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4894 if (rejects == PETSC_UNLIMITED || rejects == -1) { 4895 ts->max_reject = PETSC_UNLIMITED; 4896 } else { 4897 PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections"); 4898 ts->max_reject = rejects; 4899 } 4900 PetscFunctionReturn(PETSC_SUCCESS); 4901 } 4902 4903 /*@ 4904 TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves 4905 4906 Not Collective 4907 4908 Input Parameters: 4909 + ts - `TS` context 4910 - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures. 4911 4912 Options Database Key: 4913 . -ts_max_snes_failures - Maximum number of nonlinear solve failures 4914 4915 Level: intermediate 4916 4917 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()` 4918 @*/ 4919 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails) 4920 { 4921 PetscFunctionBegin; 4922 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4923 if (fails == PETSC_UNLIMITED || fails == -1) { 4924 ts->max_snes_failures = PETSC_UNLIMITED; 4925 } else { 4926 PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 4927 ts->max_snes_failures = fails; 4928 } 4929 PetscFunctionReturn(PETSC_SUCCESS); 4930 } 4931 4932 /*@ 4933 TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()` 4934 4935 Not Collective 4936 4937 Input Parameters: 4938 + ts - `TS` context 4939 - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure 4940 4941 Options Database Key: 4942 . -ts_error_if_step_fails - Error if no step succeeds 4943 4944 Level: intermediate 4945 4946 .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()` 4947 @*/ 4948 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err) 4949 { 4950 PetscFunctionBegin; 4951 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4952 ts->errorifstepfailed = err; 4953 PetscFunctionReturn(PETSC_SUCCESS); 4954 } 4955 4956 /*@ 4957 TSGetAdapt - Get the adaptive controller context for the current method 4958 4959 Collective if controller has not yet been created 4960 4961 Input Parameter: 4962 . ts - time stepping context 4963 4964 Output Parameter: 4965 . adapt - adaptive controller 4966 4967 Level: intermediate 4968 4969 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()` 4970 @*/ 4971 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt) 4972 { 4973 PetscFunctionBegin; 4974 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4975 PetscAssertPointer(adapt, 2); 4976 if (!ts->adapt) { 4977 PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt)); 4978 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1)); 4979 } 4980 *adapt = ts->adapt; 4981 PetscFunctionReturn(PETSC_SUCCESS); 4982 } 4983 4984 /*@ 4985 TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller 4986 4987 Logically Collective 4988 4989 Input Parameters: 4990 + ts - time integration context 4991 . atol - scalar absolute tolerances 4992 . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present 4993 . rtol - scalar relative tolerances 4994 - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present 4995 4996 Options Database Keys: 4997 + -ts_rtol <rtol> - relative tolerance for local truncation error 4998 - -ts_atol <atol> - Absolute tolerance for local truncation error 4999 5000 Level: beginner 5001 5002 Notes: 5003 `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value 5004 or the default value from when the object's type was set. 5005 5006 With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error 5007 (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be 5008 computed only for the differential or the algebraic part then this can be done using the vector of 5009 tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the 5010 differential part and infinity for the algebraic part, the LTE calculation will include only the 5011 differential variables. 5012 5013 Fortran Note: 5014 Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`. 5015 5016 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()` 5017 @*/ 5018 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol) 5019 { 5020 PetscFunctionBegin; 5021 if (atol == (PetscReal)PETSC_DETERMINE) { 5022 ts->atol = atol = ts->default_atol; 5023 } else if (atol != (PetscReal)PETSC_CURRENT) { 5024 PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol); 5025 ts->atol = atol; 5026 } 5027 5028 if (vatol) { 5029 PetscCall(PetscObjectReference((PetscObject)vatol)); 5030 PetscCall(VecDestroy(&ts->vatol)); 5031 ts->vatol = vatol; 5032 } 5033 5034 if (rtol == (PetscReal)PETSC_DETERMINE) { 5035 ts->rtol = atol = ts->default_rtol; 5036 } else if (rtol != (PetscReal)PETSC_CURRENT) { 5037 PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol); 5038 ts->rtol = rtol; 5039 } 5040 5041 if (vrtol) { 5042 PetscCall(PetscObjectReference((PetscObject)vrtol)); 5043 PetscCall(VecDestroy(&ts->vrtol)); 5044 ts->vrtol = vrtol; 5045 } 5046 PetscFunctionReturn(PETSC_SUCCESS); 5047 } 5048 5049 /*@ 5050 TSGetTolerances - Get tolerances for local truncation error when using adaptive controller 5051 5052 Logically Collective 5053 5054 Input Parameter: 5055 . ts - time integration context 5056 5057 Output Parameters: 5058 + atol - scalar absolute tolerances, `NULL` to ignore 5059 . vatol - vector of absolute tolerances, `NULL` to ignore 5060 . rtol - scalar relative tolerances, `NULL` to ignore 5061 - vrtol - vector of relative tolerances, `NULL` to ignore 5062 5063 Level: beginner 5064 5065 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()` 5066 @*/ 5067 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol) 5068 { 5069 PetscFunctionBegin; 5070 if (atol) *atol = ts->atol; 5071 if (vatol) *vatol = ts->vatol; 5072 if (rtol) *rtol = ts->rtol; 5073 if (vrtol) *vrtol = ts->vrtol; 5074 PetscFunctionReturn(PETSC_SUCCESS); 5075 } 5076 5077 /*@ 5078 TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances 5079 5080 Collective 5081 5082 Input Parameters: 5083 + ts - time stepping context 5084 . U - state vector, usually ts->vec_sol 5085 . Y - state vector to be compared to U 5086 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5087 5088 Output Parameters: 5089 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5090 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5091 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5092 5093 Options Database Key: 5094 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5095 5096 Level: developer 5097 5098 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()` 5099 @*/ 5100 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5101 { 5102 PetscInt norma_loc, norm_loc, normr_loc; 5103 5104 PetscFunctionBegin; 5105 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5106 PetscCall(VecErrorWeightedNorms(U, Y, NULL, wnormtype, ts->atol, ts->vatol, ts->rtol, ts->vrtol, ts->adapt->ignore_max, norm, &norm_loc, norma, &norma_loc, normr, &normr_loc)); 5107 if (wnormtype == NORM_2) { 5108 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5109 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5110 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5111 } 5112 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5113 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5114 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5115 PetscFunctionReturn(PETSC_SUCCESS); 5116 } 5117 5118 /*@ 5119 TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances 5120 5121 Collective 5122 5123 Input Parameters: 5124 + ts - time stepping context 5125 . E - error vector 5126 . U - state vector, usually ts->vec_sol 5127 . Y - state vector, previous time step 5128 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5129 5130 Output Parameters: 5131 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5132 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5133 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5134 5135 Options Database Key: 5136 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5137 5138 Level: developer 5139 5140 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()` 5141 @*/ 5142 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5143 { 5144 PetscInt norma_loc, norm_loc, normr_loc; 5145 5146 PetscFunctionBegin; 5147 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5148 PetscCall(VecErrorWeightedNorms(U, Y, E, wnormtype, ts->atol, ts->vatol, ts->rtol, ts->vrtol, ts->adapt->ignore_max, norm, &norm_loc, norma, &norma_loc, normr, &normr_loc)); 5149 if (wnormtype == NORM_2) { 5150 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5151 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5152 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5153 } 5154 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5155 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5156 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5157 PetscFunctionReturn(PETSC_SUCCESS); 5158 } 5159 5160 /*@ 5161 TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler 5162 5163 Logically Collective 5164 5165 Input Parameters: 5166 + ts - time stepping context 5167 - cfltime - maximum stable time step if using forward Euler (value can be different on each process) 5168 5169 Note: 5170 After calling this function, the global CFL time can be obtained by calling TSGetCFLTime() 5171 5172 Level: intermediate 5173 5174 .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL` 5175 @*/ 5176 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime) 5177 { 5178 PetscFunctionBegin; 5179 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5180 ts->cfltime_local = cfltime; 5181 ts->cfltime = -1.; 5182 PetscFunctionReturn(PETSC_SUCCESS); 5183 } 5184 5185 /*@ 5186 TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler 5187 5188 Collective 5189 5190 Input Parameter: 5191 . ts - time stepping context 5192 5193 Output Parameter: 5194 . cfltime - maximum stable time step for forward Euler 5195 5196 Level: advanced 5197 5198 .seealso: [](ch_ts), `TSSetCFLTimeLocal()` 5199 @*/ 5200 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime) 5201 { 5202 PetscFunctionBegin; 5203 if (ts->cfltime < 0) PetscCall(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts))); 5204 *cfltime = ts->cfltime; 5205 PetscFunctionReturn(PETSC_SUCCESS); 5206 } 5207 5208 /*@ 5209 TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu 5210 5211 Input Parameters: 5212 + ts - the `TS` context. 5213 . xl - lower bound. 5214 - xu - upper bound. 5215 5216 Level: advanced 5217 5218 Note: 5219 If this routine is not called then the lower and upper bounds are set to 5220 `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`. 5221 5222 .seealso: [](ch_ts), `TS` 5223 @*/ 5224 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) 5225 { 5226 SNES snes; 5227 5228 PetscFunctionBegin; 5229 PetscCall(TSGetSNES(ts, &snes)); 5230 PetscCall(SNESVISetVariableBounds(snes, xl, xu)); 5231 PetscFunctionReturn(PETSC_SUCCESS); 5232 } 5233 5234 /*@ 5235 TSComputeLinearStability - computes the linear stability function at a point 5236 5237 Collective 5238 5239 Input Parameters: 5240 + ts - the `TS` context 5241 . xr - real part of input argument 5242 - xi - imaginary part of input argument 5243 5244 Output Parameters: 5245 + yr - real part of function value 5246 - yi - imaginary part of function value 5247 5248 Level: developer 5249 5250 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()` 5251 @*/ 5252 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) 5253 { 5254 PetscFunctionBegin; 5255 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5256 PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi); 5257 PetscFunctionReturn(PETSC_SUCCESS); 5258 } 5259 5260 /*@ 5261 TSRestartStep - Flags the solver to restart the next step 5262 5263 Collective 5264 5265 Input Parameter: 5266 . ts - the `TS` context obtained from `TSCreate()` 5267 5268 Level: advanced 5269 5270 Notes: 5271 Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of 5272 discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution 5273 vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For 5274 the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce 5275 discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with 5276 discontinuous source terms). 5277 5278 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()` 5279 @*/ 5280 PetscErrorCode TSRestartStep(TS ts) 5281 { 5282 PetscFunctionBegin; 5283 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5284 ts->steprestart = PETSC_TRUE; 5285 PetscFunctionReturn(PETSC_SUCCESS); 5286 } 5287 5288 /*@ 5289 TSRollBack - Rolls back one time step 5290 5291 Collective 5292 5293 Input Parameter: 5294 . ts - the `TS` context obtained from `TSCreate()` 5295 5296 Level: advanced 5297 5298 .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()` 5299 @*/ 5300 PetscErrorCode TSRollBack(TS ts) 5301 { 5302 PetscFunctionBegin; 5303 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5304 PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called"); 5305 PetscTryTypeMethod(ts, rollback); 5306 PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol)); 5307 ts->time_step = ts->ptime - ts->ptime_prev; 5308 ts->ptime = ts->ptime_prev; 5309 ts->ptime_prev = ts->ptime_prev_rollback; 5310 ts->steps--; 5311 ts->steprollback = PETSC_TRUE; 5312 PetscFunctionReturn(PETSC_SUCCESS); 5313 } 5314 5315 /*@ 5316 TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step 5317 5318 Not collective 5319 5320 Input Parameter: 5321 . ts - the `TS` context obtained from `TSCreate()` 5322 5323 Output Parameter: 5324 . flg - the rollback flag 5325 5326 Level: advanced 5327 5328 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()` 5329 @*/ 5330 PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg) 5331 { 5332 PetscFunctionBegin; 5333 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5334 PetscAssertPointer(flg, 2); 5335 *flg = ts->steprollback; 5336 PetscFunctionReturn(PETSC_SUCCESS); 5337 } 5338 5339 /*@ 5340 TSGetStepResize - Get the internal flag indicating if the current step is after a resize. 5341 5342 Not collective 5343 5344 Input Parameter: 5345 . ts - the `TS` context obtained from `TSCreate()` 5346 5347 Output Parameter: 5348 . flg - the resize flag 5349 5350 Level: advanced 5351 5352 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()` 5353 @*/ 5354 PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg) 5355 { 5356 PetscFunctionBegin; 5357 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5358 PetscAssertPointer(flg, 2); 5359 *flg = ts->stepresize; 5360 PetscFunctionReturn(PETSC_SUCCESS); 5361 } 5362 5363 /*@ 5364 TSGetStages - Get the number of stages and stage values 5365 5366 Input Parameter: 5367 . ts - the `TS` context obtained from `TSCreate()` 5368 5369 Output Parameters: 5370 + ns - the number of stages 5371 - Y - the current stage vectors 5372 5373 Level: advanced 5374 5375 Note: 5376 Both `ns` and `Y` can be `NULL`. 5377 5378 .seealso: [](ch_ts), `TS`, `TSCreate()` 5379 @*/ 5380 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y) 5381 { 5382 PetscFunctionBegin; 5383 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5384 if (ns) PetscAssertPointer(ns, 2); 5385 if (Y) PetscAssertPointer(Y, 3); 5386 if (!ts->ops->getstages) { 5387 if (ns) *ns = 0; 5388 if (Y) *Y = NULL; 5389 } else PetscUseTypeMethod(ts, getstages, ns, Y); 5390 PetscFunctionReturn(PETSC_SUCCESS); 5391 } 5392 5393 /*@C 5394 TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity. 5395 5396 Collective 5397 5398 Input Parameters: 5399 + ts - the `TS` context 5400 . t - current timestep 5401 . U - state vector 5402 . Udot - time derivative of state vector 5403 . shift - shift to apply, see note below 5404 - ctx - an optional user context 5405 5406 Output Parameters: 5407 + J - Jacobian matrix (not altered in this routine) 5408 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`) 5409 5410 Level: intermediate 5411 5412 Notes: 5413 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 5414 5415 dF/dU + shift*dF/dUdot 5416 5417 Most users should not need to explicitly call this routine, as it 5418 is used internally within the nonlinear solvers. 5419 5420 This will first try to get the coloring from the `DM`. If the `DM` type has no coloring 5421 routine, then it will try to get the coloring from the matrix. This requires that the 5422 matrix have nonzero entries precomputed. 5423 5424 .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5425 @*/ 5426 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx) 5427 { 5428 SNES snes; 5429 MatFDColoring color; 5430 PetscBool hascolor, matcolor = PETSC_FALSE; 5431 5432 PetscFunctionBegin; 5433 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL)); 5434 PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color)); 5435 if (!color) { 5436 DM dm; 5437 ISColoring iscoloring; 5438 5439 PetscCall(TSGetDM(ts, &dm)); 5440 PetscCall(DMHasColoring(dm, &hascolor)); 5441 if (hascolor && !matcolor) { 5442 PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 5443 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5444 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5445 PetscCall(MatFDColoringSetFromOptions(color)); 5446 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5447 PetscCall(ISColoringDestroy(&iscoloring)); 5448 } else { 5449 MatColoring mc; 5450 5451 PetscCall(MatColoringCreate(B, &mc)); 5452 PetscCall(MatColoringSetDistance(mc, 2)); 5453 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5454 PetscCall(MatColoringSetFromOptions(mc)); 5455 PetscCall(MatColoringApply(mc, &iscoloring)); 5456 PetscCall(MatColoringDestroy(&mc)); 5457 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5458 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5459 PetscCall(MatFDColoringSetFromOptions(color)); 5460 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5461 PetscCall(ISColoringDestroy(&iscoloring)); 5462 } 5463 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color)); 5464 PetscCall(PetscObjectDereference((PetscObject)color)); 5465 } 5466 PetscCall(TSGetSNES(ts, &snes)); 5467 PetscCall(MatFDColoringApply(B, color, U, snes)); 5468 if (J != B) { 5469 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 5470 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 5471 } 5472 PetscFunctionReturn(PETSC_SUCCESS); 5473 } 5474 5475 /*@C 5476 TSSetFunctionDomainError - Set a function that tests if the current state vector is valid 5477 5478 Input Parameters: 5479 + ts - the `TS` context 5480 - func - function called within `TSFunctionDomainError()` 5481 5482 Calling sequence of `func`: 5483 + ts - the `TS` context 5484 . time - the current time (of the stage) 5485 . state - the state to check if it is valid 5486 - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable 5487 5488 Level: intermediate 5489 5490 Notes: 5491 If an implicit ODE solver is being used then, in addition to providing this routine, the 5492 user's code should call `SNESSetFunctionDomainError()` when domain errors occur during 5493 function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`. 5494 Use `TSGetSNES()` to obtain the `SNES` object 5495 5496 Developer Notes: 5497 The naming of this function is inconsistent with the `SNESSetFunctionDomainError()` 5498 since one takes a function pointer and the other does not. 5499 5500 .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()` 5501 @*/ 5502 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept)) 5503 { 5504 PetscFunctionBegin; 5505 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5506 ts->functiondomainerror = func; 5507 PetscFunctionReturn(PETSC_SUCCESS); 5508 } 5509 5510 /*@ 5511 TSFunctionDomainError - Checks if the current state is valid 5512 5513 Input Parameters: 5514 + ts - the `TS` context 5515 . stagetime - time of the simulation 5516 - Y - state vector to check. 5517 5518 Output Parameter: 5519 . accept - Set to `PETSC_FALSE` if the current state vector is valid. 5520 5521 Level: developer 5522 5523 Note: 5524 This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`) 5525 to check if the current state is valid. 5526 5527 .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()` 5528 @*/ 5529 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept) 5530 { 5531 PetscFunctionBegin; 5532 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5533 *accept = PETSC_TRUE; 5534 if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept)); 5535 PetscFunctionReturn(PETSC_SUCCESS); 5536 } 5537 5538 /*@ 5539 TSClone - This function clones a time step `TS` object. 5540 5541 Collective 5542 5543 Input Parameter: 5544 . tsin - The input `TS` 5545 5546 Output Parameter: 5547 . tsout - The output `TS` (cloned) 5548 5549 Level: developer 5550 5551 Notes: 5552 This function is used to create a clone of a `TS` object. It is used in `TSARKIMEX` for initializing the slope for first stage explicit methods. 5553 It will likely be replaced in the future with a mechanism of switching methods on the fly. 5554 5555 When using `TSDestroy()` on a clone the user has to first reset the correct `TS` reference in the embedded `SNES` object: e.g., by running 5556 .vb 5557 SNES snes_dup = NULL; 5558 TSGetSNES(ts,&snes_dup); 5559 TSSetSNES(ts,snes_dup); 5560 .ve 5561 5562 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()` 5563 @*/ 5564 PetscErrorCode TSClone(TS tsin, TS *tsout) 5565 { 5566 TS t; 5567 SNES snes_start; 5568 DM dm; 5569 TSType type; 5570 5571 PetscFunctionBegin; 5572 PetscAssertPointer(tsin, 1); 5573 *tsout = NULL; 5574 5575 PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView)); 5576 5577 /* General TS description */ 5578 t->numbermonitors = 0; 5579 t->monitorFrequency = 1; 5580 t->setupcalled = 0; 5581 t->ksp_its = 0; 5582 t->snes_its = 0; 5583 t->nwork = 0; 5584 t->rhsjacobian.time = PETSC_MIN_REAL; 5585 t->rhsjacobian.scale = 1.; 5586 t->ijacobian.shift = 1.; 5587 5588 PetscCall(TSGetSNES(tsin, &snes_start)); 5589 PetscCall(TSSetSNES(t, snes_start)); 5590 5591 PetscCall(TSGetDM(tsin, &dm)); 5592 PetscCall(TSSetDM(t, dm)); 5593 5594 t->adapt = tsin->adapt; 5595 PetscCall(PetscObjectReference((PetscObject)t->adapt)); 5596 5597 t->trajectory = tsin->trajectory; 5598 PetscCall(PetscObjectReference((PetscObject)t->trajectory)); 5599 5600 t->event = tsin->event; 5601 if (t->event) t->event->refct++; 5602 5603 t->problem_type = tsin->problem_type; 5604 t->ptime = tsin->ptime; 5605 t->ptime_prev = tsin->ptime_prev; 5606 t->time_step = tsin->time_step; 5607 t->max_time = tsin->max_time; 5608 t->steps = tsin->steps; 5609 t->max_steps = tsin->max_steps; 5610 t->equation_type = tsin->equation_type; 5611 t->atol = tsin->atol; 5612 t->rtol = tsin->rtol; 5613 t->max_snes_failures = tsin->max_snes_failures; 5614 t->max_reject = tsin->max_reject; 5615 t->errorifstepfailed = tsin->errorifstepfailed; 5616 5617 PetscCall(TSGetType(tsin, &type)); 5618 PetscCall(TSSetType(t, type)); 5619 5620 t->vec_sol = NULL; 5621 5622 t->cfltime = tsin->cfltime; 5623 t->cfltime_local = tsin->cfltime_local; 5624 t->exact_final_time = tsin->exact_final_time; 5625 5626 t->ops[0] = tsin->ops[0]; 5627 5628 if (((PetscObject)tsin)->fortran_func_pointers) { 5629 PetscInt i; 5630 PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers)); 5631 for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i]; 5632 } 5633 *tsout = t; 5634 PetscFunctionReturn(PETSC_SUCCESS); 5635 } 5636 5637 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y) 5638 { 5639 TS ts = (TS)ctx; 5640 5641 PetscFunctionBegin; 5642 PetscCall(TSComputeRHSFunction(ts, 0, x, y)); 5643 PetscFunctionReturn(PETSC_SUCCESS); 5644 } 5645 5646 /*@ 5647 TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5648 5649 Logically Collective 5650 5651 Input Parameter: 5652 . ts - the time stepping routine 5653 5654 Output Parameter: 5655 . flg - `PETSC_TRUE` if the multiply is likely correct 5656 5657 Options Database Key: 5658 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator 5659 5660 Level: advanced 5661 5662 Note: 5663 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5664 5665 .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()` 5666 @*/ 5667 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg) 5668 { 5669 Mat J, B; 5670 TSRHSJacobianFn *func; 5671 void *ctx; 5672 5673 PetscFunctionBegin; 5674 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5675 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5676 PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5677 PetscFunctionReturn(PETSC_SUCCESS); 5678 } 5679 5680 /*@ 5681 TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5682 5683 Logically Collective 5684 5685 Input Parameter: 5686 . ts - the time stepping routine 5687 5688 Output Parameter: 5689 . flg - `PETSC_TRUE` if the multiply is likely correct 5690 5691 Options Database Key: 5692 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator 5693 5694 Level: advanced 5695 5696 Notes: 5697 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5698 5699 .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()` 5700 @*/ 5701 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg) 5702 { 5703 Mat J, B; 5704 void *ctx; 5705 TSRHSJacobianFn *func; 5706 5707 PetscFunctionBegin; 5708 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5709 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5710 PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5711 PetscFunctionReturn(PETSC_SUCCESS); 5712 } 5713 5714 /*@ 5715 TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used. 5716 5717 Logically Collective 5718 5719 Input Parameters: 5720 + ts - timestepping context 5721 - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5722 5723 Options Database Key: 5724 . -ts_use_splitrhsfunction - <true,false> 5725 5726 Level: intermediate 5727 5728 Note: 5729 This is only for multirate methods 5730 5731 .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()` 5732 @*/ 5733 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) 5734 { 5735 PetscFunctionBegin; 5736 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5737 ts->use_splitrhsfunction = use_splitrhsfunction; 5738 PetscFunctionReturn(PETSC_SUCCESS); 5739 } 5740 5741 /*@ 5742 TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used. 5743 5744 Not Collective 5745 5746 Input Parameter: 5747 . ts - timestepping context 5748 5749 Output Parameter: 5750 . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5751 5752 Level: intermediate 5753 5754 .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()` 5755 @*/ 5756 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) 5757 { 5758 PetscFunctionBegin; 5759 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5760 *use_splitrhsfunction = ts->use_splitrhsfunction; 5761 PetscFunctionReturn(PETSC_SUCCESS); 5762 } 5763 5764 /*@ 5765 TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix. 5766 5767 Logically Collective 5768 5769 Input Parameters: 5770 + ts - the time-stepper 5771 - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`) 5772 5773 Level: intermediate 5774 5775 Note: 5776 When the relationship between the nonzero structures is known and supplied the solution process can be much faster 5777 5778 .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure` 5779 @*/ 5780 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str) 5781 { 5782 PetscFunctionBegin; 5783 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5784 ts->axpy_pattern = str; 5785 PetscFunctionReturn(PETSC_SUCCESS); 5786 } 5787 5788 /*@ 5789 TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span 5790 5791 Collective 5792 5793 Input Parameters: 5794 + ts - the time-stepper 5795 . n - number of the time points (>=2) 5796 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 5797 5798 Options Database Key: 5799 . -ts_time_span <t0,...tf> - Sets the time span 5800 5801 Level: intermediate 5802 5803 Notes: 5804 The elements in tspan must be all increasing. They correspond to the intermediate points for time integration. 5805 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 5806 The intermediate solutions are saved in a vector array that can be accessed with `TSGetTimeSpanSolutions()`. Thus using time span may 5807 pressure the memory system when using a large number of span points. 5808 5809 .seealso: [](ch_ts), `TS`, `TSGetTimeSpan()`, `TSGetTimeSpanSolutions()` 5810 @*/ 5811 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times) 5812 { 5813 PetscFunctionBegin; 5814 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5815 PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n); 5816 if (ts->tspan && n != ts->tspan->num_span_times) { 5817 PetscCall(PetscFree(ts->tspan->span_times)); 5818 PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol)); 5819 PetscCall(PetscMalloc1(n, &ts->tspan->span_times)); 5820 } 5821 if (!ts->tspan) { 5822 TSTimeSpan tspan; 5823 PetscCall(PetscNew(&tspan)); 5824 PetscCall(PetscMalloc1(n, &tspan->span_times)); 5825 tspan->reltol = 1e-6; 5826 tspan->abstol = 10 * PETSC_MACHINE_EPSILON; 5827 tspan->worktol = 0; 5828 ts->tspan = tspan; 5829 } 5830 ts->tspan->num_span_times = n; 5831 PetscCall(PetscArraycpy(ts->tspan->span_times, span_times, n)); 5832 PetscCall(TSSetTime(ts, ts->tspan->span_times[0])); 5833 PetscCall(TSSetMaxTime(ts, ts->tspan->span_times[n - 1])); 5834 PetscFunctionReturn(PETSC_SUCCESS); 5835 } 5836 5837 /*@C 5838 TSGetTimeSpan - gets the time span set with `TSSetTimeSpan()` 5839 5840 Not Collective 5841 5842 Input Parameter: 5843 . ts - the time-stepper 5844 5845 Output Parameters: 5846 + n - number of the time points (>=2) 5847 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 5848 5849 Level: beginner 5850 5851 Note: 5852 The values obtained are valid until the `TS` object is destroyed. 5853 5854 Both `n` and `span_times` can be `NULL`. 5855 5856 .seealso: [](ch_ts), `TS`, `TSSetTimeSpan()`, `TSGetTimeSpanSolutions()` 5857 @*/ 5858 PetscErrorCode TSGetTimeSpan(TS ts, PetscInt *n, const PetscReal *span_times[]) 5859 { 5860 PetscFunctionBegin; 5861 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5862 if (n) PetscAssertPointer(n, 2); 5863 if (span_times) PetscAssertPointer(span_times, 3); 5864 if (!ts->tspan) { 5865 if (n) *n = 0; 5866 if (span_times) *span_times = NULL; 5867 } else { 5868 if (n) *n = ts->tspan->num_span_times; 5869 if (span_times) *span_times = ts->tspan->span_times; 5870 } 5871 PetscFunctionReturn(PETSC_SUCCESS); 5872 } 5873 5874 /*@ 5875 TSGetTimeSpanSolutions - Get the number of solutions and the solutions at the time points specified by the time span. 5876 5877 Input Parameter: 5878 . ts - the `TS` context obtained from `TSCreate()` 5879 5880 Output Parameters: 5881 + nsol - the number of solutions 5882 - Sols - the solution vectors 5883 5884 Level: intermediate 5885 5886 Notes: 5887 Both `nsol` and `Sols` can be `NULL`. 5888 5889 Some time points in the time span may be skipped by `TS` so that `nsol` is less than the number of points specified by `TSSetTimeSpan()`. 5890 For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain points in the span. 5891 5892 .seealso: [](ch_ts), `TS`, `TSSetTimeSpan()` 5893 @*/ 5894 PetscErrorCode TSGetTimeSpanSolutions(TS ts, PetscInt *nsol, Vec **Sols) 5895 { 5896 PetscFunctionBegin; 5897 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5898 if (nsol) PetscAssertPointer(nsol, 2); 5899 if (Sols) PetscAssertPointer(Sols, 3); 5900 if (!ts->tspan) { 5901 if (nsol) *nsol = 0; 5902 if (Sols) *Sols = NULL; 5903 } else { 5904 if (nsol) *nsol = ts->tspan->spanctr; 5905 if (Sols) *Sols = ts->tspan->vecs_sol; 5906 } 5907 PetscFunctionReturn(PETSC_SUCCESS); 5908 } 5909 5910 /*@ 5911 TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information. 5912 5913 Collective 5914 5915 Input Parameters: 5916 + ts - the `TS` context 5917 . J - Jacobian matrix (not altered in this routine) 5918 - B - newly computed Jacobian matrix to use with preconditioner 5919 5920 Level: intermediate 5921 5922 Notes: 5923 This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains 5924 many constant zeros entries, which is typically the case when the matrix is generated by a `DM` 5925 and multiple fields are involved. 5926 5927 Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity 5928 structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can 5929 usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian. 5930 `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`. 5931 5932 .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5933 @*/ 5934 PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B) 5935 { 5936 MatColoring mc = NULL; 5937 ISColoring iscoloring = NULL; 5938 MatFDColoring matfdcoloring = NULL; 5939 5940 PetscFunctionBegin; 5941 /* Generate new coloring after eliminating zeros in the matrix */ 5942 PetscCall(MatEliminateZeros(B, PETSC_TRUE)); 5943 PetscCall(MatColoringCreate(B, &mc)); 5944 PetscCall(MatColoringSetDistance(mc, 2)); 5945 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5946 PetscCall(MatColoringSetFromOptions(mc)); 5947 PetscCall(MatColoringApply(mc, &iscoloring)); 5948 PetscCall(MatColoringDestroy(&mc)); 5949 /* Replace the old coloring with the new one */ 5950 PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring)); 5951 PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5952 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 5953 PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring)); 5954 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring)); 5955 PetscCall(PetscObjectDereference((PetscObject)matfdcoloring)); 5956 PetscCall(ISColoringDestroy(&iscoloring)); 5957 PetscFunctionReturn(PETSC_SUCCESS); 5958 } 5959