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