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 PetscCall(TSResizeReset(*ts)); 2709 2710 /* if memory was published with SAWs then destroy it */ 2711 PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts)); 2712 PetscTryTypeMethod((*ts), destroy); 2713 2714 PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory)); 2715 2716 PetscCall(TSAdaptDestroy(&(*ts)->adapt)); 2717 PetscCall(TSEventDestroy(&(*ts)->event)); 2718 2719 PetscCall(SNESDestroy(&(*ts)->snes)); 2720 PetscCall(DMDestroy(&(*ts)->dm)); 2721 PetscCall(TSMonitorCancel((*ts))); 2722 PetscCall(TSAdjointMonitorCancel((*ts))); 2723 2724 PetscCall(TSDestroy(&(*ts)->quadraturets)); 2725 PetscCall(PetscHeaderDestroy(ts)); 2726 PetscFunctionReturn(PETSC_SUCCESS); 2727 } 2728 2729 /*@ 2730 TSGetSNES - Returns the `SNES` (nonlinear solver) associated with 2731 a `TS` (timestepper) context. Valid only for nonlinear problems. 2732 2733 Not Collective, but snes is parallel if ts is parallel 2734 2735 Input Parameter: 2736 . ts - the `TS` context obtained from `TSCreate()` 2737 2738 Output Parameter: 2739 . snes - the nonlinear solver context 2740 2741 Level: beginner 2742 2743 Notes: 2744 The user can then directly manipulate the `SNES` context to set various 2745 options, etc. Likewise, the user can then extract and manipulate the 2746 `KSP`, and `PC` contexts as well. 2747 2748 `TSGetSNES()` does not work for integrators that do not use `SNES`; in 2749 this case `TSGetSNES()` returns `NULL` in `snes`. 2750 2751 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()` 2752 @*/ 2753 PetscErrorCode TSGetSNES(TS ts, SNES *snes) 2754 { 2755 PetscFunctionBegin; 2756 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2757 PetscValidPointer(snes, 2); 2758 if (!ts->snes) { 2759 PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts), &ts->snes)); 2760 PetscCall(PetscObjectSetOptions((PetscObject)ts->snes, ((PetscObject)ts)->options)); 2761 PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts)); 2762 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1)); 2763 if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm)); 2764 if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY)); 2765 } 2766 *snes = ts->snes; 2767 PetscFunctionReturn(PETSC_SUCCESS); 2768 } 2769 2770 /*@ 2771 TSSetSNES - Set the `SNES` (nonlinear solver) to be used by the timestepping context 2772 2773 Collective 2774 2775 Input Parameters: 2776 + ts - the `TS` context obtained from `TSCreate()` 2777 - snes - the nonlinear solver context 2778 2779 Level: developer 2780 2781 Note: 2782 Most users should have the `TS` created by calling `TSGetSNES()` 2783 2784 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()` 2785 @*/ 2786 PetscErrorCode TSSetSNES(TS ts, SNES snes) 2787 { 2788 PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *); 2789 2790 PetscFunctionBegin; 2791 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2792 PetscValidHeaderSpecific(snes, SNES_CLASSID, 2); 2793 PetscCall(PetscObjectReference((PetscObject)snes)); 2794 PetscCall(SNESDestroy(&ts->snes)); 2795 2796 ts->snes = snes; 2797 2798 PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts)); 2799 PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL)); 2800 if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts)); 2801 PetscFunctionReturn(PETSC_SUCCESS); 2802 } 2803 2804 /*@ 2805 TSGetKSP - Returns the `KSP` (linear solver) associated with 2806 a `TS` (timestepper) context. 2807 2808 Not Collective, but `ksp` is parallel if `ts` is parallel 2809 2810 Input Parameter: 2811 . ts - the `TS` context obtained from `TSCreate()` 2812 2813 Output Parameter: 2814 . ksp - the nonlinear solver context 2815 2816 Level: beginner 2817 2818 Notes: 2819 The user can then directly manipulate the `KSP` context to set various 2820 options, etc. Likewise, the user can then extract and manipulate the 2821 `PC` context as well. 2822 2823 `TSGetKSP()` does not work for integrators that do not use `KSP`; 2824 in this case `TSGetKSP()` returns `NULL` in `ksp`. 2825 2826 .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()` 2827 @*/ 2828 PetscErrorCode TSGetKSP(TS ts, KSP *ksp) 2829 { 2830 SNES snes; 2831 2832 PetscFunctionBegin; 2833 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2834 PetscValidPointer(ksp, 2); 2835 PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first"); 2836 PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()"); 2837 PetscCall(TSGetSNES(ts, &snes)); 2838 PetscCall(SNESGetKSP(snes, ksp)); 2839 PetscFunctionReturn(PETSC_SUCCESS); 2840 } 2841 2842 /* ----------- Routines to set solver parameters ---------- */ 2843 2844 /*@ 2845 TSSetMaxSteps - Sets the maximum number of steps to use. 2846 2847 Logically Collective 2848 2849 Input Parameters: 2850 + ts - the `TS` context obtained from `TSCreate()` 2851 - maxsteps - maximum number of steps to use 2852 2853 Options Database Key: 2854 . -ts_max_steps <maxsteps> - Sets maxsteps 2855 2856 Level: intermediate 2857 2858 Note: 2859 The default maximum number of steps is 5000 2860 2861 .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()` 2862 @*/ 2863 PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps) 2864 { 2865 PetscFunctionBegin; 2866 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2867 PetscValidLogicalCollectiveInt(ts, maxsteps, 2); 2868 PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative"); 2869 ts->max_steps = maxsteps; 2870 PetscFunctionReturn(PETSC_SUCCESS); 2871 } 2872 2873 /*@ 2874 TSGetMaxSteps - Gets the maximum number of steps to use. 2875 2876 Not Collective 2877 2878 Input Parameter: 2879 . ts - the `TS` context obtained from `TSCreate()` 2880 2881 Output Parameter: 2882 . maxsteps - maximum number of steps to use 2883 2884 Level: advanced 2885 2886 .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()` 2887 @*/ 2888 PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps) 2889 { 2890 PetscFunctionBegin; 2891 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2892 PetscValidIntPointer(maxsteps, 2); 2893 *maxsteps = ts->max_steps; 2894 PetscFunctionReturn(PETSC_SUCCESS); 2895 } 2896 2897 /*@ 2898 TSSetMaxTime - Sets the maximum (or final) time for timestepping. 2899 2900 Logically Collective 2901 2902 Input Parameters: 2903 + ts - the `TS` context obtained from `TSCreate()` 2904 - maxtime - final time to step to 2905 2906 Options Database Key: 2907 . -ts_max_time <maxtime> - Sets maxtime 2908 2909 Level: intermediate 2910 2911 Notes: 2912 The default maximum time is 5.0 2913 2914 .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()` 2915 @*/ 2916 PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime) 2917 { 2918 PetscFunctionBegin; 2919 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2920 PetscValidLogicalCollectiveReal(ts, maxtime, 2); 2921 ts->max_time = maxtime; 2922 PetscFunctionReturn(PETSC_SUCCESS); 2923 } 2924 2925 /*@ 2926 TSGetMaxTime - Gets the maximum (or final) time for timestepping. 2927 2928 Not Collective 2929 2930 Input Parameter: 2931 . ts - the `TS` context obtained from `TSCreate()` 2932 2933 Output Parameter: 2934 . maxtime - final time to step to 2935 2936 Level: advanced 2937 2938 .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()` 2939 @*/ 2940 PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime) 2941 { 2942 PetscFunctionBegin; 2943 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2944 PetscValidRealPointer(maxtime, 2); 2945 *maxtime = ts->max_time; 2946 PetscFunctionReturn(PETSC_SUCCESS); 2947 } 2948 2949 /*@ 2950 TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`. 2951 2952 Level: deprecated 2953 2954 @*/ 2955 PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step) 2956 { 2957 PetscFunctionBegin; 2958 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2959 PetscCall(TSSetTime(ts, initial_time)); 2960 PetscCall(TSSetTimeStep(ts, time_step)); 2961 PetscFunctionReturn(PETSC_SUCCESS); 2962 } 2963 2964 /*@ 2965 TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`. 2966 2967 Level: deprecated 2968 2969 @*/ 2970 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime) 2971 { 2972 PetscFunctionBegin; 2973 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2974 if (maxsteps) { 2975 PetscValidIntPointer(maxsteps, 2); 2976 *maxsteps = ts->max_steps; 2977 } 2978 if (maxtime) { 2979 PetscValidRealPointer(maxtime, 3); 2980 *maxtime = ts->max_time; 2981 } 2982 PetscFunctionReturn(PETSC_SUCCESS); 2983 } 2984 2985 /*@ 2986 TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`. 2987 2988 Level: deprecated 2989 2990 @*/ 2991 PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime) 2992 { 2993 PetscFunctionBegin; 2994 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2995 PetscValidLogicalCollectiveInt(ts, maxsteps, 2); 2996 PetscValidLogicalCollectiveReal(ts, maxtime, 3); 2997 if (maxsteps >= 0) ts->max_steps = maxsteps; 2998 if (maxtime != (PetscReal)PETSC_DEFAULT) ts->max_time = maxtime; 2999 PetscFunctionReturn(PETSC_SUCCESS); 3000 } 3001 3002 /*@ 3003 TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`. 3004 3005 Level: deprecated 3006 3007 @*/ 3008 PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps) 3009 { 3010 return TSGetStepNumber(ts, steps); 3011 } 3012 3013 /*@ 3014 TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`. 3015 3016 Level: deprecated 3017 3018 @*/ 3019 PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps) 3020 { 3021 return TSGetStepNumber(ts, steps); 3022 } 3023 3024 /*@ 3025 TSSetSolution - Sets the initial solution vector 3026 for use by the `TS` routines. 3027 3028 Logically Collective 3029 3030 Input Parameters: 3031 + ts - the `TS` context obtained from `TSCreate()` 3032 - u - the solution vector 3033 3034 Level: beginner 3035 3036 .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()` 3037 @*/ 3038 PetscErrorCode TSSetSolution(TS ts, Vec u) 3039 { 3040 DM dm; 3041 3042 PetscFunctionBegin; 3043 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3044 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3045 PetscCall(PetscObjectReference((PetscObject)u)); 3046 PetscCall(VecDestroy(&ts->vec_sol)); 3047 ts->vec_sol = u; 3048 3049 PetscCall(TSGetDM(ts, &dm)); 3050 PetscCall(DMShellSetGlobalVector(dm, u)); 3051 PetscFunctionReturn(PETSC_SUCCESS); 3052 } 3053 3054 /*@C 3055 TSSetPreStep - Sets the general-purpose function 3056 called once at the beginning of each time step. 3057 3058 Logically Collective 3059 3060 Input Parameters: 3061 + ts - The `TS` context obtained from `TSCreate()` 3062 - func - The function 3063 3064 Calling sequence of `func`: 3065 .vb 3066 PetscErrorCode func (TS ts) 3067 .ve 3068 3069 Level: intermediate 3070 3071 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()` 3072 @*/ 3073 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS)) 3074 { 3075 PetscFunctionBegin; 3076 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3077 ts->prestep = func; 3078 PetscFunctionReturn(PETSC_SUCCESS); 3079 } 3080 3081 /*@ 3082 TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()` 3083 3084 Collective 3085 3086 Input Parameter: 3087 . ts - The `TS` context obtained from `TSCreate()` 3088 3089 Level: developer 3090 3091 Note: 3092 `TSPreStep()` is typically used within time stepping implementations, 3093 so most users would not generally call this routine themselves. 3094 3095 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()` 3096 @*/ 3097 PetscErrorCode TSPreStep(TS ts) 3098 { 3099 PetscFunctionBegin; 3100 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3101 if (ts->prestep) { 3102 Vec U; 3103 PetscObjectId idprev; 3104 PetscBool sameObject; 3105 PetscObjectState sprev, spost; 3106 3107 PetscCall(TSGetSolution(ts, &U)); 3108 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3109 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3110 PetscCallBack("TS callback preset", (*ts->prestep)(ts)); 3111 PetscCall(TSGetSolution(ts, &U)); 3112 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3113 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3114 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3115 } 3116 PetscFunctionReturn(PETSC_SUCCESS); 3117 } 3118 3119 /*@C 3120 TSSetPreStage - Sets the general-purpose function 3121 called once at the beginning of each stage. 3122 3123 Logically Collective 3124 3125 Input Parameters: 3126 + ts - The `TS` context obtained from `TSCreate()` 3127 - func - The function 3128 3129 Calling sequence of `func`: 3130 .vb 3131 PetscErrorCode func(TS ts, PetscReal stagetime) 3132 .ve 3133 3134 Level: intermediate 3135 3136 Note: 3137 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3138 The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being 3139 attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`. 3140 3141 .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3142 @*/ 3143 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS, PetscReal)) 3144 { 3145 PetscFunctionBegin; 3146 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3147 ts->prestage = func; 3148 PetscFunctionReturn(PETSC_SUCCESS); 3149 } 3150 3151 /*@C 3152 TSSetPostStage - Sets the general-purpose function, provided with `TSSetPostStep()`, 3153 called once at the end of each stage. 3154 3155 Logically Collective 3156 3157 Input Parameters: 3158 + ts - The `TS` context obtained from `TSCreate()` 3159 - func - The function 3160 3161 Calling sequence of `func`: 3162 .vb 3163 PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y) 3164 .ve 3165 3166 Level: intermediate 3167 3168 Note: 3169 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3170 The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being 3171 attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`. 3172 3173 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3174 @*/ 3175 PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS, PetscReal, PetscInt, Vec *)) 3176 { 3177 PetscFunctionBegin; 3178 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3179 ts->poststage = func; 3180 PetscFunctionReturn(PETSC_SUCCESS); 3181 } 3182 3183 /*@C 3184 TSSetPostEvaluate - Sets the general-purpose function 3185 called once at the end of each step evaluation. 3186 3187 Logically Collective 3188 3189 Input Parameters: 3190 + ts - The `TS` context obtained from `TSCreate()` 3191 - func - The function 3192 3193 Calling sequence of `func`: 3194 .vb 3195 PetscErrorCode func(TS ts) 3196 .ve 3197 3198 Level: intermediate 3199 3200 Note: 3201 Semantically, `TSSetPostEvaluate()` differs from `TSSetPostStep()` since the function it sets is called before event-handling 3202 thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, `TSPostStep()` 3203 may be passed a different solution, possibly changed by the event handler. `TSPostEvaluate()` is called after the next step 3204 solution is evaluated allowing to modify it, if need be. The solution can be obtained with `TSGetSolution()`, the time step 3205 with `TSGetTimeStep()`, and the time at the start of the step is available via `TSGetTime()` 3206 3207 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3208 @*/ 3209 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS)) 3210 { 3211 PetscFunctionBegin; 3212 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3213 ts->postevaluate = func; 3214 PetscFunctionReturn(PETSC_SUCCESS); 3215 } 3216 3217 /*@ 3218 TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()` 3219 3220 Collective 3221 3222 Input Parameters: 3223 . ts - The `TS` context obtained from `TSCreate()` 3224 stagetime - The absolute time of the current stage 3225 3226 Level: developer 3227 3228 Note: 3229 `TSPreStage()` is typically used within time stepping implementations, 3230 most users would not generally call this routine themselves. 3231 3232 .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3233 @*/ 3234 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime) 3235 { 3236 PetscFunctionBegin; 3237 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3238 if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime)); 3239 PetscFunctionReturn(PETSC_SUCCESS); 3240 } 3241 3242 /*@ 3243 TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()` 3244 3245 Collective 3246 3247 Input Parameters: 3248 . ts - The `TS` context obtained from `TSCreate()` 3249 stagetime - The absolute time of the current stage 3250 stageindex - Stage number 3251 Y - Array of vectors (of size = total number 3252 of stages) with the stage solutions 3253 3254 Level: developer 3255 3256 Note: 3257 `TSPostStage()` is typically used within time stepping implementations, 3258 most users would not generally call this routine themselves. 3259 3260 .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3261 @*/ 3262 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y) 3263 { 3264 PetscFunctionBegin; 3265 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3266 if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y)); 3267 PetscFunctionReturn(PETSC_SUCCESS); 3268 } 3269 3270 /*@ 3271 TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()` 3272 3273 Collective 3274 3275 Input Parameter: 3276 . ts - The `TS` context obtained from `TSCreate()` 3277 3278 Level: developer 3279 3280 Note: 3281 `TSPostEvaluate()` is typically used within time stepping implementations, 3282 most users would not generally call this routine themselves. 3283 3284 .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3285 @*/ 3286 PetscErrorCode TSPostEvaluate(TS ts) 3287 { 3288 PetscFunctionBegin; 3289 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3290 if (ts->postevaluate) { 3291 Vec U; 3292 PetscObjectState sprev, spost; 3293 3294 PetscCall(TSGetSolution(ts, &U)); 3295 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3296 PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts)); 3297 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3298 if (sprev != spost) PetscCall(TSRestartStep(ts)); 3299 } 3300 PetscFunctionReturn(PETSC_SUCCESS); 3301 } 3302 3303 /*@C 3304 TSSetPostStep - Sets the general-purpose function 3305 called once at the end of each time step. 3306 3307 Logically Collective 3308 3309 Input Parameters: 3310 + ts - The `TS` context obtained from `TSCreate()` 3311 - func - The function 3312 3313 Calling sequence of `func`: 3314 $ PetscErrorCode func(TS ts) 3315 3316 Level: intermediate 3317 3318 Note: 3319 The function set by `TSSetPostStep()` is called after each successful step. The solution vector 3320 obtained by `TSGetSolution()` may be different than that computed at the step end if the event handler 3321 locates an event and `TSPostEvent()` modifies it. Use `TSSetPostEvaluate()` if an unmodified solution is needed instead. 3322 3323 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()` 3324 @*/ 3325 PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS)) 3326 { 3327 PetscFunctionBegin; 3328 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3329 ts->poststep = func; 3330 PetscFunctionReturn(PETSC_SUCCESS); 3331 } 3332 3333 /*@ 3334 TSPostStep - Runs the user-defined post-step function that was set with `TSSetPostStep()` 3335 3336 Collective 3337 3338 Input Parameter: 3339 . ts - The `TS` context obtained from `TSCreate()` 3340 3341 Note: 3342 `TSPostStep()` is typically used within time stepping implementations, 3343 so most users would not generally call this routine themselves. 3344 3345 Level: developer 3346 3347 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPotsStep()` 3348 @*/ 3349 PetscErrorCode TSPostStep(TS ts) 3350 { 3351 PetscFunctionBegin; 3352 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3353 if (ts->poststep) { 3354 Vec U; 3355 PetscObjectId idprev; 3356 PetscBool sameObject; 3357 PetscObjectState sprev, spost; 3358 3359 PetscCall(TSGetSolution(ts, &U)); 3360 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3361 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3362 PetscCallBack("TS callback poststep", (*ts->poststep)(ts)); 3363 PetscCall(TSGetSolution(ts, &U)); 3364 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3365 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3366 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3367 } 3368 PetscFunctionReturn(PETSC_SUCCESS); 3369 } 3370 3371 /*@ 3372 TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval 3373 3374 Collective 3375 3376 Input Parameters: 3377 + ts - time stepping context 3378 - t - time to interpolate to 3379 3380 Output Parameter: 3381 . U - state at given time 3382 3383 Level: intermediate 3384 3385 Developer Notes: 3386 `TSInterpolate()` and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints. 3387 3388 .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()` 3389 @*/ 3390 PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U) 3391 { 3392 PetscFunctionBegin; 3393 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3394 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3395 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); 3396 PetscUseTypeMethod(ts, interpolate, t, U); 3397 PetscFunctionReturn(PETSC_SUCCESS); 3398 } 3399 3400 /*@ 3401 TSStep - Steps one time step 3402 3403 Collective 3404 3405 Input Parameter: 3406 . ts - the `TS` context obtained from `TSCreate()` 3407 3408 Level: developer 3409 3410 Notes: 3411 The public interface for the ODE/DAE solvers is `TSSolve()`, you should almost for sure be using that routine and not this routine. 3412 3413 The hook set using `TSSetPreStep()` is called before each attempt to take the step. In general, the time step size may 3414 be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages. 3415 3416 This may over-step the final time provided in `TSSetMaxTime()` depending on the time-step used. `TSSolve()` interpolates to exactly the 3417 time provided in `TSSetMaxTime()`. One can use `TSInterpolate()` to determine an interpolated solution within the final timestep. 3418 3419 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()` 3420 @*/ 3421 PetscErrorCode TSStep(TS ts) 3422 { 3423 static PetscBool cite = PETSC_FALSE; 3424 PetscReal ptime; 3425 3426 PetscFunctionBegin; 3427 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3428 PetscCall(PetscCitationsRegister("@article{tspaper,\n" 3429 " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n" 3430 " author = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n" 3431 " journal = {arXiv e-preprints},\n" 3432 " eprint = {1806.01437},\n" 3433 " archivePrefix = {arXiv},\n" 3434 " year = {2018}\n}\n", 3435 &cite)); 3436 PetscCall(TSSetUp(ts)); 3437 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 3438 3439 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>"); 3440 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()"); 3441 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"); 3442 3443 if (!ts->steps) ts->ptime_prev = ts->ptime; 3444 ptime = ts->ptime; 3445 ts->ptime_prev_rollback = ts->ptime_prev; 3446 ts->reason = TS_CONVERGED_ITERATING; 3447 3448 PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0)); 3449 PetscUseTypeMethod(ts, step); 3450 PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0)); 3451 3452 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) 3453 PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[ts->tspan->spanctr++])); 3454 if (ts->reason >= 0) { 3455 ts->ptime_prev = ptime; 3456 ts->steps++; 3457 ts->steprollback = PETSC_FALSE; 3458 ts->steprestart = PETSC_FALSE; 3459 } 3460 if (!ts->reason) { 3461 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 3462 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 3463 } 3464 3465 if (ts->reason < 0 && ts->errorifstepfailed) { 3466 PetscCall(TSMonitorCancel(ts)); 3467 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]); 3468 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]); 3469 } 3470 PetscFunctionReturn(PETSC_SUCCESS); 3471 } 3472 3473 /*@ 3474 TSEvaluateWLTE - Evaluate the weighted local truncation error norm 3475 at the end of a time step with a given order of accuracy. 3476 3477 Collective 3478 3479 Input Parameters: 3480 + ts - time stepping context 3481 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 3482 3483 Input/Output Parameter: 3484 . order - optional, desired order for the error evaluation or `PETSC_DECIDE`; 3485 on output, the actual order of the error evaluation 3486 3487 Output Parameter: 3488 . wlte - the weighted local truncation error norm 3489 3490 Level: advanced 3491 3492 Note: 3493 If the timestepper cannot evaluate the error in a particular step 3494 (eg. in the first step or restart steps after event handling), 3495 this routine returns wlte=-1.0 . 3496 3497 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()` 3498 @*/ 3499 PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte) 3500 { 3501 PetscFunctionBegin; 3502 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3503 PetscValidType(ts, 1); 3504 PetscValidLogicalCollectiveEnum(ts, wnormtype, 2); 3505 if (order) PetscValidIntPointer(order, 3); 3506 if (order) PetscValidLogicalCollectiveInt(ts, *order, 3); 3507 PetscValidRealPointer(wlte, 4); 3508 PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 3509 PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte); 3510 PetscFunctionReturn(PETSC_SUCCESS); 3511 } 3512 3513 /*@ 3514 TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy. 3515 3516 Collective 3517 3518 Input Parameters: 3519 + ts - time stepping context 3520 . order - desired order of accuracy 3521 - done - whether the step was evaluated at this order (pass `NULL` to generate an error if not available) 3522 3523 Output Parameter: 3524 . U - state at the end of the current step 3525 3526 Level: advanced 3527 3528 Notes: 3529 This function cannot be called until all stages have been evaluated. 3530 3531 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. 3532 3533 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt` 3534 @*/ 3535 PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done) 3536 { 3537 PetscFunctionBegin; 3538 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3539 PetscValidType(ts, 1); 3540 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3541 PetscUseTypeMethod(ts, evaluatestep, order, U, done); 3542 PetscFunctionReturn(PETSC_SUCCESS); 3543 } 3544 3545 /*@C 3546 TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping. 3547 3548 Not collective 3549 3550 Input Parameter: 3551 . ts - time stepping context 3552 3553 Output Parameter: 3554 . initCondition - The function which computes an initial condition 3555 3556 Calling sequence of `initCondition`: 3557 .vb 3558 PetscErrorCode initCondition(TS ts, Vec u) 3559 .ve 3560 + ts - The timestepping context 3561 - u - The input vector in which the initial condition is stored 3562 3563 Level: advanced 3564 3565 .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()` 3566 @*/ 3567 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS, Vec)) 3568 { 3569 PetscFunctionBegin; 3570 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3571 PetscValidPointer(initCondition, 2); 3572 *initCondition = ts->ops->initcondition; 3573 PetscFunctionReturn(PETSC_SUCCESS); 3574 } 3575 3576 /*@C 3577 TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping. 3578 3579 Logically collective 3580 3581 Input Parameters: 3582 + ts - time stepping context 3583 - initCondition - The function which computes an initial condition 3584 3585 Calling sequence of `initCondition`: 3586 $ PetscErrorCode initCondition(TS ts, Vec u) 3587 + ts - The timestepping context 3588 - u - The input vector in which the initial condition is to be stored 3589 3590 Level: advanced 3591 3592 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()` 3593 @*/ 3594 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS, Vec)) 3595 { 3596 PetscFunctionBegin; 3597 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3598 PetscValidFunction(initCondition, 2); 3599 ts->ops->initcondition = initCondition; 3600 PetscFunctionReturn(PETSC_SUCCESS); 3601 } 3602 3603 /*@ 3604 TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()` 3605 3606 Collective 3607 3608 Input Parameters: 3609 + ts - time stepping context 3610 - u - The `Vec` to store the condition in which will be used in `TSSolve()` 3611 3612 Level: advanced 3613 3614 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3615 @*/ 3616 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u) 3617 { 3618 PetscFunctionBegin; 3619 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3620 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3621 PetscTryTypeMethod(ts, initcondition, u); 3622 PetscFunctionReturn(PETSC_SUCCESS); 3623 } 3624 3625 /*@C 3626 TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping. 3627 3628 Not collective 3629 3630 Input Parameter: 3631 . ts - time stepping context 3632 3633 Output Parameter: 3634 . exactError - The function which computes the solution error 3635 3636 Calling sequence of `exactError`: 3637 $ PetscErrorCode exactError(TS ts, Vec u, Vec e) 3638 + ts - The timestepping context 3639 . u - The approximate solution vector 3640 - e - The vector in which the error is stored 3641 3642 Level: advanced 3643 3644 .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()` 3645 @*/ 3646 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS, Vec, Vec)) 3647 { 3648 PetscFunctionBegin; 3649 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3650 PetscValidPointer(exactError, 2); 3651 *exactError = ts->ops->exacterror; 3652 PetscFunctionReturn(PETSC_SUCCESS); 3653 } 3654 3655 /*@C 3656 TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping. 3657 3658 Logically collective 3659 3660 Input Parameters: 3661 + ts - time stepping context 3662 - exactError - The function which computes the solution error 3663 3664 Calling sequence of `exactError`: 3665 $ PetscErrorCode exactError(TS ts, Vec u) 3666 + ts - The timestepping context 3667 . u - The approximate solution vector 3668 - e - The vector in which the error is stored 3669 3670 Level: advanced 3671 3672 .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()` 3673 @*/ 3674 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS, Vec, Vec)) 3675 { 3676 PetscFunctionBegin; 3677 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3678 PetscValidFunction(exactError, 2); 3679 ts->ops->exacterror = exactError; 3680 PetscFunctionReturn(PETSC_SUCCESS); 3681 } 3682 3683 /*@ 3684 TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()` 3685 3686 Collective 3687 3688 Input Parameters: 3689 + ts - time stepping context 3690 . u - The approximate solution 3691 - e - The `Vec` used to store the error 3692 3693 Level: advanced 3694 3695 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3696 @*/ 3697 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e) 3698 { 3699 PetscFunctionBegin; 3700 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3701 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3702 PetscValidHeaderSpecific(e, VEC_CLASSID, 3); 3703 PetscTryTypeMethod(ts, exacterror, u, e); 3704 PetscFunctionReturn(PETSC_SUCCESS); 3705 } 3706 3707 /*@C 3708 TSSetResize - Sets the resize callbacks. 3709 3710 Logically Collective 3711 3712 Input Parameters: 3713 + ts - The `TS` context obtained from `TSCreate()` 3714 . setup - The setup function 3715 - transfer - The transfer function 3716 3717 Calling sequence of `setup`: 3718 $ PetscErrorCode setup(TS ts, PetscInt step, PetscReal time, Vec state, PetscBool *resize, void *ctx) 3719 + ts - the TS context 3720 . step - the current step 3721 . time - the current time 3722 . state - the current vector of state 3723 . resize - (output parameter) `PETSC_TRUE` if need resizing, `PETSC_FALSE` otherwise 3724 - ctx - user defined context 3725 3726 Calling sequence of `transfer`: 3727 $ PetscErrorCode transfer(TS ts, PetscInt nv, Vec vecsin[], Vec vecsout[], void *ctx) 3728 + ts - the TS context 3729 . nv - the number of vectors to be transferred 3730 . vecsin - array of vectors to be transferred 3731 . vecsout - array of transferred vectors 3732 - ctx - user defined context 3733 3734 Notes: 3735 The `setup` function is called inside `TSSolve()` after `TSPostStep()` at the end of each time step 3736 to determine if the problem size has changed. 3737 If it is the case, the solver will collect the needed vectors that need to be 3738 transferred from the old to the new sizes using `transfer`. These vectors will include the current 3739 solution vector, and other vectors needed by the specific solver used. 3740 For example, `TSBDF` uses previous solutions vectors to solve for the next time step. 3741 Other application specific objects associated with the solver, i.e. Jacobian matrices and `DM`, 3742 will be automatically reset if the sizes are changed and they must be specified again by the user 3743 inside the `transfer` function. 3744 The input and output arrays passed to `transfer` are allocated by PETSc. 3745 Vectors in `vecsout` must be created by the user. 3746 Ownership of vectors in `vecsout` is transferred to PETSc. 3747 3748 Level: advanced 3749 3750 .seealso: [](ch_ts), `TS`, `TSSetDM()`, `TSSetIJacobian()`, `TSSetRHSJacobian()` 3751 @*/ 3752 PetscErrorCode TSSetResize(TS ts, PetscErrorCode (*setup)(TS, PetscInt, PetscReal, Vec, PetscBool *, void *), PetscErrorCode (*transfer)(TS, PetscInt, Vec[], Vec[], void *), void *ctx) 3753 { 3754 PetscFunctionBegin; 3755 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3756 ts->resizesetup = setup; 3757 ts->resizetransfer = transfer; 3758 ts->resizectx = ctx; 3759 PetscFunctionReturn(PETSC_SUCCESS); 3760 } 3761 3762 /*@C 3763 TSResizeRegisterOrRetrieve - Register or import vectors transferred with `TSResize()`. 3764 3765 Collective 3766 3767 Input Parameters: 3768 + ts - The `TS` context obtained from `TSCreate()` 3769 - flg - If `PETSC_TRUE` each TS implementation (e.g. `TSBDF`) will register vectors to be transferred, if `PETSC_FALSE` vectors will be imported from transferred vectors. 3770 3771 Level: developer 3772 3773 Note: 3774 `TSResizeRegisterOrRetrieve()` is declared PETSC_INTERN since it is 3775 used within time stepping implementations, 3776 so most users would not generally call this routine themselves. 3777 3778 .seealso: [](ch_ts), `TS`, `TSSetResize()` 3779 @*/ 3780 PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg) 3781 { 3782 PetscFunctionBegin; 3783 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3784 PetscTryTypeMethod(ts, resizeregister, flg); 3785 /* PetscTryTypeMethod(adapt, resizeregister, flg); */ 3786 PetscFunctionReturn(PETSC_SUCCESS); 3787 } 3788 3789 PetscErrorCode TSResizeReset(TS ts) 3790 { 3791 PetscFunctionBegin; 3792 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3793 PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs)); 3794 PetscFunctionReturn(PETSC_SUCCESS); 3795 } 3796 3797 static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[]) 3798 { 3799 PetscFunctionBegin; 3800 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3801 PetscValidLogicalCollectiveInt(ts, cnt, 2); 3802 for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPush(vecsin[i])); 3803 if (ts->resizetransfer) { 3804 PetscCall(PetscInfo(ts, "Transferring %" PetscInt_FMT " vectors\n", cnt)); 3805 PetscCallBack("TS callback resize transfer", (*ts->resizetransfer)(ts, cnt, vecsin, vecsout, ts->resizectx)); 3806 } 3807 for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPop(vecsin[i])); 3808 PetscFunctionReturn(PETSC_SUCCESS); 3809 } 3810 3811 /*@C 3812 TSResizeRegisterVec - Register a vector to be transferred with `TSResize()`. 3813 3814 Collective 3815 3816 Input Parameters: 3817 + ts - The `TS` context obtained from `TSCreate()` 3818 . name - A string identifiying the vector 3819 - vec - The vector 3820 3821 Level: developer 3822 3823 Note: 3824 `TSResizeRegisterVec()` is typically used within time stepping implementations, 3825 so most users would not generally call this routine themselves. 3826 3827 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()` 3828 @*/ 3829 PetscErrorCode TSResizeRegisterVec(TS ts, const char *name, Vec vec) 3830 { 3831 PetscFunctionBegin; 3832 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3833 PetscValidCharPointer(name, 2); 3834 if (vec) PetscValidHeaderSpecific(vec, VEC_CLASSID, 3); 3835 PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec)); 3836 PetscFunctionReturn(PETSC_SUCCESS); 3837 } 3838 3839 /*@C 3840 TSResizeRetrieveVec - Retrieve a vector registered with `TSResizeRegisterVec()`. 3841 3842 Collective 3843 3844 Input Parameters: 3845 + ts - The `TS` context obtained from `TSCreate()` 3846 . name - A string identifiying the vector 3847 - vec - The vector 3848 3849 Level: developer 3850 3851 Note: 3852 `TSResizeRetrieveVec()` is typically used within time stepping implementations, 3853 so most users would not generally call this routine themselves. 3854 3855 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()` 3856 @*/ 3857 PetscErrorCode TSResizeRetrieveVec(TS ts, const char *name, Vec *vec) 3858 { 3859 PetscFunctionBegin; 3860 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3861 PetscValidCharPointer(name, 2); 3862 PetscValidPointer(vec, 3); 3863 PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec)); 3864 PetscFunctionReturn(PETSC_SUCCESS); 3865 } 3866 3867 static PetscErrorCode TSResizeGetVecArray(TS ts, PetscInt *nv, const char **names[], Vec *vecs[]) 3868 { 3869 PetscInt cnt; 3870 PetscObjectList tmp; 3871 Vec *vecsin = NULL; 3872 const char **namesin = NULL; 3873 3874 PetscFunctionBegin; 3875 for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) 3876 if (tmp->obj && tmp->obj->classid == VEC_CLASSID) cnt++; 3877 if (names) PetscCall(PetscMalloc1(cnt, &vecsin)); 3878 if (vecs) PetscCall(PetscMalloc1(cnt, &namesin)); 3879 for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) { 3880 if (tmp->obj && tmp->obj->classid == VEC_CLASSID) { 3881 if (vecs) vecsin[cnt] = (Vec)tmp->obj; 3882 if (names) namesin[cnt] = tmp->name; 3883 cnt++; 3884 } 3885 } 3886 if (nv) *nv = cnt; 3887 if (names) *names = namesin; 3888 if (vecs) *vecs = vecsin; 3889 PetscFunctionReturn(PETSC_SUCCESS); 3890 } 3891 3892 /*@ 3893 TSResize - Runs the user-defined transfer functions provided with `TSSetResize()` 3894 3895 Collective 3896 3897 Input Parameter: 3898 . ts - The `TS` context obtained from `TSCreate()` 3899 3900 Level: developer 3901 3902 Note: 3903 `TSResize()` is typically used within time stepping implementations, 3904 so most users would not generally call this routine themselves. 3905 3906 .seealso: [](ch_ts), `TS`, `TSSetResize()` 3907 @*/ 3908 PetscErrorCode TSResize(TS ts) 3909 { 3910 PetscInt nv = 0; 3911 const char **names = NULL; 3912 Vec *vecsin = NULL; 3913 const char *solname = "ts:vec_sol"; 3914 3915 PetscFunctionBegin; 3916 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3917 if (ts->resizesetup) { 3918 PetscBool flg = PETSC_FALSE; 3919 3920 PetscCall(VecLockReadPush(ts->vec_sol)); 3921 PetscCallBack("TS callback resize setup", (*ts->resizesetup)(ts, ts->steps, ts->ptime, ts->vec_sol, &flg, ts->resizectx)); 3922 PetscCall(VecLockReadPop(ts->vec_sol)); 3923 if (flg) { 3924 PetscCall(TSResizeRegisterVec(ts, solname, ts->vec_sol)); 3925 PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_TRUE)); /* specific impls register their own objects */ 3926 } 3927 } 3928 3929 PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin)); 3930 if (nv) { 3931 Vec *vecsout, vecsol; 3932 3933 /* Reset internal objects */ 3934 PetscCall(TSReset(ts)); 3935 3936 /* Transfer needed vectors (users can call SetJacobian, SetDM here) */ 3937 PetscCall(PetscCalloc1(nv, &vecsout)); 3938 PetscCall(TSResizeTransferVecs(ts, nv, vecsin, vecsout)); 3939 for (PetscInt i = 0; i < nv; i++) { 3940 PetscCall(TSResizeRegisterVec(ts, names[i], vecsout[i])); 3941 PetscCall(VecDestroy(&vecsout[i])); 3942 } 3943 PetscCall(PetscFree(vecsout)); 3944 PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_FALSE)); /* specific impls import the transferred objects */ 3945 3946 PetscCall(TSResizeRetrieveVec(ts, solname, &vecsol)); 3947 if (vecsol) PetscCall(TSSetSolution(ts, vecsol)); 3948 PetscAssert(ts->vec_sol, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_NULL, "Missing TS solution"); 3949 } 3950 3951 PetscCall(PetscFree(names)); 3952 PetscCall(PetscFree(vecsin)); 3953 PetscCall(TSResizeReset(ts)); 3954 PetscFunctionReturn(PETSC_SUCCESS); 3955 } 3956 3957 /*@ 3958 TSSolve - Steps the requested number of timesteps. 3959 3960 Collective 3961 3962 Input Parameters: 3963 + ts - the `TS` context obtained from `TSCreate()` 3964 - u - the solution vector (can be null if `TSSetSolution()` was used and `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`) was not used, 3965 otherwise must contain the initial conditions and will contain the solution at the final requested time 3966 3967 Level: beginner 3968 3969 Notes: 3970 The final time returned by this function may be different from the time of the internally 3971 held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have 3972 stepped over the final time. 3973 3974 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()` 3975 @*/ 3976 PetscErrorCode TSSolve(TS ts, Vec u) 3977 { 3978 Vec solution; 3979 3980 PetscFunctionBegin; 3981 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3982 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3983 3984 PetscCall(TSSetExactFinalTimeDefault(ts)); 3985 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 */ 3986 if (!ts->vec_sol || u == ts->vec_sol) { 3987 PetscCall(VecDuplicate(u, &solution)); 3988 PetscCall(TSSetSolution(ts, solution)); 3989 PetscCall(VecDestroy(&solution)); /* grant ownership */ 3990 } 3991 PetscCall(VecCopy(u, ts->vec_sol)); 3992 PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE"); 3993 } else if (u) PetscCall(TSSetSolution(ts, u)); 3994 PetscCall(TSSetUp(ts)); 3995 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 3996 3997 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>"); 3998 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()"); 3999 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"); 4000 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"); 4001 4002 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 */ 4003 PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[0])); 4004 ts->tspan->spanctr = 1; 4005 } 4006 4007 if (ts->forward_solve) PetscCall(TSForwardSetUp(ts)); 4008 4009 /* reset number of steps only when the step is not restarted. ARKIMEX 4010 restarts the step after an event. Resetting these counters in such case causes 4011 TSTrajectory to incorrectly save the output files 4012 */ 4013 /* reset time step and iteration counters */ 4014 if (!ts->steps) { 4015 ts->ksp_its = 0; 4016 ts->snes_its = 0; 4017 ts->num_snes_failures = 0; 4018 ts->reject = 0; 4019 ts->steprestart = PETSC_TRUE; 4020 ts->steprollback = PETSC_FALSE; 4021 ts->rhsjacobian.time = PETSC_MIN_REAL; 4022 } 4023 4024 /* make sure initial time step does not overshoot final time or the next point in tspan */ 4025 if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 4026 PetscReal maxdt; 4027 PetscReal dt = ts->time_step; 4028 4029 if (ts->tspan) maxdt = ts->tspan->span_times[ts->tspan->spanctr] - ts->ptime; 4030 else maxdt = ts->max_time - ts->ptime; 4031 ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt); 4032 } 4033 ts->reason = TS_CONVERGED_ITERATING; 4034 4035 { 4036 PetscViewer viewer; 4037 PetscViewerFormat format; 4038 PetscBool flg; 4039 static PetscBool incall = PETSC_FALSE; 4040 4041 if (!incall) { 4042 /* Estimate the convergence rate of the time discretization */ 4043 PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg)); 4044 if (flg) { 4045 PetscConvEst conv; 4046 DM dm; 4047 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4048 PetscInt Nf; 4049 PetscBool checkTemporal = PETSC_TRUE; 4050 4051 incall = PETSC_TRUE; 4052 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg)); 4053 PetscCall(TSGetDM(ts, &dm)); 4054 PetscCall(DMGetNumFields(dm, &Nf)); 4055 PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha)); 4056 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv)); 4057 PetscCall(PetscConvEstUseTS(conv, checkTemporal)); 4058 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts)); 4059 PetscCall(PetscConvEstSetFromOptions(conv)); 4060 PetscCall(PetscConvEstSetUp(conv)); 4061 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 4062 PetscCall(PetscViewerPushFormat(viewer, format)); 4063 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 4064 PetscCall(PetscViewerPopFormat(viewer)); 4065 PetscCall(PetscViewerDestroy(&viewer)); 4066 PetscCall(PetscConvEstDestroy(&conv)); 4067 PetscCall(PetscFree(alpha)); 4068 incall = PETSC_FALSE; 4069 } 4070 } 4071 } 4072 4073 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre")); 4074 4075 if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */ 4076 PetscUseTypeMethod(ts, solve); 4077 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 4078 ts->solvetime = ts->ptime; 4079 solution = ts->vec_sol; 4080 } else { /* Step the requested number of timesteps. */ 4081 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 4082 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 4083 4084 if (!ts->steps) { 4085 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 4086 PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol)); 4087 } 4088 4089 while (!ts->reason) { 4090 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 4091 if (!ts->steprollback) PetscCall(TSPreStep(ts)); 4092 PetscCall(TSStep(ts)); 4093 if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL)); 4094 if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL)); 4095 if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */ 4096 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 4097 PetscCall(TSForwardCostIntegral(ts)); 4098 if (ts->reason >= 0) ts->steps++; 4099 } 4100 if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */ 4101 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 4102 PetscCall(TSForwardStep(ts)); 4103 if (ts->reason >= 0) ts->steps++; 4104 } 4105 PetscCall(TSPostEvaluate(ts)); 4106 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. */ 4107 if (ts->steprollback) PetscCall(TSPostEvaluate(ts)); 4108 if (!ts->steprollback) { 4109 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 4110 PetscCall(TSPostStep(ts)); 4111 PetscCall(TSResize(ts)); 4112 } 4113 } 4114 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 4115 4116 if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) { 4117 PetscCall(TSInterpolate(ts, ts->max_time, u)); 4118 ts->solvetime = ts->max_time; 4119 solution = u; 4120 PetscCall(TSMonitor(ts, -1, ts->solvetime, solution)); 4121 } else { 4122 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 4123 ts->solvetime = ts->ptime; 4124 solution = ts->vec_sol; 4125 } 4126 } 4127 4128 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view")); 4129 PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution")); 4130 PetscCall(PetscObjectSAWsBlock((PetscObject)ts)); 4131 if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts)); 4132 PetscFunctionReturn(PETSC_SUCCESS); 4133 } 4134 4135 /*@ 4136 TSGetTime - Gets the time of the most recently completed step. 4137 4138 Not Collective 4139 4140 Input Parameter: 4141 . ts - the `TS` context obtained from `TSCreate()` 4142 4143 Output Parameter: 4144 . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`. 4145 4146 Level: beginner 4147 4148 Note: 4149 When called during time step evaluation (e.g. during residual evaluation or via hooks set using `TSSetPreStep()`, 4150 `TSSetPreStage()`, `TSSetPostStage()`, or `TSSetPostStep()`), the time is the time at the start of the step being evaluated. 4151 4152 .seealso: [](ch_ts), `TS`, ``TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()` 4153 @*/ 4154 PetscErrorCode TSGetTime(TS ts, PetscReal *t) 4155 { 4156 PetscFunctionBegin; 4157 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4158 PetscValidRealPointer(t, 2); 4159 *t = ts->ptime; 4160 PetscFunctionReturn(PETSC_SUCCESS); 4161 } 4162 4163 /*@ 4164 TSGetPrevTime - Gets the starting time of the previously completed step. 4165 4166 Not Collective 4167 4168 Input Parameter: 4169 . ts - the `TS` context obtained from `TSCreate()` 4170 4171 Output Parameter: 4172 . t - the previous time 4173 4174 Level: beginner 4175 4176 .seealso: [](ch_ts), `TS`, ``TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()` 4177 @*/ 4178 PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t) 4179 { 4180 PetscFunctionBegin; 4181 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4182 PetscValidRealPointer(t, 2); 4183 *t = ts->ptime_prev; 4184 PetscFunctionReturn(PETSC_SUCCESS); 4185 } 4186 4187 /*@ 4188 TSSetTime - Allows one to reset the time. 4189 4190 Logically Collective 4191 4192 Input Parameters: 4193 + ts - the `TS` context obtained from `TSCreate()` 4194 - t - the time 4195 4196 Level: intermediate 4197 4198 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()` 4199 @*/ 4200 PetscErrorCode TSSetTime(TS ts, PetscReal t) 4201 { 4202 PetscFunctionBegin; 4203 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4204 PetscValidLogicalCollectiveReal(ts, t, 2); 4205 ts->ptime = t; 4206 PetscFunctionReturn(PETSC_SUCCESS); 4207 } 4208 4209 /*@C 4210 TSSetOptionsPrefix - Sets the prefix used for searching for all 4211 TS options in the database. 4212 4213 Logically Collective 4214 4215 Input Parameters: 4216 + ts - The `TS` context 4217 - prefix - The prefix to prepend to all option names 4218 4219 Level: advanced 4220 4221 Note: 4222 A hyphen (-) must NOT be given at the beginning of the prefix name. 4223 The first character of all runtime options is AUTOMATICALLY the 4224 hyphen. 4225 4226 .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()` 4227 @*/ 4228 PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[]) 4229 { 4230 SNES snes; 4231 4232 PetscFunctionBegin; 4233 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4234 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix)); 4235 PetscCall(TSGetSNES(ts, &snes)); 4236 PetscCall(SNESSetOptionsPrefix(snes, prefix)); 4237 PetscFunctionReturn(PETSC_SUCCESS); 4238 } 4239 4240 /*@C 4241 TSAppendOptionsPrefix - Appends to the prefix used for searching for all 4242 TS options in the database. 4243 4244 Logically Collective 4245 4246 Input Parameters: 4247 + ts - The `TS` context 4248 - prefix - The prefix to prepend to all option names 4249 4250 Level: advanced 4251 4252 Note: 4253 A hyphen (-) must NOT be given at the beginning of the prefix name. 4254 The first character of all runtime options is AUTOMATICALLY the 4255 hyphen. 4256 4257 .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()` 4258 @*/ 4259 PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[]) 4260 { 4261 SNES snes; 4262 4263 PetscFunctionBegin; 4264 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4265 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix)); 4266 PetscCall(TSGetSNES(ts, &snes)); 4267 PetscCall(SNESAppendOptionsPrefix(snes, prefix)); 4268 PetscFunctionReturn(PETSC_SUCCESS); 4269 } 4270 4271 /*@C 4272 TSGetOptionsPrefix - Sets the prefix used for searching for all 4273 `TS` options in the database. 4274 4275 Not Collective 4276 4277 Input Parameter: 4278 . ts - The `TS` context 4279 4280 Output Parameter: 4281 . prefix - A pointer to the prefix string used 4282 4283 Level: intermediate 4284 4285 Fortran Notes: 4286 The user should pass in a string 'prefix' of 4287 sufficient length to hold the prefix. 4288 4289 .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()` 4290 @*/ 4291 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[]) 4292 { 4293 PetscFunctionBegin; 4294 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4295 PetscValidPointer(prefix, 2); 4296 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix)); 4297 PetscFunctionReturn(PETSC_SUCCESS); 4298 } 4299 4300 /*@C 4301 TSGetRHSJacobian - Returns the Jacobian J at the present timestep. 4302 4303 Not Collective, but parallel objects are returned if ts is parallel 4304 4305 Input Parameter: 4306 . ts - The `TS` context obtained from `TSCreate()` 4307 4308 Output Parameters: 4309 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or `NULL`) 4310 . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat` (or `NULL`) 4311 . func - Function to compute the Jacobian of the RHS (or `NULL`) 4312 - ctx - User-defined context for Jacobian evaluation routine (or `NULL`) 4313 4314 Level: intermediate 4315 4316 Note: 4317 You can pass in `NULL` for any return argument you do not need. 4318 4319 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4320 4321 @*/ 4322 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobian *func, void **ctx) 4323 { 4324 DM dm; 4325 4326 PetscFunctionBegin; 4327 if (Amat || Pmat) { 4328 SNES snes; 4329 PetscCall(TSGetSNES(ts, &snes)); 4330 PetscCall(SNESSetUpMatrices(snes)); 4331 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4332 } 4333 PetscCall(TSGetDM(ts, &dm)); 4334 PetscCall(DMTSGetRHSJacobian(dm, func, ctx)); 4335 PetscFunctionReturn(PETSC_SUCCESS); 4336 } 4337 4338 /*@C 4339 TSGetIJacobian - Returns the implicit Jacobian at the present timestep. 4340 4341 Not Collective, but parallel objects are returned if ts is parallel 4342 4343 Input Parameter: 4344 . ts - The `TS` context obtained from `TSCreate()` 4345 4346 Output Parameters: 4347 + Amat - The (approximate) Jacobian of F(t,U,U_t) 4348 . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat` 4349 . f - The function to compute the matrices 4350 - ctx - User-defined context for Jacobian evaluation routine 4351 4352 Level: advanced 4353 4354 Note: 4355 You can pass in `NULL` for any return argument you do not need. 4356 4357 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4358 @*/ 4359 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobian *f, void **ctx) 4360 { 4361 DM dm; 4362 4363 PetscFunctionBegin; 4364 if (Amat || Pmat) { 4365 SNES snes; 4366 PetscCall(TSGetSNES(ts, &snes)); 4367 PetscCall(SNESSetUpMatrices(snes)); 4368 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4369 } 4370 PetscCall(TSGetDM(ts, &dm)); 4371 PetscCall(DMTSGetIJacobian(dm, f, ctx)); 4372 PetscFunctionReturn(PETSC_SUCCESS); 4373 } 4374 4375 #include <petsc/private/dmimpl.h> 4376 /*@ 4377 TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS` 4378 4379 Logically Collective 4380 4381 Input Parameters: 4382 + ts - the `TS` integrator object 4383 - dm - the dm, cannot be `NULL` 4384 4385 Level: intermediate 4386 4387 Notes: 4388 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 4389 even when not using interfaces like `DMTSSetIFunction()`. Use `DMClone()` to get a distinct `DM` when solving 4390 different problems using the same function space. 4391 4392 .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()` 4393 @*/ 4394 PetscErrorCode TSSetDM(TS ts, DM dm) 4395 { 4396 SNES snes; 4397 DMTS tsdm; 4398 4399 PetscFunctionBegin; 4400 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4401 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 4402 PetscCall(PetscObjectReference((PetscObject)dm)); 4403 if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */ 4404 if (ts->dm->dmts && !dm->dmts) { 4405 PetscCall(DMCopyDMTS(ts->dm, dm)); 4406 PetscCall(DMGetDMTS(ts->dm, &tsdm)); 4407 /* Grant write privileges to the replacement DM */ 4408 if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm; 4409 } 4410 PetscCall(DMDestroy(&ts->dm)); 4411 } 4412 ts->dm = dm; 4413 4414 PetscCall(TSGetSNES(ts, &snes)); 4415 PetscCall(SNESSetDM(snes, dm)); 4416 PetscFunctionReturn(PETSC_SUCCESS); 4417 } 4418 4419 /*@ 4420 TSGetDM - Gets the `DM` that may be used by some preconditioners 4421 4422 Not Collective 4423 4424 Input Parameter: 4425 . ts - the `TS` 4426 4427 Output Parameter: 4428 . dm - the `DM` 4429 4430 Level: intermediate 4431 4432 .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()` 4433 @*/ 4434 PetscErrorCode TSGetDM(TS ts, DM *dm) 4435 { 4436 PetscFunctionBegin; 4437 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4438 if (!ts->dm) { 4439 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm)); 4440 if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm)); 4441 } 4442 *dm = ts->dm; 4443 PetscFunctionReturn(PETSC_SUCCESS); 4444 } 4445 4446 /*@ 4447 SNESTSFormFunction - Function to evaluate nonlinear residual 4448 4449 Logically Collective 4450 4451 Input Parameters: 4452 + snes - nonlinear solver 4453 . U - the current state at which to evaluate the residual 4454 - ctx - user context, must be a TS 4455 4456 Output Parameter: 4457 . F - the nonlinear residual 4458 4459 Level: advanced 4460 4461 Note: 4462 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4463 It is most frequently passed to `MatFDColoringSetFunction()`. 4464 4465 .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()` 4466 @*/ 4467 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx) 4468 { 4469 TS ts = (TS)ctx; 4470 4471 PetscFunctionBegin; 4472 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4473 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4474 PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 4475 PetscValidHeaderSpecific(ts, TS_CLASSID, 4); 4476 PetscCall((ts->ops->snesfunction)(snes, U, F, ts)); 4477 PetscFunctionReturn(PETSC_SUCCESS); 4478 } 4479 4480 /*@ 4481 SNESTSFormJacobian - Function to evaluate the Jacobian 4482 4483 Collective 4484 4485 Input Parameters: 4486 + snes - nonlinear solver 4487 . U - the current state at which to evaluate the residual 4488 - ctx - user context, must be a `TS` 4489 4490 Output Parameters: 4491 + A - the Jacobian 4492 - B - the preconditioning matrix (may be the same as A) 4493 4494 Level: developer 4495 4496 Note: 4497 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4498 4499 .seealso: [](ch_ts), `SNESSetJacobian()` 4500 @*/ 4501 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx) 4502 { 4503 TS ts = (TS)ctx; 4504 4505 PetscFunctionBegin; 4506 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4507 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4508 PetscValidPointer(A, 3); 4509 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 4510 PetscValidPointer(B, 4); 4511 PetscValidHeaderSpecific(B, MAT_CLASSID, 4); 4512 PetscValidHeaderSpecific(ts, TS_CLASSID, 5); 4513 PetscCall((ts->ops->snesjacobian)(snes, U, A, B, ts)); 4514 PetscFunctionReturn(PETSC_SUCCESS); 4515 } 4516 4517 /*@C 4518 TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only 4519 4520 Collective 4521 4522 Input Parameters: 4523 + ts - time stepping context 4524 . t - time at which to evaluate 4525 . U - state at which to evaluate 4526 - ctx - context 4527 4528 Output Parameter: 4529 . F - right hand side 4530 4531 Level: intermediate 4532 4533 Note: 4534 This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right hand side for linear problems. 4535 The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`. 4536 4537 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 4538 @*/ 4539 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx) 4540 { 4541 Mat Arhs, Brhs; 4542 4543 PetscFunctionBegin; 4544 PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs)); 4545 /* undo the damage caused by shifting */ 4546 PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs)); 4547 PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs)); 4548 PetscCall(MatMult(Arhs, U, F)); 4549 PetscFunctionReturn(PETSC_SUCCESS); 4550 } 4551 4552 /*@C 4553 TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent. 4554 4555 Collective 4556 4557 Input Parameters: 4558 + ts - time stepping context 4559 . t - time at which to evaluate 4560 . U - state at which to evaluate 4561 - ctx - context 4562 4563 Output Parameters: 4564 + A - pointer to operator 4565 - B - pointer to preconditioning matrix 4566 4567 Level: intermediate 4568 4569 Note: 4570 This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems. 4571 4572 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()` 4573 @*/ 4574 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx) 4575 { 4576 PetscFunctionBegin; 4577 PetscFunctionReturn(PETSC_SUCCESS); 4578 } 4579 4580 /*@C 4581 TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only 4582 4583 Collective 4584 4585 Input Parameters: 4586 + ts - time stepping context 4587 . t - time at which to evaluate 4588 . U - state at which to evaluate 4589 . Udot - time derivative of state vector 4590 - ctx - context 4591 4592 Output Parameter: 4593 . F - left hand side 4594 4595 Level: intermediate 4596 4597 Notes: 4598 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 4599 user is required to write their own `TSComputeIFunction()`. 4600 This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems. 4601 The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`. 4602 4603 Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U 4604 4605 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()` 4606 @*/ 4607 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx) 4608 { 4609 Mat A, B; 4610 4611 PetscFunctionBegin; 4612 PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL)); 4613 PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE)); 4614 PetscCall(MatMult(A, Udot, F)); 4615 PetscFunctionReturn(PETSC_SUCCESS); 4616 } 4617 4618 /*@C 4619 TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE 4620 4621 Collective 4622 4623 Input Parameters: 4624 + ts - time stepping context 4625 . t - time at which to evaluate 4626 . U - state at which to evaluate 4627 . Udot - time derivative of state vector 4628 . shift - shift to apply 4629 - ctx - context 4630 4631 Output Parameters: 4632 + A - pointer to operator 4633 - B - pointer to preconditioning matrix 4634 4635 Level: advanced 4636 4637 Notes: 4638 This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems. 4639 4640 It is only appropriate for problems of the form 4641 4642 $ M Udot = F(U,t) 4643 4644 where M is constant and F is non-stiff. The user must pass M to `TSSetIJacobian()`. The current implementation only 4645 works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing 4646 an implicit operator of the form 4647 4648 $ shift*M + J 4649 4650 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 4651 a copy of M or reassemble it when requested. 4652 4653 .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()` 4654 @*/ 4655 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx) 4656 { 4657 PetscFunctionBegin; 4658 PetscCall(MatScale(A, shift / ts->ijacobian.shift)); 4659 ts->ijacobian.shift = shift; 4660 PetscFunctionReturn(PETSC_SUCCESS); 4661 } 4662 4663 /*@ 4664 TSGetEquationType - Gets the type of the equation that `TS` is solving. 4665 4666 Not Collective 4667 4668 Input Parameter: 4669 . ts - the `TS` context 4670 4671 Output Parameter: 4672 . equation_type - see `TSEquationType` 4673 4674 Level: beginner 4675 4676 .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType` 4677 @*/ 4678 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type) 4679 { 4680 PetscFunctionBegin; 4681 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4682 PetscValidPointer(equation_type, 2); 4683 *equation_type = ts->equation_type; 4684 PetscFunctionReturn(PETSC_SUCCESS); 4685 } 4686 4687 /*@ 4688 TSSetEquationType - Sets the type of the equation that `TS` is solving. 4689 4690 Not Collective 4691 4692 Input Parameters: 4693 + ts - the `TS` context 4694 - equation_type - see `TSEquationType` 4695 4696 Level: advanced 4697 4698 .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType` 4699 @*/ 4700 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type) 4701 { 4702 PetscFunctionBegin; 4703 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4704 ts->equation_type = equation_type; 4705 PetscFunctionReturn(PETSC_SUCCESS); 4706 } 4707 4708 /*@ 4709 TSGetConvergedReason - Gets the reason the `TS` iteration was stopped. 4710 4711 Not Collective 4712 4713 Input Parameter: 4714 . ts - the `TS` context 4715 4716 Output Parameter: 4717 . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4718 manual pages for the individual convergence tests for complete lists 4719 4720 Level: beginner 4721 4722 Note: 4723 Can only be called after the call to `TSSolve()` is complete. 4724 4725 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSSetConvergenceTest()`, `TSConvergedReason` 4726 @*/ 4727 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason) 4728 { 4729 PetscFunctionBegin; 4730 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4731 PetscValidPointer(reason, 2); 4732 *reason = ts->reason; 4733 PetscFunctionReturn(PETSC_SUCCESS); 4734 } 4735 4736 /*@ 4737 TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`. 4738 4739 Logically Collective; reason must contain common value 4740 4741 Input Parameters: 4742 + ts - the `TS` context 4743 - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4744 manual pages for the individual convergence tests for complete lists 4745 4746 Level: advanced 4747 4748 Note: 4749 Can only be called while `TSSolve()` is active. 4750 4751 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4752 @*/ 4753 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason) 4754 { 4755 PetscFunctionBegin; 4756 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4757 ts->reason = reason; 4758 PetscFunctionReturn(PETSC_SUCCESS); 4759 } 4760 4761 /*@ 4762 TSGetSolveTime - Gets the time after a call to `TSSolve()` 4763 4764 Not Collective 4765 4766 Input Parameter: 4767 . ts - the `TS` context 4768 4769 Output Parameter: 4770 . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()` 4771 4772 Level: beginner 4773 4774 Note: 4775 Can only be called after the call to `TSSolve()` is complete. 4776 4777 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSSetConvergenceTest()`, `TSConvergedReason` 4778 @*/ 4779 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime) 4780 { 4781 PetscFunctionBegin; 4782 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4783 PetscValidRealPointer(ftime, 2); 4784 *ftime = ts->solvetime; 4785 PetscFunctionReturn(PETSC_SUCCESS); 4786 } 4787 4788 /*@ 4789 TSGetSNESIterations - Gets the total number of nonlinear iterations 4790 used by the time integrator. 4791 4792 Not Collective 4793 4794 Input Parameter: 4795 . ts - `TS` context 4796 4797 Output Parameter: 4798 . nits - number of nonlinear iterations 4799 4800 Level: intermediate 4801 4802 Note: 4803 This counter is reset to zero for each successive call to `TSSolve()`. 4804 4805 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()` 4806 @*/ 4807 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits) 4808 { 4809 PetscFunctionBegin; 4810 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4811 PetscValidIntPointer(nits, 2); 4812 *nits = ts->snes_its; 4813 PetscFunctionReturn(PETSC_SUCCESS); 4814 } 4815 4816 /*@ 4817 TSGetKSPIterations - Gets the total number of linear iterations 4818 used by the time integrator. 4819 4820 Not Collective 4821 4822 Input Parameter: 4823 . ts - `TS` context 4824 4825 Output Parameter: 4826 . lits - number of linear iterations 4827 4828 Level: intermediate 4829 4830 Note: 4831 This counter is reset to zero for each successive call to `TSSolve()`. 4832 4833 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `SNESGetKSPIterations()` 4834 @*/ 4835 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits) 4836 { 4837 PetscFunctionBegin; 4838 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4839 PetscValidIntPointer(lits, 2); 4840 *lits = ts->ksp_its; 4841 PetscFunctionReturn(PETSC_SUCCESS); 4842 } 4843 4844 /*@ 4845 TSGetStepRejections - Gets the total number of rejected steps. 4846 4847 Not Collective 4848 4849 Input Parameter: 4850 . ts - `TS` context 4851 4852 Output Parameter: 4853 . rejects - number of steps rejected 4854 4855 Level: intermediate 4856 4857 Note: 4858 This counter is reset to zero for each successive call to `TSSolve()`. 4859 4860 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()` 4861 @*/ 4862 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects) 4863 { 4864 PetscFunctionBegin; 4865 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4866 PetscValidIntPointer(rejects, 2); 4867 *rejects = ts->reject; 4868 PetscFunctionReturn(PETSC_SUCCESS); 4869 } 4870 4871 /*@ 4872 TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS` 4873 4874 Not Collective 4875 4876 Input Parameter: 4877 . ts - `TS` context 4878 4879 Output Parameter: 4880 . fails - number of failed nonlinear solves 4881 4882 Level: intermediate 4883 4884 Note: 4885 This counter is reset to zero for each successive call to `TSSolve()`. 4886 4887 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()` 4888 @*/ 4889 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails) 4890 { 4891 PetscFunctionBegin; 4892 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4893 PetscValidIntPointer(fails, 2); 4894 *fails = ts->num_snes_failures; 4895 PetscFunctionReturn(PETSC_SUCCESS); 4896 } 4897 4898 /*@ 4899 TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails 4900 4901 Not Collective 4902 4903 Input Parameters: 4904 + ts - `TS` context 4905 - rejects - maximum number of rejected steps, pass -1 for unlimited 4906 4907 Options Database Key: 4908 . -ts_max_reject - Maximum number of step rejections before a step fails 4909 4910 Level: intermediate 4911 4912 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4913 @*/ 4914 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects) 4915 { 4916 PetscFunctionBegin; 4917 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4918 ts->max_reject = rejects; 4919 PetscFunctionReturn(PETSC_SUCCESS); 4920 } 4921 4922 /*@ 4923 TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves 4924 4925 Not Collective 4926 4927 Input Parameters: 4928 + ts - `TS` context 4929 - fails - maximum number of failed nonlinear solves, pass -1 for unlimited 4930 4931 Options Database Key: 4932 . -ts_max_snes_failures - Maximum number of nonlinear solve failures 4933 4934 Level: intermediate 4935 4936 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()` 4937 @*/ 4938 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails) 4939 { 4940 PetscFunctionBegin; 4941 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4942 ts->max_snes_failures = fails; 4943 PetscFunctionReturn(PETSC_SUCCESS); 4944 } 4945 4946 /*@ 4947 TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()` 4948 4949 Not Collective 4950 4951 Input Parameters: 4952 + ts - `TS` context 4953 - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure 4954 4955 Options Database Key: 4956 . -ts_error_if_step_fails - Error if no step succeeds 4957 4958 Level: intermediate 4959 4960 .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4961 @*/ 4962 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err) 4963 { 4964 PetscFunctionBegin; 4965 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4966 ts->errorifstepfailed = err; 4967 PetscFunctionReturn(PETSC_SUCCESS); 4968 } 4969 4970 /*@ 4971 TSGetAdapt - Get the adaptive controller context for the current method 4972 4973 Collective on `ts` if controller has not been created yet 4974 4975 Input Parameter: 4976 . ts - time stepping context 4977 4978 Output Parameter: 4979 . adapt - adaptive controller 4980 4981 Level: intermediate 4982 4983 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()` 4984 @*/ 4985 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt) 4986 { 4987 PetscFunctionBegin; 4988 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4989 PetscValidPointer(adapt, 2); 4990 if (!ts->adapt) { 4991 PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt)); 4992 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1)); 4993 } 4994 *adapt = ts->adapt; 4995 PetscFunctionReturn(PETSC_SUCCESS); 4996 } 4997 4998 /*@ 4999 TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller 5000 5001 Logically Collective 5002 5003 Input Parameters: 5004 + ts - time integration context 5005 . atol - scalar absolute tolerances, `PETSC_DECIDE` to leave current value 5006 . vatol - vector of absolute tolerances or `NULL`, used in preference to atol if present 5007 . rtol - scalar relative tolerances, `PETSC_DECIDE` to leave current value 5008 - vrtol - vector of relative tolerances or `NULL`, used in preference to atol if present 5009 5010 Options Database Keys: 5011 + -ts_rtol <rtol> - relative tolerance for local truncation error 5012 - -ts_atol <atol> - Absolute tolerance for local truncation error 5013 5014 Level: beginner 5015 5016 Notes: 5017 With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error 5018 (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be 5019 computed only for the differential or the algebraic part then this can be done using the vector of 5020 tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the 5021 differential part and infinity for the algebraic part, the LTE calculation will include only the 5022 differential variables. 5023 5024 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()` 5025 @*/ 5026 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol) 5027 { 5028 PetscFunctionBegin; 5029 if (atol != (PetscReal)PETSC_DECIDE && atol != (PetscReal)PETSC_DEFAULT) ts->atol = atol; 5030 if (vatol) { 5031 PetscCall(PetscObjectReference((PetscObject)vatol)); 5032 PetscCall(VecDestroy(&ts->vatol)); 5033 ts->vatol = vatol; 5034 } 5035 if (rtol != (PetscReal)PETSC_DECIDE && rtol != (PetscReal)PETSC_DEFAULT) ts->rtol = rtol; 5036 if (vrtol) { 5037 PetscCall(PetscObjectReference((PetscObject)vrtol)); 5038 PetscCall(VecDestroy(&ts->vrtol)); 5039 ts->vrtol = vrtol; 5040 } 5041 PetscFunctionReturn(PETSC_SUCCESS); 5042 } 5043 5044 /*@ 5045 TSGetTolerances - Get tolerances for local truncation error when using adaptive controller 5046 5047 Logically Collective 5048 5049 Input Parameter: 5050 . ts - time integration context 5051 5052 Output Parameters: 5053 + atol - scalar absolute tolerances, `NULL` to ignore 5054 . vatol - vector of absolute tolerances, `NULL` to ignore 5055 . rtol - scalar relative tolerances, `NULL` to ignore 5056 - vrtol - vector of relative tolerances, `NULL` to ignore 5057 5058 Level: beginner 5059 5060 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()` 5061 @*/ 5062 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol) 5063 { 5064 PetscFunctionBegin; 5065 if (atol) *atol = ts->atol; 5066 if (vatol) *vatol = ts->vatol; 5067 if (rtol) *rtol = ts->rtol; 5068 if (vrtol) *vrtol = ts->vrtol; 5069 PetscFunctionReturn(PETSC_SUCCESS); 5070 } 5071 5072 /*@ 5073 TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances 5074 5075 Collective 5076 5077 Input Parameters: 5078 + ts - time stepping context 5079 . U - state vector, usually ts->vec_sol 5080 . Y - state vector to be compared to U 5081 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5082 5083 Output Parameters: 5084 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5085 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5086 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5087 5088 Options Database Key: 5089 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5090 5091 Level: developer 5092 5093 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()` 5094 @*/ 5095 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5096 { 5097 PetscInt norma_loc, norm_loc, normr_loc; 5098 5099 PetscFunctionBegin; 5100 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5101 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)); 5102 if (wnormtype == NORM_2) { 5103 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5104 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5105 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5106 } 5107 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5108 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5109 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5110 PetscFunctionReturn(PETSC_SUCCESS); 5111 } 5112 5113 /*@ 5114 TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances 5115 5116 Collective 5117 5118 Input Parameters: 5119 + ts - time stepping context 5120 . E - error vector 5121 . U - state vector, usually ts->vec_sol 5122 . Y - state vector, previous time step 5123 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5124 5125 Output Parameters: 5126 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5127 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5128 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5129 5130 Options Database Key: 5131 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5132 5133 Level: developer 5134 5135 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()` 5136 @*/ 5137 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5138 { 5139 PetscInt norma_loc, norm_loc, normr_loc; 5140 5141 PetscFunctionBegin; 5142 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5143 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)); 5144 if (wnormtype == NORM_2) { 5145 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5146 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5147 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5148 } 5149 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5150 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5151 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5152 PetscFunctionReturn(PETSC_SUCCESS); 5153 } 5154 5155 /*@ 5156 TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler 5157 5158 Logically Collective 5159 5160 Input Parameters: 5161 + ts - time stepping context 5162 - cfltime - maximum stable time step if using forward Euler (value can be different on each process) 5163 5164 Note: 5165 After calling this function, the global CFL time can be obtained by calling TSGetCFLTime() 5166 5167 Level: intermediate 5168 5169 .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL` 5170 @*/ 5171 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime) 5172 { 5173 PetscFunctionBegin; 5174 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5175 ts->cfltime_local = cfltime; 5176 ts->cfltime = -1.; 5177 PetscFunctionReturn(PETSC_SUCCESS); 5178 } 5179 5180 /*@ 5181 TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler 5182 5183 Collective 5184 5185 Input Parameter: 5186 . ts - time stepping context 5187 5188 Output Parameter: 5189 . cfltime - maximum stable time step for forward Euler 5190 5191 Level: advanced 5192 5193 .seealso: [](ch_ts), `TSSetCFLTimeLocal()` 5194 @*/ 5195 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime) 5196 { 5197 PetscFunctionBegin; 5198 if (ts->cfltime < 0) PetscCall(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts))); 5199 *cfltime = ts->cfltime; 5200 PetscFunctionReturn(PETSC_SUCCESS); 5201 } 5202 5203 /*@ 5204 TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu 5205 5206 Input Parameters: 5207 + ts - the `TS` context. 5208 . xl - lower bound. 5209 - xu - upper bound. 5210 5211 Level: advanced 5212 5213 Note: 5214 If this routine is not called then the lower and upper bounds are set to 5215 `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`. 5216 5217 .seealso: [](ch_ts), `TS` 5218 @*/ 5219 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) 5220 { 5221 SNES snes; 5222 5223 PetscFunctionBegin; 5224 PetscCall(TSGetSNES(ts, &snes)); 5225 PetscCall(SNESVISetVariableBounds(snes, xl, xu)); 5226 PetscFunctionReturn(PETSC_SUCCESS); 5227 } 5228 5229 /*@ 5230 TSComputeLinearStability - computes the linear stability function at a point 5231 5232 Collective 5233 5234 Input Parameters: 5235 + ts - the `TS` context 5236 . xr - real part of input argument 5237 - xi - imaginary part of input argument 5238 5239 Output Parameters: 5240 + yr - real part of function value 5241 - yi - imaginary part of function value 5242 5243 Level: developer 5244 5245 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()` 5246 @*/ 5247 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) 5248 { 5249 PetscFunctionBegin; 5250 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5251 PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi); 5252 PetscFunctionReturn(PETSC_SUCCESS); 5253 } 5254 5255 /*@ 5256 TSRestartStep - Flags the solver to restart the next step 5257 5258 Collective 5259 5260 Input Parameter: 5261 . ts - the `TS` context obtained from `TSCreate()` 5262 5263 Level: advanced 5264 5265 Notes: 5266 Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of 5267 discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution 5268 vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For 5269 the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce 5270 discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with 5271 discontinuous source terms). 5272 5273 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()` 5274 @*/ 5275 PetscErrorCode TSRestartStep(TS ts) 5276 { 5277 PetscFunctionBegin; 5278 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5279 ts->steprestart = PETSC_TRUE; 5280 PetscFunctionReturn(PETSC_SUCCESS); 5281 } 5282 5283 /*@ 5284 TSRollBack - Rolls back one time step 5285 5286 Collective 5287 5288 Input Parameter: 5289 . ts - the `TS` context obtained from `TSCreate()` 5290 5291 Level: advanced 5292 5293 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()` 5294 @*/ 5295 PetscErrorCode TSRollBack(TS ts) 5296 { 5297 PetscFunctionBegin; 5298 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5299 PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called"); 5300 PetscUseTypeMethod(ts, rollback); 5301 ts->time_step = ts->ptime - ts->ptime_prev; 5302 ts->ptime = ts->ptime_prev; 5303 ts->ptime_prev = ts->ptime_prev_rollback; 5304 ts->steps--; 5305 ts->steprollback = PETSC_TRUE; 5306 PetscFunctionReturn(PETSC_SUCCESS); 5307 } 5308 5309 /*@ 5310 TSGetStages - Get the number of stages and stage values 5311 5312 Input Parameter: 5313 . ts - the `TS` context obtained from `TSCreate()` 5314 5315 Output Parameters: 5316 + ns - the number of stages 5317 - Y - the current stage vectors 5318 5319 Level: advanced 5320 5321 Note: 5322 Both `ns` and `Y` can be `NULL`. 5323 5324 .seealso: [](ch_ts), `TS`, `TSCreate()` 5325 @*/ 5326 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y) 5327 { 5328 PetscFunctionBegin; 5329 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5330 if (ns) PetscValidIntPointer(ns, 2); 5331 if (Y) PetscValidPointer(Y, 3); 5332 if (!ts->ops->getstages) { 5333 if (ns) *ns = 0; 5334 if (Y) *Y = NULL; 5335 } else PetscUseTypeMethod(ts, getstages, ns, Y); 5336 PetscFunctionReturn(PETSC_SUCCESS); 5337 } 5338 5339 /*@C 5340 TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity. 5341 5342 Collective 5343 5344 Input Parameters: 5345 + ts - the `TS` context 5346 . t - current timestep 5347 . U - state vector 5348 . Udot - time derivative of state vector 5349 . shift - shift to apply, see note below 5350 - ctx - an optional user context 5351 5352 Output Parameters: 5353 + J - Jacobian matrix (not altered in this routine) 5354 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`) 5355 5356 Level: intermediate 5357 5358 Notes: 5359 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 5360 5361 dF/dU + shift*dF/dUdot 5362 5363 Most users should not need to explicitly call this routine, as it 5364 is used internally within the nonlinear solvers. 5365 5366 This will first try to get the coloring from the `DM`. If the `DM` type has no coloring 5367 routine, then it will try to get the coloring from the matrix. This requires that the 5368 matrix have nonzero entries precomputed. 5369 5370 .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5371 @*/ 5372 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx) 5373 { 5374 SNES snes; 5375 MatFDColoring color; 5376 PetscBool hascolor, matcolor = PETSC_FALSE; 5377 5378 PetscFunctionBegin; 5379 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL)); 5380 PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color)); 5381 if (!color) { 5382 DM dm; 5383 ISColoring iscoloring; 5384 5385 PetscCall(TSGetDM(ts, &dm)); 5386 PetscCall(DMHasColoring(dm, &hascolor)); 5387 if (hascolor && !matcolor) { 5388 PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 5389 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5390 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5391 PetscCall(MatFDColoringSetFromOptions(color)); 5392 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5393 PetscCall(ISColoringDestroy(&iscoloring)); 5394 } else { 5395 MatColoring mc; 5396 5397 PetscCall(MatColoringCreate(B, &mc)); 5398 PetscCall(MatColoringSetDistance(mc, 2)); 5399 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5400 PetscCall(MatColoringSetFromOptions(mc)); 5401 PetscCall(MatColoringApply(mc, &iscoloring)); 5402 PetscCall(MatColoringDestroy(&mc)); 5403 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5404 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5405 PetscCall(MatFDColoringSetFromOptions(color)); 5406 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5407 PetscCall(ISColoringDestroy(&iscoloring)); 5408 } 5409 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color)); 5410 PetscCall(PetscObjectDereference((PetscObject)color)); 5411 } 5412 PetscCall(TSGetSNES(ts, &snes)); 5413 PetscCall(MatFDColoringApply(B, color, U, snes)); 5414 if (J != B) { 5415 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 5416 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 5417 } 5418 PetscFunctionReturn(PETSC_SUCCESS); 5419 } 5420 5421 /*@C 5422 TSSetFunctionDomainError - Set a function that tests if the current state vector is valid 5423 5424 Input Parameters: 5425 + ts - the `TS` context 5426 - func - function called within `TSFunctionDomainError()` 5427 5428 Calling sequence of `func`: 5429 $ PetscErrorCode func(TS ts, PetscReal time, Vec state, PetscBool reject) 5430 + ts - the TS context 5431 . time - the current time (of the stage) 5432 . state - the state to check if it is valid 5433 - reject - (output parameter) `PETSC_FALSE` if the state is acceptable, `PETSC_TRUE` if not acceptable 5434 5435 Level: intermediate 5436 5437 Notes: 5438 If an implicit ODE solver is being used then, in addition to providing this routine, the 5439 user's code should call `SNESSetFunctionDomainError()` when domain errors occur during 5440 function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`. 5441 Use `TSGetSNES()` to obtain the `SNES` object 5442 5443 Developer Notes: 5444 The naming of this function is inconsistent with the `SNESSetFunctionDomainError()` 5445 since one takes a function pointer and the other does not. 5446 5447 .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()` 5448 @*/ 5449 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS, PetscReal, Vec, PetscBool *)) 5450 { 5451 PetscFunctionBegin; 5452 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5453 ts->functiondomainerror = func; 5454 PetscFunctionReturn(PETSC_SUCCESS); 5455 } 5456 5457 /*@ 5458 TSFunctionDomainError - Checks if the current state is valid 5459 5460 Input Parameters: 5461 + ts - the `TS` context 5462 . stagetime - time of the simulation 5463 - Y - state vector to check. 5464 5465 Output Parameter: 5466 . accept - Set to `PETSC_FALSE` if the current state vector is valid. 5467 5468 Level: developer 5469 5470 Note: 5471 This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`) 5472 to check if the current state is valid. 5473 5474 .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()` 5475 @*/ 5476 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept) 5477 { 5478 PetscFunctionBegin; 5479 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5480 *accept = PETSC_TRUE; 5481 if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept)); 5482 PetscFunctionReturn(PETSC_SUCCESS); 5483 } 5484 5485 /*@C 5486 TSClone - This function clones a time step `TS` object. 5487 5488 Collective 5489 5490 Input Parameter: 5491 . tsin - The input `TS` 5492 5493 Output Parameter: 5494 . tsout - The output `TS` (cloned) 5495 5496 Level: developer 5497 5498 Notes: 5499 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. 5500 It will likely be replaced in the future with a mechanism of switching methods on the fly. 5501 5502 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 5503 .vb 5504 SNES snes_dup = NULL; 5505 TSGetSNES(ts,&snes_dup); 5506 TSSetSNES(ts,snes_dup); 5507 .ve 5508 5509 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()` 5510 @*/ 5511 PetscErrorCode TSClone(TS tsin, TS *tsout) 5512 { 5513 TS t; 5514 SNES snes_start; 5515 DM dm; 5516 TSType type; 5517 5518 PetscFunctionBegin; 5519 PetscValidPointer(tsin, 1); 5520 *tsout = NULL; 5521 5522 PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView)); 5523 5524 /* General TS description */ 5525 t->numbermonitors = 0; 5526 t->monitorFrequency = 1; 5527 t->setupcalled = 0; 5528 t->ksp_its = 0; 5529 t->snes_its = 0; 5530 t->nwork = 0; 5531 t->rhsjacobian.time = PETSC_MIN_REAL; 5532 t->rhsjacobian.scale = 1.; 5533 t->ijacobian.shift = 1.; 5534 5535 PetscCall(TSGetSNES(tsin, &snes_start)); 5536 PetscCall(TSSetSNES(t, snes_start)); 5537 5538 PetscCall(TSGetDM(tsin, &dm)); 5539 PetscCall(TSSetDM(t, dm)); 5540 5541 t->adapt = tsin->adapt; 5542 PetscCall(PetscObjectReference((PetscObject)t->adapt)); 5543 5544 t->trajectory = tsin->trajectory; 5545 PetscCall(PetscObjectReference((PetscObject)t->trajectory)); 5546 5547 t->event = tsin->event; 5548 if (t->event) t->event->refct++; 5549 5550 t->problem_type = tsin->problem_type; 5551 t->ptime = tsin->ptime; 5552 t->ptime_prev = tsin->ptime_prev; 5553 t->time_step = tsin->time_step; 5554 t->max_time = tsin->max_time; 5555 t->steps = tsin->steps; 5556 t->max_steps = tsin->max_steps; 5557 t->equation_type = tsin->equation_type; 5558 t->atol = tsin->atol; 5559 t->rtol = tsin->rtol; 5560 t->max_snes_failures = tsin->max_snes_failures; 5561 t->max_reject = tsin->max_reject; 5562 t->errorifstepfailed = tsin->errorifstepfailed; 5563 5564 PetscCall(TSGetType(tsin, &type)); 5565 PetscCall(TSSetType(t, type)); 5566 5567 t->vec_sol = NULL; 5568 5569 t->cfltime = tsin->cfltime; 5570 t->cfltime_local = tsin->cfltime_local; 5571 t->exact_final_time = tsin->exact_final_time; 5572 5573 t->ops[0] = tsin->ops[0]; 5574 5575 if (((PetscObject)tsin)->fortran_func_pointers) { 5576 PetscInt i; 5577 PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers)); 5578 for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i]; 5579 } 5580 *tsout = t; 5581 PetscFunctionReturn(PETSC_SUCCESS); 5582 } 5583 5584 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y) 5585 { 5586 TS ts = (TS)ctx; 5587 5588 PetscFunctionBegin; 5589 PetscCall(TSComputeRHSFunction(ts, 0, x, y)); 5590 PetscFunctionReturn(PETSC_SUCCESS); 5591 } 5592 5593 /*@ 5594 TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5595 5596 Logically Collective 5597 5598 Input Parameter: 5599 . ts - the time stepping routine 5600 5601 Output Parameter: 5602 . flg - `PETSC_TRUE` if the multiply is likely correct 5603 5604 Options Database Key: 5605 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator 5606 5607 Level: advanced 5608 5609 Note: 5610 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5611 5612 .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()` 5613 @*/ 5614 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg) 5615 { 5616 Mat J, B; 5617 TSRHSJacobian func; 5618 void *ctx; 5619 5620 PetscFunctionBegin; 5621 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5622 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5623 PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5624 PetscFunctionReturn(PETSC_SUCCESS); 5625 } 5626 5627 /*@C 5628 TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5629 5630 Logically Collective 5631 5632 Input Parameter: 5633 . ts - the time stepping routine 5634 5635 Output Parameter: 5636 . flg - `PETSC_TRUE` if the multiply is likely correct 5637 5638 Options Database Key: 5639 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator 5640 5641 Level: advanced 5642 5643 Notes: 5644 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5645 5646 .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()` 5647 @*/ 5648 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg) 5649 { 5650 Mat J, B; 5651 void *ctx; 5652 TSRHSJacobian func; 5653 5654 PetscFunctionBegin; 5655 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5656 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5657 PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5658 PetscFunctionReturn(PETSC_SUCCESS); 5659 } 5660 5661 /*@ 5662 TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used. 5663 5664 Logically Collective 5665 5666 Input Parameters: 5667 + ts - timestepping context 5668 - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5669 5670 Options Database Key: 5671 . -ts_use_splitrhsfunction - <true,false> 5672 5673 Level: intermediate 5674 5675 Note: 5676 This is only for multirate methods 5677 5678 .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()` 5679 @*/ 5680 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) 5681 { 5682 PetscFunctionBegin; 5683 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5684 ts->use_splitrhsfunction = use_splitrhsfunction; 5685 PetscFunctionReturn(PETSC_SUCCESS); 5686 } 5687 5688 /*@ 5689 TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used. 5690 5691 Not Collective 5692 5693 Input Parameter: 5694 . ts - timestepping context 5695 5696 Output Parameter: 5697 . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5698 5699 Level: intermediate 5700 5701 .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()` 5702 @*/ 5703 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) 5704 { 5705 PetscFunctionBegin; 5706 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5707 *use_splitrhsfunction = ts->use_splitrhsfunction; 5708 PetscFunctionReturn(PETSC_SUCCESS); 5709 } 5710 5711 /*@ 5712 TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix. 5713 5714 Logically Collective 5715 5716 Input Parameters: 5717 + ts - the time-stepper 5718 - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`) 5719 5720 Level: intermediate 5721 5722 Note: 5723 When the relationship between the nonzero structures is known and supplied the solution process can be much faster 5724 5725 .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure` 5726 @*/ 5727 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str) 5728 { 5729 PetscFunctionBegin; 5730 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5731 ts->axpy_pattern = str; 5732 PetscFunctionReturn(PETSC_SUCCESS); 5733 } 5734 5735 /*@ 5736 TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span 5737 5738 Collective 5739 5740 Input Parameters: 5741 + ts - the time-stepper 5742 . n - number of the time points (>=2) 5743 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 5744 5745 Options Database Key: 5746 . -ts_time_span <t0,...tf> - Sets the time span 5747 5748 Level: intermediate 5749 5750 Notes: 5751 The elements in tspan must be all increasing. They correspond to the intermediate points for time integration. 5752 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 5753 The intermediate solutions are saved in a vector array that can be accessed with `TSGetTimeSpanSolutions()`. Thus using time span may 5754 pressure the memory system when using a large number of span points. 5755 5756 .seealso: [](ch_ts), `TS`, `TSGetTimeSpan()`, `TSGetTimeSpanSolutions()` 5757 @*/ 5758 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times) 5759 { 5760 PetscFunctionBegin; 5761 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5762 PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n); 5763 if (ts->tspan && n != ts->tspan->num_span_times) { 5764 PetscCall(PetscFree(ts->tspan->span_times)); 5765 PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol)); 5766 PetscCall(PetscMalloc1(n, &ts->tspan->span_times)); 5767 } 5768 if (!ts->tspan) { 5769 TSTimeSpan tspan; 5770 PetscCall(PetscNew(&tspan)); 5771 PetscCall(PetscMalloc1(n, &tspan->span_times)); 5772 tspan->reltol = 1e-6; 5773 tspan->abstol = 10 * PETSC_MACHINE_EPSILON; 5774 ts->tspan = tspan; 5775 } 5776 ts->tspan->num_span_times = n; 5777 PetscCall(PetscArraycpy(ts->tspan->span_times, span_times, n)); 5778 PetscCall(TSSetTime(ts, ts->tspan->span_times[0])); 5779 PetscCall(TSSetMaxTime(ts, ts->tspan->span_times[n - 1])); 5780 PetscFunctionReturn(PETSC_SUCCESS); 5781 } 5782 5783 /*@C 5784 TSGetTimeSpan - gets the time span set with `TSSetTimeSpan()` 5785 5786 Not Collective 5787 5788 Input Parameter: 5789 . ts - the time-stepper 5790 5791 Output Parameters: 5792 + n - number of the time points (>=2) 5793 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 5794 5795 Level: beginner 5796 5797 Note: 5798 The values obtained are valid until the `TS` object is destroyed. 5799 5800 Both `n` and `span_times` can be `NULL`. 5801 5802 .seealso: [](ch_ts), `TS`, `TSSetTimeSpan()`, `TSGetTimeSpanSolutions()` 5803 @*/ 5804 PetscErrorCode TSGetTimeSpan(TS ts, PetscInt *n, const PetscReal **span_times) 5805 { 5806 PetscFunctionBegin; 5807 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5808 if (n) PetscValidIntPointer(n, 2); 5809 if (span_times) PetscValidPointer(span_times, 3); 5810 if (!ts->tspan) { 5811 if (n) *n = 0; 5812 if (span_times) *span_times = NULL; 5813 } else { 5814 if (n) *n = ts->tspan->num_span_times; 5815 if (span_times) *span_times = ts->tspan->span_times; 5816 } 5817 PetscFunctionReturn(PETSC_SUCCESS); 5818 } 5819 5820 /*@ 5821 TSGetTimeSpanSolutions - Get the number of solutions and the solutions at the time points specified by the time span. 5822 5823 Input Parameter: 5824 . ts - the `TS` context obtained from `TSCreate()` 5825 5826 Output Parameters: 5827 + nsol - the number of solutions 5828 - Sols - the solution vectors 5829 5830 Level: intermediate 5831 5832 Notes: 5833 Both `nsol` and `Sols` can be `NULL`. 5834 5835 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()`. 5836 For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain points in the span. 5837 5838 .seealso: [](ch_ts), `TS`, `TSSetTimeSpan()` 5839 @*/ 5840 PetscErrorCode TSGetTimeSpanSolutions(TS ts, PetscInt *nsol, Vec **Sols) 5841 { 5842 PetscFunctionBegin; 5843 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5844 if (nsol) PetscValidIntPointer(nsol, 2); 5845 if (Sols) PetscValidPointer(Sols, 3); 5846 if (!ts->tspan) { 5847 if (nsol) *nsol = 0; 5848 if (Sols) *Sols = NULL; 5849 } else { 5850 if (nsol) *nsol = ts->tspan->spanctr; 5851 if (Sols) *Sols = ts->tspan->vecs_sol; 5852 } 5853 PetscFunctionReturn(PETSC_SUCCESS); 5854 } 5855 5856 /*@C 5857 TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information. 5858 5859 Collective 5860 5861 Input Parameters: 5862 + ts - the `TS` context 5863 . J - Jacobian matrix (not altered in this routine) 5864 - B - newly computed Jacobian matrix to use with preconditioner 5865 5866 Level: intermediate 5867 5868 Notes: 5869 This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains 5870 many constant zeros entries, which is typically the case when the matrix is generated by a `DM` 5871 and multiple fields are involved. 5872 5873 Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity 5874 structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can 5875 usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian. 5876 `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`. 5877 5878 .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5879 @*/ 5880 PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B) 5881 { 5882 MatColoring mc = NULL; 5883 ISColoring iscoloring = NULL; 5884 MatFDColoring matfdcoloring = NULL; 5885 5886 PetscFunctionBegin; 5887 /* Generate new coloring after eliminating zeros in the matrix */ 5888 PetscCall(MatEliminateZeros(B)); 5889 PetscCall(MatColoringCreate(B, &mc)); 5890 PetscCall(MatColoringSetDistance(mc, 2)); 5891 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5892 PetscCall(MatColoringSetFromOptions(mc)); 5893 PetscCall(MatColoringApply(mc, &iscoloring)); 5894 PetscCall(MatColoringDestroy(&mc)); 5895 /* Replace the old coloring with the new one */ 5896 PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring)); 5897 PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5898 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 5899 PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring)); 5900 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring)); 5901 PetscCall(PetscObjectDereference((PetscObject)matfdcoloring)); 5902 PetscCall(ISColoringDestroy(&iscoloring)); 5903 PetscFunctionReturn(PETSC_SUCCESS); 5904 } 5905