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