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