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