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