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