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