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