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