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