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