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(0); 24 } 25 26 /*@ 27 TSSetFromOptions - Sets various `TS` parameters from user options. 28 29 Collective on ts 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, *ptr2; 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(0); 410 } 411 412 /*@ 413 TSGetTrajectory - Gets the trajectory from a `TS` if it exists 414 415 Collective on ts 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(0); 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 on ts 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(0); 466 } 467 468 /*@ 469 TSResetTrajectory - Destroys and recreates the internal `TSTrajectory` object 470 471 Collective on ts 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(0); 489 } 490 491 /*@ 492 TSRemoveTrajectory - Destroys and removes the internal `TSTrajectory` object from TS 493 494 Collective on ts 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(0); 509 } 510 511 /*@ 512 TSComputeRHSJacobian - Computes the Jacobian matrix that has been 513 set with `TSSetRHSJacobian()`. 514 515 Collective on ts 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(0); 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(0); 573 } 574 575 /*@ 576 TSComputeRHSFunction - Evaluates the right-hand-side function for a `TS` 577 578 Collective on ts 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(0); 622 } 623 624 /*@ 625 TSComputeSolutionFunction - Evaluates the solution function. 626 627 Collective on ts 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(0); 653 } 654 /*@ 655 TSComputeForcingFunction - Evaluates the forcing function. 656 657 Collective on ts 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(0); 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(0); 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(0); 745 } 746 747 /*@ 748 TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,U,Udot)=0 749 750 Collective on ts 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(0); 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(0); 837 } 838 839 /*@ 840 TSComputeIJacobian - Evaluates the Jacobian of the DAE 841 842 Collective on ts 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(0); 980 } 981 982 /*@C 983 TSSetRHSFunction - Sets the routine for evaluating the function, 984 where U_t = G(t,u). 985 986 Logically Collective on ts 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(0); 1031 } 1032 1033 /*@C 1034 TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE 1035 1036 Logically Collective on ts 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(0); 1075 } 1076 1077 /*@C 1078 TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE 1079 1080 Logically Collective on ts 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(0); 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 on ts 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(0); 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 on ts 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(0); 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(0); 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(0); 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 on ts 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(0); 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(0); 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 on ts 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(0); 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(0); 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 on ts 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(0); 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(0); 1541 } 1542 1543 /*@ 1544 TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0 1545 1546 Collective on ts 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(0); 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(0); 1602 } 1603 1604 /*@ 1605 TSComputeI2Jacobian - Evaluates the Jacobian of the DAE 1606 1607 Collective on ts 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(0); 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(0); 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(0); 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(0); 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(0); 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 on ts 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(0); 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(0); 1836 } 1837 1838 /*@C 1839 TSLoad - Loads a `TS` that has been stored in binary with `TSView()`. 1840 1841 Collective on PetscViewer 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(0); 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 on ts 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(0); 1909 } 1910 1911 /*@C 1912 TSView - Prints the `TS` data structure. 1913 1914 Collective on ts 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(0); 2060 } 2061 2062 /*@ 2063 TSSetApplicationContext - Sets an optional user-defined context for 2064 the timesteppers. 2065 2066 Logically Collective on ts 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(0); 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(0); 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(0); 2138 } 2139 2140 /*@ 2141 TSSetStepNumber - Sets the number of steps completed. 2142 2143 Logically Collective on ts 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(0); 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 on ts 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(0); 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 on ts 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(0); 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(0); 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(0); 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(0); 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 PETSC_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 PETSC_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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 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(0); 2491 } 2492 2493 /*@ 2494 TSSetUp - Sets up the internal data structures for the later use of a timestepper. 2495 2496 Collective on ts 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(0); 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(0); 2599 } 2600 2601 /*@ 2602 TSReset - Resets a `TS` context and removes any allocated `Vec`s and `Mat`s. 2603 2604 Collective on ts 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(0); 2657 } 2658 2659 /*@C 2660 TSDestroy - Destroys the timestepper context that was created 2661 with `TSCreate()`. 2662 2663 Collective on ts 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(0); 2676 PetscValidHeaderSpecific(*ts, TS_CLASSID, 1); 2677 if (--((PetscObject)(*ts))->refct > 0) { 2678 *ts = NULL; 2679 PetscFunctionReturn(0); 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(0); 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(0); 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(0); 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(0); 2816 } 2817 2818 /* ----------- Routines to set solver parameters ---------- */ 2819 2820 /*@ 2821 TSSetMaxSteps - Sets the maximum number of steps to use. 2822 2823 Logically Collective on ts 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(0); 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(0); 2871 } 2872 2873 /*@ 2874 TSSetMaxTime - Sets the maximum (or final) time for timestepping. 2875 2876 Logically Collective on ts 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(0); 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(0); 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(0); 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(0); 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(0); 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 on ts 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(0); 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 on ts 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(0); 3055 } 3056 3057 /*@ 3058 TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()` 3059 3060 Collective on ts 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(0); 3093 } 3094 3095 /*@C 3096 TSSetPreStage - Sets the general-purpose function 3097 called once at the beginning of each stage. 3098 3099 Logically Collective on ts 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(0); 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 on ts 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(0); 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 on ts 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(0); 3191 } 3192 3193 /*@ 3194 TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()` 3195 3196 Collective on ts 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(0); 3216 } 3217 3218 /*@ 3219 TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()` 3220 3221 Collective on ts 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(0); 3244 } 3245 3246 /*@ 3247 TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()` 3248 3249 Collective on ts 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(0); 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 on ts 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(0); 3307 } 3308 3309 /*@ 3310 TSPostStep - Runs the user-defined post-step function that was set with `TSSetPotsStep()` 3311 3312 Collective on ts 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(0); 3345 } 3346 3347 /*@ 3348 TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval 3349 3350 Collective on ts 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(0); 3374 } 3375 3376 /*@ 3377 TSStep - Steps one time step 3378 3379 Collective on ts 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 PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed || 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]); 3442 PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]); 3443 PetscFunctionReturn(0); 3444 } 3445 3446 /*@ 3447 TSEvaluateWLTE - Evaluate the weighted local truncation error norm 3448 at the end of a time step with a given order of accuracy. 3449 3450 Collective on ts 3451 3452 Input Parameters: 3453 + ts - time stepping context 3454 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 3455 3456 Input/Output Parameter: 3457 . order - optional, desired order for the error evaluation or `PETSC_DECIDE`; 3458 on output, the actual order of the error evaluation 3459 3460 Output Parameter: 3461 . wlte - the weighted local truncation error norm 3462 3463 Level: advanced 3464 3465 Note: 3466 If the timestepper cannot evaluate the error in a particular step 3467 (eg. in the first step or restart steps after event handling), 3468 this routine returns wlte=-1.0 . 3469 3470 .seealso: [](chapter_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()` 3471 @*/ 3472 PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte) 3473 { 3474 PetscFunctionBegin; 3475 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3476 PetscValidType(ts, 1); 3477 PetscValidLogicalCollectiveEnum(ts, wnormtype, 2); 3478 if (order) PetscValidIntPointer(order, 3); 3479 if (order) PetscValidLogicalCollectiveInt(ts, *order, 3); 3480 PetscValidRealPointer(wlte, 4); 3481 PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 3482 PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte); 3483 PetscFunctionReturn(0); 3484 } 3485 3486 /*@ 3487 TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy. 3488 3489 Collective on ts 3490 3491 Input Parameters: 3492 + ts - time stepping context 3493 . order - desired order of accuracy 3494 - done - whether the step was evaluated at this order (pass NULL to generate an error if not available) 3495 3496 Output Parameter: 3497 . U - state at the end of the current step 3498 3499 Level: advanced 3500 3501 Notes: 3502 This function cannot be called until all stages have been evaluated. 3503 3504 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. 3505 3506 .seealso: [](chapter_ts), `TS`, `TSStep()`, `TSAdapt` 3507 @*/ 3508 PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done) 3509 { 3510 PetscFunctionBegin; 3511 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3512 PetscValidType(ts, 1); 3513 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3514 PetscUseTypeMethod(ts, evaluatestep, order, U, done); 3515 PetscFunctionReturn(0); 3516 } 3517 3518 /*@C 3519 TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping. 3520 3521 Not collective 3522 3523 Input Parameter: 3524 . ts - time stepping context 3525 3526 Output Parameter: 3527 . initConditions - The function which computes an initial condition 3528 3529 The calling sequence for the function is 3530 .vb 3531 initCondition(TS ts, Vec u) 3532 ts - The timestepping context 3533 u - The input vector in which the initial condition is stored 3534 .ve 3535 3536 Level: advanced 3537 3538 .seealso: [](chapter_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()` 3539 @*/ 3540 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS, Vec)) 3541 { 3542 PetscFunctionBegin; 3543 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3544 PetscValidPointer(initCondition, 2); 3545 *initCondition = ts->ops->initcondition; 3546 PetscFunctionReturn(0); 3547 } 3548 3549 /*@C 3550 TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping. 3551 3552 Logically collective on ts 3553 3554 Input Parameters: 3555 + ts - time stepping context 3556 - initCondition - The function which computes an initial condition 3557 3558 Calling sequence for initCondition: 3559 $ PetscErrorCode initCondition(TS ts, Vec u) 3560 + ts - The timestepping context 3561 - u - The input vector in which the initial condition is to be stored 3562 3563 Level: advanced 3564 3565 .seealso: [](chapter_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()` 3566 @*/ 3567 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS, Vec)) 3568 { 3569 PetscFunctionBegin; 3570 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3571 PetscValidFunction(initCondition, 2); 3572 ts->ops->initcondition = initCondition; 3573 PetscFunctionReturn(0); 3574 } 3575 3576 /*@ 3577 TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()` 3578 3579 Collective on ts 3580 3581 Input Parameters: 3582 + ts - time stepping context 3583 - u - The `Vec` to store the condition in which will be used in `TSSolve()` 3584 3585 Level: advanced 3586 3587 .seealso: [](chapter_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3588 @*/ 3589 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u) 3590 { 3591 PetscFunctionBegin; 3592 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3593 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3594 PetscTryTypeMethod(ts, initcondition, u); 3595 PetscFunctionReturn(0); 3596 } 3597 3598 /*@C 3599 TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping. 3600 3601 Not collective 3602 3603 Input Parameter: 3604 . ts - time stepping context 3605 3606 Output Parameter: 3607 . exactError - The function which computes the solution error 3608 3609 Calling sequence for exactError: 3610 $ PetscErrorCode exactError(TS ts, Vec u) 3611 + ts - The timestepping context 3612 . u - The approximate solution vector 3613 - e - The input vector in which the error is stored 3614 3615 Level: advanced 3616 3617 .seealso: [](chapter_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()` 3618 @*/ 3619 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS, Vec, Vec)) 3620 { 3621 PetscFunctionBegin; 3622 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3623 PetscValidPointer(exactError, 2); 3624 *exactError = ts->ops->exacterror; 3625 PetscFunctionReturn(0); 3626 } 3627 3628 /*@C 3629 TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping. 3630 3631 Logically collective on ts 3632 3633 Input Parameters: 3634 + ts - time stepping context 3635 - exactError - The function which computes the solution error 3636 3637 Calling sequence for exactError: 3638 $ PetscErrorCode exactError(TS ts, Vec u) 3639 + ts - The timestepping context 3640 . u - The approximate solution vector 3641 - e - The input vector in which the error is stored 3642 3643 Level: advanced 3644 3645 .seealso: [](chapter_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()` 3646 @*/ 3647 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS, Vec, Vec)) 3648 { 3649 PetscFunctionBegin; 3650 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3651 PetscValidFunction(exactError, 2); 3652 ts->ops->exacterror = exactError; 3653 PetscFunctionReturn(0); 3654 } 3655 3656 /*@ 3657 TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()` 3658 3659 Collective on ts 3660 3661 Input Parameters: 3662 + ts - time stepping context 3663 . u - The approximate solution 3664 - e - The `Vec` used to store the error 3665 3666 Level: advanced 3667 3668 .seealso: [](chapter_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3669 @*/ 3670 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e) 3671 { 3672 PetscFunctionBegin; 3673 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3674 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3675 PetscValidHeaderSpecific(e, VEC_CLASSID, 3); 3676 PetscTryTypeMethod(ts, exacterror, u, e); 3677 PetscFunctionReturn(0); 3678 } 3679 3680 /*@ 3681 TSSolve - Steps the requested number of timesteps. 3682 3683 Collective on ts 3684 3685 Input Parameters: 3686 + ts - the `TS` context obtained from `TSCreate()` 3687 - u - the solution vector (can be null if `TSSetSolution()` was used and `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`) was not used, 3688 otherwise must contain the initial conditions and will contain the solution at the final requested time 3689 3690 Level: beginner 3691 3692 Notes: 3693 The final time returned by this function may be different from the time of the internally 3694 held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have 3695 stepped over the final time. 3696 3697 .seealso: [](chapter_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()` 3698 @*/ 3699 PetscErrorCode TSSolve(TS ts, Vec u) 3700 { 3701 Vec solution; 3702 3703 PetscFunctionBegin; 3704 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3705 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3706 3707 PetscCall(TSSetExactFinalTimeDefault(ts)); 3708 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 */ 3709 if (!ts->vec_sol || u == ts->vec_sol) { 3710 PetscCall(VecDuplicate(u, &solution)); 3711 PetscCall(TSSetSolution(ts, solution)); 3712 PetscCall(VecDestroy(&solution)); /* grant ownership */ 3713 } 3714 PetscCall(VecCopy(u, ts->vec_sol)); 3715 PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE"); 3716 } else if (u) PetscCall(TSSetSolution(ts, u)); 3717 PetscCall(TSSetUp(ts)); 3718 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 3719 3720 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>"); 3721 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()"); 3722 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"); 3723 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"); 3724 3725 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 */ 3726 PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[0])); 3727 ts->tspan->spanctr = 1; 3728 } 3729 3730 if (ts->forward_solve) PetscCall(TSForwardSetUp(ts)); 3731 3732 /* reset number of steps only when the step is not restarted. ARKIMEX 3733 restarts the step after an event. Resetting these counters in such case causes 3734 TSTrajectory to incorrectly save the output files 3735 */ 3736 /* reset time step and iteration counters */ 3737 if (!ts->steps) { 3738 ts->ksp_its = 0; 3739 ts->snes_its = 0; 3740 ts->num_snes_failures = 0; 3741 ts->reject = 0; 3742 ts->steprestart = PETSC_TRUE; 3743 ts->steprollback = PETSC_FALSE; 3744 ts->rhsjacobian.time = PETSC_MIN_REAL; 3745 } 3746 3747 /* make sure initial time step does not overshoot final time or the next point in tspan */ 3748 if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 3749 PetscReal maxdt; 3750 PetscReal dt = ts->time_step; 3751 3752 if (ts->tspan) maxdt = ts->tspan->span_times[ts->tspan->spanctr] - ts->ptime; 3753 else maxdt = ts->max_time - ts->ptime; 3754 ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt); 3755 } 3756 ts->reason = TS_CONVERGED_ITERATING; 3757 3758 { 3759 PetscViewer viewer; 3760 PetscViewerFormat format; 3761 PetscBool flg; 3762 static PetscBool incall = PETSC_FALSE; 3763 3764 if (!incall) { 3765 /* Estimate the convergence rate of the time discretization */ 3766 PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg)); 3767 if (flg) { 3768 PetscConvEst conv; 3769 DM dm; 3770 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 3771 PetscInt Nf; 3772 PetscBool checkTemporal = PETSC_TRUE; 3773 3774 incall = PETSC_TRUE; 3775 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg)); 3776 PetscCall(TSGetDM(ts, &dm)); 3777 PetscCall(DMGetNumFields(dm, &Nf)); 3778 PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha)); 3779 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv)); 3780 PetscCall(PetscConvEstUseTS(conv, checkTemporal)); 3781 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts)); 3782 PetscCall(PetscConvEstSetFromOptions(conv)); 3783 PetscCall(PetscConvEstSetUp(conv)); 3784 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 3785 PetscCall(PetscViewerPushFormat(viewer, format)); 3786 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 3787 PetscCall(PetscViewerPopFormat(viewer)); 3788 PetscCall(PetscViewerDestroy(&viewer)); 3789 PetscCall(PetscConvEstDestroy(&conv)); 3790 PetscCall(PetscFree(alpha)); 3791 incall = PETSC_FALSE; 3792 } 3793 } 3794 } 3795 3796 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre")); 3797 3798 if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */ 3799 PetscUseTypeMethod(ts, solve); 3800 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 3801 ts->solvetime = ts->ptime; 3802 solution = ts->vec_sol; 3803 } else { /* Step the requested number of timesteps. */ 3804 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 3805 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 3806 3807 if (!ts->steps) { 3808 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 3809 PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol)); 3810 } 3811 3812 while (!ts->reason) { 3813 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 3814 if (!ts->steprollback) PetscCall(TSPreStep(ts)); 3815 PetscCall(TSStep(ts)); 3816 if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL)); 3817 if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL)); 3818 if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */ 3819 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 3820 PetscCall(TSForwardCostIntegral(ts)); 3821 if (ts->reason >= 0) ts->steps++; 3822 } 3823 if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */ 3824 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 3825 PetscCall(TSForwardStep(ts)); 3826 if (ts->reason >= 0) ts->steps++; 3827 } 3828 PetscCall(TSPostEvaluate(ts)); 3829 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. */ 3830 if (ts->steprollback) PetscCall(TSPostEvaluate(ts)); 3831 if (!ts->steprollback) { 3832 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 3833 PetscCall(TSPostStep(ts)); 3834 } 3835 } 3836 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 3837 3838 if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) { 3839 PetscCall(TSInterpolate(ts, ts->max_time, u)); 3840 ts->solvetime = ts->max_time; 3841 solution = u; 3842 PetscCall(TSMonitor(ts, -1, ts->solvetime, solution)); 3843 } else { 3844 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 3845 ts->solvetime = ts->ptime; 3846 solution = ts->vec_sol; 3847 } 3848 } 3849 3850 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view")); 3851 PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution")); 3852 PetscCall(PetscObjectSAWsBlock((PetscObject)ts)); 3853 if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts)); 3854 PetscFunctionReturn(0); 3855 } 3856 3857 /*@ 3858 TSGetTime - Gets the time of the most recently completed step. 3859 3860 Not Collective 3861 3862 Input Parameter: 3863 . ts - the `TS` context obtained from `TSCreate()` 3864 3865 Output Parameter: 3866 . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`. 3867 3868 Level: beginner 3869 3870 Note: 3871 When called during time step evaluation (e.g. during residual evaluation or via hooks set using `TSSetPreStep()`, 3872 `TSSetPreStage()`, `TSSetPostStage()`, or `TSSetPostStep()`), the time is the time at the start of the step being evaluated. 3873 3874 .seealso: [](chapter_ts), TS`, ``TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()` 3875 @*/ 3876 PetscErrorCode TSGetTime(TS ts, PetscReal *t) 3877 { 3878 PetscFunctionBegin; 3879 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3880 PetscValidRealPointer(t, 2); 3881 *t = ts->ptime; 3882 PetscFunctionReturn(0); 3883 } 3884 3885 /*@ 3886 TSGetPrevTime - Gets the starting time of the previously completed step. 3887 3888 Not Collective 3889 3890 Input Parameter: 3891 . ts - the `TS` context obtained from `TSCreate()` 3892 3893 Output Parameter: 3894 . t - the previous time 3895 3896 Level: beginner 3897 3898 .seealso: [](chapter_ts), TS`, ``TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()` 3899 @*/ 3900 PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t) 3901 { 3902 PetscFunctionBegin; 3903 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3904 PetscValidRealPointer(t, 2); 3905 *t = ts->ptime_prev; 3906 PetscFunctionReturn(0); 3907 } 3908 3909 /*@ 3910 TSSetTime - Allows one to reset the time. 3911 3912 Logically Collective on ts 3913 3914 Input Parameters: 3915 + ts - the `TS` context obtained from `TSCreate()` 3916 - time - the time 3917 3918 Level: intermediate 3919 3920 .seealso: [](chapter_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()` 3921 @*/ 3922 PetscErrorCode TSSetTime(TS ts, PetscReal t) 3923 { 3924 PetscFunctionBegin; 3925 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3926 PetscValidLogicalCollectiveReal(ts, t, 2); 3927 ts->ptime = t; 3928 PetscFunctionReturn(0); 3929 } 3930 3931 /*@C 3932 TSSetOptionsPrefix - Sets the prefix used for searching for all 3933 TS options in the database. 3934 3935 Logically Collective on ts 3936 3937 Input Parameters: 3938 + ts - The `TS` context 3939 - prefix - The prefix to prepend to all option names 3940 3941 Level: advanced 3942 3943 Note: 3944 A hyphen (-) must NOT be given at the beginning of the prefix name. 3945 The first character of all runtime options is AUTOMATICALLY the 3946 hyphen. 3947 3948 .seealso: [](chapter_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()` 3949 @*/ 3950 PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[]) 3951 { 3952 SNES snes; 3953 3954 PetscFunctionBegin; 3955 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3956 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix)); 3957 PetscCall(TSGetSNES(ts, &snes)); 3958 PetscCall(SNESSetOptionsPrefix(snes, prefix)); 3959 PetscFunctionReturn(0); 3960 } 3961 3962 /*@C 3963 TSAppendOptionsPrefix - Appends to the prefix used for searching for all 3964 TS options in the database. 3965 3966 Logically Collective on ts 3967 3968 Input Parameters: 3969 + ts - The `TS` context 3970 - prefix - The prefix to prepend to all option names 3971 3972 Level: advanced 3973 3974 Note: 3975 A hyphen (-) must NOT be given at the beginning of the prefix name. 3976 The first character of all runtime options is AUTOMATICALLY the 3977 hyphen. 3978 3979 .seealso: [](chapter_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()` 3980 @*/ 3981 PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[]) 3982 { 3983 SNES snes; 3984 3985 PetscFunctionBegin; 3986 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3987 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix)); 3988 PetscCall(TSGetSNES(ts, &snes)); 3989 PetscCall(SNESAppendOptionsPrefix(snes, prefix)); 3990 PetscFunctionReturn(0); 3991 } 3992 3993 /*@C 3994 TSGetOptionsPrefix - Sets the prefix used for searching for all 3995 `TS` options in the database. 3996 3997 Not Collective 3998 3999 Input Parameter: 4000 . ts - The `TS` context 4001 4002 Output Parameter: 4003 . prefix - A pointer to the prefix string used 4004 4005 Level: intermediate 4006 4007 Fortran Note: 4008 On the fortran side, the user should pass in a string 'prefix' of 4009 sufficient length to hold the prefix. 4010 4011 .seealso: [](chapter_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()` 4012 @*/ 4013 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[]) 4014 { 4015 PetscFunctionBegin; 4016 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4017 PetscValidPointer(prefix, 2); 4018 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix)); 4019 PetscFunctionReturn(0); 4020 } 4021 4022 /*@C 4023 TSGetRHSJacobian - Returns the Jacobian J at the present timestep. 4024 4025 Not Collective, but parallel objects are returned if ts is parallel 4026 4027 Input Parameter: 4028 . ts - The `TS` context obtained from `TSCreate()` 4029 4030 Output Parameters: 4031 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or NULL) 4032 . Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat (or NULL) 4033 . func - Function to compute the Jacobian of the RHS (or NULL) 4034 - ctx - User-defined context for Jacobian evaluation routine (or NULL) 4035 4036 Level: intermediate 4037 4038 Note: 4039 You can pass in NULL for any return argument you do not need. 4040 4041 .seealso: [](chapter_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4042 4043 @*/ 4044 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobian *func, void **ctx) 4045 { 4046 DM dm; 4047 4048 PetscFunctionBegin; 4049 if (Amat || Pmat) { 4050 SNES snes; 4051 PetscCall(TSGetSNES(ts, &snes)); 4052 PetscCall(SNESSetUpMatrices(snes)); 4053 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4054 } 4055 PetscCall(TSGetDM(ts, &dm)); 4056 PetscCall(DMTSGetRHSJacobian(dm, func, ctx)); 4057 PetscFunctionReturn(0); 4058 } 4059 4060 /*@C 4061 TSGetIJacobian - Returns the implicit Jacobian at the present timestep. 4062 4063 Not Collective, but parallel objects are returned if ts is parallel 4064 4065 Input Parameter: 4066 . ts - The `TS` context obtained from `TSCreate()` 4067 4068 Output Parameters: 4069 + Amat - The (approximate) Jacobian of F(t,U,U_t) 4070 . Pmat - The matrix from which the preconditioner is constructed, often the same as Amat 4071 . f - The function to compute the matrices 4072 - ctx - User-defined context for Jacobian evaluation routine 4073 4074 Level: advanced 4075 4076 Note: 4077 You can pass in NULL for any return argument you do not need. 4078 4079 .seealso: [](chapter_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4080 4081 @*/ 4082 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobian *f, void **ctx) 4083 { 4084 DM dm; 4085 4086 PetscFunctionBegin; 4087 if (Amat || Pmat) { 4088 SNES snes; 4089 PetscCall(TSGetSNES(ts, &snes)); 4090 PetscCall(SNESSetUpMatrices(snes)); 4091 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4092 } 4093 PetscCall(TSGetDM(ts, &dm)); 4094 PetscCall(DMTSGetIJacobian(dm, f, ctx)); 4095 PetscFunctionReturn(0); 4096 } 4097 4098 #include <petsc/private/dmimpl.h> 4099 /*@ 4100 TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS` 4101 4102 Logically Collective on ts 4103 4104 Input Parameters: 4105 + ts - the `TS` integrator object 4106 - dm - the dm, cannot be NULL 4107 4108 Level: intermediate 4109 4110 Notes: 4111 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 4112 even when not using interfaces like `DMTSSetIFunction()`. Use `DMClone()` to get a distinct `DM` when solving 4113 different problems using the same function space. 4114 4115 .seealso: [](chapter_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()` 4116 @*/ 4117 PetscErrorCode TSSetDM(TS ts, DM dm) 4118 { 4119 SNES snes; 4120 DMTS tsdm; 4121 4122 PetscFunctionBegin; 4123 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4124 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 4125 PetscCall(PetscObjectReference((PetscObject)dm)); 4126 if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */ 4127 if (ts->dm->dmts && !dm->dmts) { 4128 PetscCall(DMCopyDMTS(ts->dm, dm)); 4129 PetscCall(DMGetDMTS(ts->dm, &tsdm)); 4130 /* Grant write privileges to the replacement DM */ 4131 if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm; 4132 } 4133 PetscCall(DMDestroy(&ts->dm)); 4134 } 4135 ts->dm = dm; 4136 4137 PetscCall(TSGetSNES(ts, &snes)); 4138 PetscCall(SNESSetDM(snes, dm)); 4139 PetscFunctionReturn(0); 4140 } 4141 4142 /*@ 4143 TSGetDM - Gets the `DM` that may be used by some preconditioners 4144 4145 Not Collective 4146 4147 Input Parameter: 4148 . ts - the `TS` 4149 4150 Output Parameter: 4151 . dm - the dm 4152 4153 Level: intermediate 4154 4155 .seealso: [](chapter_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()` 4156 @*/ 4157 PetscErrorCode TSGetDM(TS ts, DM *dm) 4158 { 4159 PetscFunctionBegin; 4160 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4161 if (!ts->dm) { 4162 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm)); 4163 if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm)); 4164 } 4165 *dm = ts->dm; 4166 PetscFunctionReturn(0); 4167 } 4168 4169 /*@ 4170 SNESTSFormFunction - Function to evaluate nonlinear residual 4171 4172 Logically Collective on snes 4173 4174 Input Parameters: 4175 + snes - nonlinear solver 4176 . U - the current state at which to evaluate the residual 4177 - ctx - user context, must be a TS 4178 4179 Output Parameter: 4180 . F - the nonlinear residual 4181 4182 Level: advanced 4183 4184 Note: 4185 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4186 It is most frequently passed to `MatFDColoringSetFunction()`. 4187 4188 .seealso: [](chapter_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()` 4189 @*/ 4190 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx) 4191 { 4192 TS ts = (TS)ctx; 4193 4194 PetscFunctionBegin; 4195 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4196 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4197 PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 4198 PetscValidHeaderSpecific(ts, TS_CLASSID, 4); 4199 PetscCall((ts->ops->snesfunction)(snes, U, F, ts)); 4200 PetscFunctionReturn(0); 4201 } 4202 4203 /*@ 4204 SNESTSFormJacobian - Function to evaluate the Jacobian 4205 4206 Collective on snes 4207 4208 Input Parameters: 4209 + snes - nonlinear solver 4210 . U - the current state at which to evaluate the residual 4211 - ctx - user context, must be a `TS` 4212 4213 Output Parameters: 4214 + A - the Jacobian 4215 - B - the preconditioning matrix (may be the same as A) 4216 4217 Level: developer 4218 4219 Note: 4220 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4221 4222 .seealso: [](chapter_ts), `SNESSetJacobian()` 4223 @*/ 4224 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx) 4225 { 4226 TS ts = (TS)ctx; 4227 4228 PetscFunctionBegin; 4229 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4230 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4231 PetscValidPointer(A, 3); 4232 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 4233 PetscValidPointer(B, 4); 4234 PetscValidHeaderSpecific(B, MAT_CLASSID, 4); 4235 PetscValidHeaderSpecific(ts, TS_CLASSID, 5); 4236 PetscCall((ts->ops->snesjacobian)(snes, U, A, B, ts)); 4237 PetscFunctionReturn(0); 4238 } 4239 4240 /*@C 4241 TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only 4242 4243 Collective on ts 4244 4245 Input Parameters: 4246 + ts - time stepping context 4247 . t - time at which to evaluate 4248 . U - state at which to evaluate 4249 - ctx - context 4250 4251 Output Parameter: 4252 . F - right hand side 4253 4254 Level: intermediate 4255 4256 Note: 4257 This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right hand side for linear problems. 4258 The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`. 4259 4260 .seealso: [](chapter_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 4261 @*/ 4262 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx) 4263 { 4264 Mat Arhs, Brhs; 4265 4266 PetscFunctionBegin; 4267 PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs)); 4268 /* undo the damage caused by shifting */ 4269 PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs)); 4270 PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs)); 4271 PetscCall(MatMult(Arhs, U, F)); 4272 PetscFunctionReturn(0); 4273 } 4274 4275 /*@C 4276 TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent. 4277 4278 Collective on ts 4279 4280 Input Parameters: 4281 + ts - time stepping context 4282 . t - time at which to evaluate 4283 . U - state at which to evaluate 4284 - ctx - context 4285 4286 Output Parameters: 4287 + A - pointer to operator 4288 - B - pointer to preconditioning matrix 4289 4290 Level: intermediate 4291 4292 Note: 4293 This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems. 4294 4295 .seealso: [](chapter_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()` 4296 @*/ 4297 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx) 4298 { 4299 PetscFunctionBegin; 4300 PetscFunctionReturn(0); 4301 } 4302 4303 /*@C 4304 TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only 4305 4306 Collective on ts 4307 4308 Input Parameters: 4309 + ts - time stepping context 4310 . t - time at which to evaluate 4311 . U - state at which to evaluate 4312 . Udot - time derivative of state vector 4313 - ctx - context 4314 4315 Output Parameter: 4316 . F - left hand side 4317 4318 Level: intermediate 4319 4320 Notes: 4321 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 4322 user is required to write their own `TSComputeIFunction()`. 4323 This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems. 4324 The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`. 4325 4326 Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U 4327 4328 .seealso: [](chapter_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()` 4329 @*/ 4330 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx) 4331 { 4332 Mat A, B; 4333 4334 PetscFunctionBegin; 4335 PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL)); 4336 PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE)); 4337 PetscCall(MatMult(A, Udot, F)); 4338 PetscFunctionReturn(0); 4339 } 4340 4341 /*@C 4342 TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE 4343 4344 Collective on ts 4345 4346 Input Parameters: 4347 + ts - time stepping context 4348 . t - time at which to evaluate 4349 . U - state at which to evaluate 4350 . Udot - time derivative of state vector 4351 . shift - shift to apply 4352 - ctx - context 4353 4354 Output Parameters: 4355 + A - pointer to operator 4356 - B - pointer to preconditioning matrix 4357 4358 Level: advanced 4359 4360 Notes: 4361 This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems. 4362 4363 It is only appropriate for problems of the form 4364 4365 $ M Udot = F(U,t) 4366 4367 where M is constant and F is non-stiff. The user must pass M to `TSSetIJacobian()`. The current implementation only 4368 works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing 4369 an implicit operator of the form 4370 4371 $ shift*M + J 4372 4373 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 4374 a copy of M or reassemble it when requested. 4375 4376 .seealso: [](chapter_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()` 4377 @*/ 4378 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx) 4379 { 4380 PetscFunctionBegin; 4381 PetscCall(MatScale(A, shift / ts->ijacobian.shift)); 4382 ts->ijacobian.shift = shift; 4383 PetscFunctionReturn(0); 4384 } 4385 4386 /*@ 4387 TSGetEquationType - Gets the type of the equation that `TS` is solving. 4388 4389 Not Collective 4390 4391 Input Parameter: 4392 . ts - the `TS` context 4393 4394 Output Parameter: 4395 . equation_type - see `TSEquationType` 4396 4397 Level: beginner 4398 4399 .seealso: [](chapter_ts), `TS`, `TSSetEquationType()`, `TSEquationType` 4400 @*/ 4401 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type) 4402 { 4403 PetscFunctionBegin; 4404 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4405 PetscValidPointer(equation_type, 2); 4406 *equation_type = ts->equation_type; 4407 PetscFunctionReturn(0); 4408 } 4409 4410 /*@ 4411 TSSetEquationType - Sets the type of the equation that `TS` is solving. 4412 4413 Not Collective 4414 4415 Input Parameters: 4416 + ts - the `TS` context 4417 - equation_type - see `TSEquationType` 4418 4419 Level: advanced 4420 4421 .seealso: [](chapter_ts), `TS`, `TSGetEquationType()`, `TSEquationType` 4422 @*/ 4423 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type) 4424 { 4425 PetscFunctionBegin; 4426 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4427 ts->equation_type = equation_type; 4428 PetscFunctionReturn(0); 4429 } 4430 4431 /*@ 4432 TSGetConvergedReason - Gets the reason the `TS` iteration was stopped. 4433 4434 Not Collective 4435 4436 Input Parameter: 4437 . ts - the `TS` context 4438 4439 Output Parameter: 4440 . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4441 manual pages for the individual convergence tests for complete lists 4442 4443 Level: beginner 4444 4445 Note: 4446 Can only be called after the call to `TSSolve()` is complete. 4447 4448 .seealso: [](chapter_ts), `TS`, `TSSolve()`, `TSSetConvergenceTest()`, `TSConvergedReason` 4449 @*/ 4450 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason) 4451 { 4452 PetscFunctionBegin; 4453 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4454 PetscValidPointer(reason, 2); 4455 *reason = ts->reason; 4456 PetscFunctionReturn(0); 4457 } 4458 4459 /*@ 4460 TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`. 4461 4462 Logically Collective; reason must contain common value 4463 4464 Input Parameters: 4465 + ts - the `TS` context 4466 - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4467 manual pages for the individual convergence tests for complete lists 4468 4469 Level: advanced 4470 4471 Note: 4472 Can only be called while `TSSolve()` is active. 4473 4474 .seealso: [](chapter_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4475 @*/ 4476 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason) 4477 { 4478 PetscFunctionBegin; 4479 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4480 ts->reason = reason; 4481 PetscFunctionReturn(0); 4482 } 4483 4484 /*@ 4485 TSGetSolveTime - Gets the time after a call to `TSSolve()` 4486 4487 Not Collective 4488 4489 Input Parameter: 4490 . ts - the `TS` context 4491 4492 Output Parameter: 4493 . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()` 4494 4495 Level: beginner 4496 4497 Note: 4498 Can only be called after the call to `TSSolve()` is complete. 4499 4500 .seealso: [](chapter_ts), `TS`, `TSSolve()`, `TSSetConvergenceTest()`, `TSConvergedReason` 4501 @*/ 4502 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime) 4503 { 4504 PetscFunctionBegin; 4505 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4506 PetscValidRealPointer(ftime, 2); 4507 *ftime = ts->solvetime; 4508 PetscFunctionReturn(0); 4509 } 4510 4511 /*@ 4512 TSGetSNESIterations - Gets the total number of nonlinear iterations 4513 used by the time integrator. 4514 4515 Not Collective 4516 4517 Input Parameter: 4518 . ts - `TS` context 4519 4520 Output Parameter: 4521 . nits - number of nonlinear iterations 4522 4523 Level: intermediate 4524 4525 Notes: 4526 This counter is reset to zero for each successive call to `TSSolve()`. 4527 4528 .seealso: [](chapter_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()` 4529 @*/ 4530 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits) 4531 { 4532 PetscFunctionBegin; 4533 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4534 PetscValidIntPointer(nits, 2); 4535 *nits = ts->snes_its; 4536 PetscFunctionReturn(0); 4537 } 4538 4539 /*@ 4540 TSGetKSPIterations - Gets the total number of linear iterations 4541 used by the time integrator. 4542 4543 Not Collective 4544 4545 Input Parameter: 4546 . ts - `TS` context 4547 4548 Output Parameter: 4549 . lits - number of linear iterations 4550 4551 Level: intermediate 4552 4553 Note: 4554 This counter is reset to zero for each successive call to `TSSolve()`. 4555 4556 .seealso: [](chapter_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `SNESGetKSPIterations()` 4557 @*/ 4558 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits) 4559 { 4560 PetscFunctionBegin; 4561 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4562 PetscValidIntPointer(lits, 2); 4563 *lits = ts->ksp_its; 4564 PetscFunctionReturn(0); 4565 } 4566 4567 /*@ 4568 TSGetStepRejections - Gets the total number of rejected steps. 4569 4570 Not Collective 4571 4572 Input Parameter: 4573 . ts - `TS` context 4574 4575 Output Parameter: 4576 . rejects - number of steps rejected 4577 4578 Level: intermediate 4579 4580 Note: 4581 This counter is reset to zero for each successive call to `TSSolve()`. 4582 4583 .seealso: [](chapter_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()` 4584 @*/ 4585 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects) 4586 { 4587 PetscFunctionBegin; 4588 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4589 PetscValidIntPointer(rejects, 2); 4590 *rejects = ts->reject; 4591 PetscFunctionReturn(0); 4592 } 4593 4594 /*@ 4595 TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS` 4596 4597 Not Collective 4598 4599 Input Parameter: 4600 . ts - `TS` context 4601 4602 Output Parameter: 4603 . fails - number of failed nonlinear solves 4604 4605 Level: intermediate 4606 4607 Note: 4608 This counter is reset to zero for each successive call to `TSSolve()`. 4609 4610 .seealso: [](chapter_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()` 4611 @*/ 4612 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails) 4613 { 4614 PetscFunctionBegin; 4615 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4616 PetscValidIntPointer(fails, 2); 4617 *fails = ts->num_snes_failures; 4618 PetscFunctionReturn(0); 4619 } 4620 4621 /*@ 4622 TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails 4623 4624 Not Collective 4625 4626 Input Parameters: 4627 + ts - `TS` context 4628 - rejects - maximum number of rejected steps, pass -1 for unlimited 4629 4630 Options Database Key: 4631 . -ts_max_reject - Maximum number of step rejections before a step fails 4632 4633 Level: intermediate 4634 4635 .seealso: [](chapter_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4636 @*/ 4637 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects) 4638 { 4639 PetscFunctionBegin; 4640 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4641 ts->max_reject = rejects; 4642 PetscFunctionReturn(0); 4643 } 4644 4645 /*@ 4646 TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves 4647 4648 Not Collective 4649 4650 Input Parameters: 4651 + ts - `TS` context 4652 - fails - maximum number of failed nonlinear solves, pass -1 for unlimited 4653 4654 Options Database Key: 4655 . -ts_max_snes_failures - Maximum number of nonlinear solve failures 4656 4657 Level: intermediate 4658 4659 .seealso: [](chapter_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()` 4660 @*/ 4661 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails) 4662 { 4663 PetscFunctionBegin; 4664 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4665 ts->max_snes_failures = fails; 4666 PetscFunctionReturn(0); 4667 } 4668 4669 /*@ 4670 TSSetErrorIfStepFails - Immediately error if no step succeeds 4671 4672 Not Collective 4673 4674 Input Parameters: 4675 + ts - `TS` context 4676 - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure 4677 4678 Options Database Key: 4679 . -ts_error_if_step_fails - Error if no step succeeds 4680 4681 Level: intermediate 4682 4683 .seealso: [](chapter_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4684 @*/ 4685 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err) 4686 { 4687 PetscFunctionBegin; 4688 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4689 ts->errorifstepfailed = err; 4690 PetscFunctionReturn(0); 4691 } 4692 4693 /*@ 4694 TSGetAdapt - Get the adaptive controller context for the current method 4695 4696 Collective on ts if controller has not been created yet 4697 4698 Input Parameter: 4699 . ts - time stepping context 4700 4701 Output Parameter: 4702 . adapt - adaptive controller 4703 4704 Level: intermediate 4705 4706 .seealso: [](chapter_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()` 4707 @*/ 4708 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt) 4709 { 4710 PetscFunctionBegin; 4711 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4712 PetscValidPointer(adapt, 2); 4713 if (!ts->adapt) { 4714 PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt)); 4715 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1)); 4716 } 4717 *adapt = ts->adapt; 4718 PetscFunctionReturn(0); 4719 } 4720 4721 /*@ 4722 TSSetTolerances - Set tolerances for local truncation error when using adaptive controller 4723 4724 Logically Collective 4725 4726 Input Parameters: 4727 + ts - time integration context 4728 . atol - scalar absolute tolerances, `PETSC_DECIDE` to leave current value 4729 . vatol - vector of absolute tolerances or NULL, used in preference to atol if present 4730 . rtol - scalar relative tolerances, `PETSC_DECIDE` to leave current value 4731 - vrtol - vector of relative tolerances or NULL, used in preference to atol if present 4732 4733 Options Database keys: 4734 + -ts_rtol <rtol> - relative tolerance for local truncation error 4735 - -ts_atol <atol> - Absolute tolerance for local truncation error 4736 4737 Level: beginner 4738 4739 Notes: 4740 With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error 4741 (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be 4742 computed only for the differential or the algebraic part then this can be done using the vector of 4743 tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the 4744 differential part and infinity for the algebraic part, the LTE calculation will include only the 4745 differential variables. 4746 4747 .seealso: [](chapter_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()` 4748 @*/ 4749 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol) 4750 { 4751 PetscFunctionBegin; 4752 if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol; 4753 if (vatol) { 4754 PetscCall(PetscObjectReference((PetscObject)vatol)); 4755 PetscCall(VecDestroy(&ts->vatol)); 4756 ts->vatol = vatol; 4757 } 4758 if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol; 4759 if (vrtol) { 4760 PetscCall(PetscObjectReference((PetscObject)vrtol)); 4761 PetscCall(VecDestroy(&ts->vrtol)); 4762 ts->vrtol = vrtol; 4763 } 4764 PetscFunctionReturn(0); 4765 } 4766 4767 /*@ 4768 TSGetTolerances - Get tolerances for local truncation error when using adaptive controller 4769 4770 Logically Collective 4771 4772 Input Parameter: 4773 . ts - time integration context 4774 4775 Output Parameters: 4776 + atol - scalar absolute tolerances, NULL to ignore 4777 . vatol - vector of absolute tolerances, NULL to ignore 4778 . rtol - scalar relative tolerances, NULL to ignore 4779 - vrtol - vector of relative tolerances, NULL to ignore 4780 4781 Level: beginner 4782 4783 .seealso: [](chapter_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()` 4784 @*/ 4785 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol) 4786 { 4787 PetscFunctionBegin; 4788 if (atol) *atol = ts->atol; 4789 if (vatol) *vatol = ts->vatol; 4790 if (rtol) *rtol = ts->rtol; 4791 if (vrtol) *vrtol = ts->vrtol; 4792 PetscFunctionReturn(0); 4793 } 4794 4795 /*@ 4796 TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors 4797 4798 Collective on ts 4799 4800 Input Parameters: 4801 + ts - time stepping context 4802 . U - state vector, usually ts->vec_sol 4803 - Y - state vector to be compared to U 4804 4805 Output Parameters: 4806 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 4807 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 4808 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 4809 4810 Level: developer 4811 4812 .seealso: [](chapter_ts), `TS`, `TSErrorWeightedNorm()`, `TSErrorWeightedNormInfinity()` 4813 @*/ 4814 PetscErrorCode TSErrorWeightedNorm2(TS ts, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) 4815 { 4816 PetscInt i, n, N, rstart; 4817 PetscInt n_loc, na_loc, nr_loc; 4818 PetscReal n_glb, na_glb, nr_glb; 4819 const PetscScalar *u, *y; 4820 PetscReal sum, suma, sumr, gsum, gsuma, gsumr, diff; 4821 PetscReal tol, tola, tolr; 4822 PetscReal err_loc[6], err_glb[6]; 4823 4824 PetscFunctionBegin; 4825 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4826 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4827 PetscValidHeaderSpecific(Y, VEC_CLASSID, 3); 4828 PetscValidType(U, 2); 4829 PetscValidType(Y, 3); 4830 PetscCheckSameComm(U, 2, Y, 3); 4831 PetscValidRealPointer(norm, 4); 4832 PetscValidRealPointer(norma, 5); 4833 PetscValidRealPointer(normr, 6); 4834 PetscCheck(U != Y, PetscObjectComm((PetscObject)U), PETSC_ERR_ARG_IDN, "U and Y cannot be the same vector"); 4835 4836 PetscCall(VecGetSize(U, &N)); 4837 PetscCall(VecGetLocalSize(U, &n)); 4838 PetscCall(VecGetOwnershipRange(U, &rstart, NULL)); 4839 PetscCall(VecGetArrayRead(U, &u)); 4840 PetscCall(VecGetArrayRead(Y, &y)); 4841 sum = 0.; 4842 n_loc = 0; 4843 suma = 0.; 4844 na_loc = 0; 4845 sumr = 0.; 4846 nr_loc = 0; 4847 if (ts->vatol && ts->vrtol) { 4848 const PetscScalar *atol, *rtol; 4849 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 4850 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 4851 for (i = 0; i < n; i++) { 4852 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4853 diff = PetscAbsScalar(y[i] - u[i]); 4854 tola = PetscRealPart(atol[i]); 4855 if (tola > 0.) { 4856 suma += PetscSqr(diff / tola); 4857 na_loc++; 4858 } 4859 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4860 if (tolr > 0.) { 4861 sumr += PetscSqr(diff / tolr); 4862 nr_loc++; 4863 } 4864 tol = tola + tolr; 4865 if (tol > 0.) { 4866 sum += PetscSqr(diff / tol); 4867 n_loc++; 4868 } 4869 } 4870 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 4871 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 4872 } else if (ts->vatol) { /* vector atol, scalar rtol */ 4873 const PetscScalar *atol; 4874 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 4875 for (i = 0; i < n; i++) { 4876 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4877 diff = PetscAbsScalar(y[i] - u[i]); 4878 tola = PetscRealPart(atol[i]); 4879 if (tola > 0.) { 4880 suma += PetscSqr(diff / tola); 4881 na_loc++; 4882 } 4883 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4884 if (tolr > 0.) { 4885 sumr += PetscSqr(diff / tolr); 4886 nr_loc++; 4887 } 4888 tol = tola + tolr; 4889 if (tol > 0.) { 4890 sum += PetscSqr(diff / tol); 4891 n_loc++; 4892 } 4893 } 4894 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 4895 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 4896 const PetscScalar *rtol; 4897 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 4898 for (i = 0; i < n; i++) { 4899 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4900 diff = PetscAbsScalar(y[i] - u[i]); 4901 tola = ts->atol; 4902 if (tola > 0.) { 4903 suma += PetscSqr(diff / tola); 4904 na_loc++; 4905 } 4906 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4907 if (tolr > 0.) { 4908 sumr += PetscSqr(diff / tolr); 4909 nr_loc++; 4910 } 4911 tol = tola + tolr; 4912 if (tol > 0.) { 4913 sum += PetscSqr(diff / tol); 4914 n_loc++; 4915 } 4916 } 4917 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 4918 } else { /* scalar atol, scalar rtol */ 4919 for (i = 0; i < n; i++) { 4920 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4921 diff = PetscAbsScalar(y[i] - u[i]); 4922 tola = ts->atol; 4923 if (tola > 0.) { 4924 suma += PetscSqr(diff / tola); 4925 na_loc++; 4926 } 4927 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4928 if (tolr > 0.) { 4929 sumr += PetscSqr(diff / tolr); 4930 nr_loc++; 4931 } 4932 tol = tola + tolr; 4933 if (tol > 0.) { 4934 sum += PetscSqr(diff / tol); 4935 n_loc++; 4936 } 4937 } 4938 } 4939 PetscCall(VecRestoreArrayRead(U, &u)); 4940 PetscCall(VecRestoreArrayRead(Y, &y)); 4941 4942 err_loc[0] = sum; 4943 err_loc[1] = suma; 4944 err_loc[2] = sumr; 4945 err_loc[3] = (PetscReal)n_loc; 4946 err_loc[4] = (PetscReal)na_loc; 4947 err_loc[5] = (PetscReal)nr_loc; 4948 4949 PetscCall(MPIU_Allreduce(err_loc, err_glb, 6, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ts))); 4950 4951 gsum = err_glb[0]; 4952 gsuma = err_glb[1]; 4953 gsumr = err_glb[2]; 4954 n_glb = err_glb[3]; 4955 na_glb = err_glb[4]; 4956 nr_glb = err_glb[5]; 4957 4958 *norm = 0.; 4959 if (n_glb > 0.) *norm = PetscSqrtReal(gsum / n_glb); 4960 *norma = 0.; 4961 if (na_glb > 0.) *norma = PetscSqrtReal(gsuma / na_glb); 4962 *normr = 0.; 4963 if (nr_glb > 0.) *normr = PetscSqrtReal(gsumr / nr_glb); 4964 4965 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 4966 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 4967 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 4968 PetscFunctionReturn(0); 4969 } 4970 4971 /*@ 4972 TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors 4973 4974 Collective on ts 4975 4976 Input Parameters: 4977 + ts - time stepping context 4978 . U - state vector, usually ts->vec_sol 4979 - Y - state vector to be compared to U 4980 4981 Output Parameters: 4982 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 4983 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 4984 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 4985 4986 Level: developer 4987 4988 .seealso: [](chapter_ts), `TS`, `TSErrorWeightedNorm()`, `TSErrorWeightedNorm2()` 4989 @*/ 4990 PetscErrorCode TSErrorWeightedNormInfinity(TS ts, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) 4991 { 4992 PetscInt i, n, N, rstart; 4993 const PetscScalar *u, *y; 4994 PetscReal max, gmax, maxa, gmaxa, maxr, gmaxr; 4995 PetscReal tol, tola, tolr, diff; 4996 PetscReal err_loc[3], err_glb[3]; 4997 4998 PetscFunctionBegin; 4999 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5000 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 5001 PetscValidHeaderSpecific(Y, VEC_CLASSID, 3); 5002 PetscValidType(U, 2); 5003 PetscValidType(Y, 3); 5004 PetscCheckSameComm(U, 2, Y, 3); 5005 PetscValidRealPointer(norm, 4); 5006 PetscValidRealPointer(norma, 5); 5007 PetscValidRealPointer(normr, 6); 5008 PetscCheck(U != Y, PetscObjectComm((PetscObject)U), PETSC_ERR_ARG_IDN, "U and Y cannot be the same vector"); 5009 5010 PetscCall(VecGetSize(U, &N)); 5011 PetscCall(VecGetLocalSize(U, &n)); 5012 PetscCall(VecGetOwnershipRange(U, &rstart, NULL)); 5013 PetscCall(VecGetArrayRead(U, &u)); 5014 PetscCall(VecGetArrayRead(Y, &y)); 5015 5016 max = 0.; 5017 maxa = 0.; 5018 maxr = 0.; 5019 5020 if (ts->vatol && ts->vrtol) { /* vector atol, vector rtol */ 5021 const PetscScalar *atol, *rtol; 5022 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5023 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5024 5025 for (i = 0; i < n; i++) { 5026 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5027 diff = PetscAbsScalar(y[i] - u[i]); 5028 tola = PetscRealPart(atol[i]); 5029 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5030 tol = tola + tolr; 5031 if (tola > 0.) maxa = PetscMax(maxa, diff / tola); 5032 if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr); 5033 if (tol > 0.) max = PetscMax(max, diff / tol); 5034 } 5035 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5036 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5037 } else if (ts->vatol) { /* vector atol, scalar rtol */ 5038 const PetscScalar *atol; 5039 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5040 for (i = 0; i < n; i++) { 5041 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5042 diff = PetscAbsScalar(y[i] - u[i]); 5043 tola = PetscRealPart(atol[i]); 5044 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5045 tol = tola + tolr; 5046 if (tola > 0.) maxa = PetscMax(maxa, diff / tola); 5047 if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr); 5048 if (tol > 0.) max = PetscMax(max, diff / tol); 5049 } 5050 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5051 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 5052 const PetscScalar *rtol; 5053 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5054 5055 for (i = 0; i < n; i++) { 5056 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5057 diff = PetscAbsScalar(y[i] - u[i]); 5058 tola = ts->atol; 5059 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5060 tol = tola + tolr; 5061 if (tola > 0.) maxa = PetscMax(maxa, diff / tola); 5062 if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr); 5063 if (tol > 0.) max = PetscMax(max, diff / tol); 5064 } 5065 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5066 } else { /* scalar atol, scalar rtol */ 5067 5068 for (i = 0; i < n; i++) { 5069 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5070 diff = PetscAbsScalar(y[i] - u[i]); 5071 tola = ts->atol; 5072 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5073 tol = tola + tolr; 5074 if (tola > 0.) maxa = PetscMax(maxa, diff / tola); 5075 if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr); 5076 if (tol > 0.) max = PetscMax(max, diff / tol); 5077 } 5078 } 5079 PetscCall(VecRestoreArrayRead(U, &u)); 5080 PetscCall(VecRestoreArrayRead(Y, &y)); 5081 err_loc[0] = max; 5082 err_loc[1] = maxa; 5083 err_loc[2] = maxr; 5084 PetscCall(MPIU_Allreduce(err_loc, err_glb, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)ts))); 5085 gmax = err_glb[0]; 5086 gmaxa = err_glb[1]; 5087 gmaxr = err_glb[2]; 5088 5089 *norm = gmax; 5090 *norma = gmaxa; 5091 *normr = gmaxr; 5092 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5093 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5094 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5095 PetscFunctionReturn(0); 5096 } 5097 5098 /*@ 5099 TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances 5100 5101 Collective on ts 5102 5103 Input Parameters: 5104 + ts - time stepping context 5105 . U - state vector, usually ts->vec_sol 5106 . Y - state vector to be compared to U 5107 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5108 5109 Output Parameters: 5110 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5111 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5112 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5113 5114 Options Database Key: 5115 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5116 5117 Level: developer 5118 5119 .seealso: [](chapter_ts), `TS`, `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()`, `TSErrorWeightedENorm` 5120 @*/ 5121 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5122 { 5123 PetscFunctionBegin; 5124 if (wnormtype == NORM_2) PetscCall(TSErrorWeightedNorm2(ts, U, Y, norm, norma, normr)); 5125 else if (wnormtype == NORM_INFINITY) PetscCall(TSErrorWeightedNormInfinity(ts, U, Y, norm, norma, normr)); 5126 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 5127 PetscFunctionReturn(0); 5128 } 5129 5130 /*@ 5131 TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances 5132 5133 Collective on ts 5134 5135 Input Parameters: 5136 + ts - time stepping context 5137 . E - error vector 5138 . U - state vector, usually ts->vec_sol 5139 - Y - state vector, previous time step 5140 5141 Output Parameters: 5142 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 5143 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 5144 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 5145 5146 Level: developer 5147 5148 .seealso: [](chapter_ts), `TS`, `TSErrorWeightedENorm()`, `TSErrorWeightedENormInfinity()` 5149 @*/ 5150 PetscErrorCode TSErrorWeightedENorm2(TS ts, Vec E, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5151 { 5152 PetscInt i, n, N, rstart; 5153 PetscInt n_loc, na_loc, nr_loc; 5154 PetscReal n_glb, na_glb, nr_glb; 5155 const PetscScalar *e, *u, *y; 5156 PetscReal err, sum, suma, sumr, gsum, gsuma, gsumr; 5157 PetscReal tol, tola, tolr; 5158 PetscReal err_loc[6], err_glb[6]; 5159 5160 PetscFunctionBegin; 5161 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5162 PetscValidHeaderSpecific(E, VEC_CLASSID, 2); 5163 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 5164 PetscValidHeaderSpecific(Y, VEC_CLASSID, 4); 5165 PetscValidType(E, 2); 5166 PetscValidType(U, 3); 5167 PetscValidType(Y, 4); 5168 PetscCheckSameComm(E, 2, U, 3); 5169 PetscCheckSameComm(U, 3, Y, 4); 5170 PetscValidRealPointer(norm, 5); 5171 PetscValidRealPointer(norma, 6); 5172 PetscValidRealPointer(normr, 7); 5173 5174 PetscCall(VecGetSize(E, &N)); 5175 PetscCall(VecGetLocalSize(E, &n)); 5176 PetscCall(VecGetOwnershipRange(E, &rstart, NULL)); 5177 PetscCall(VecGetArrayRead(E, &e)); 5178 PetscCall(VecGetArrayRead(U, &u)); 5179 PetscCall(VecGetArrayRead(Y, &y)); 5180 sum = 0.; 5181 n_loc = 0; 5182 suma = 0.; 5183 na_loc = 0; 5184 sumr = 0.; 5185 nr_loc = 0; 5186 if (ts->vatol && ts->vrtol) { 5187 const PetscScalar *atol, *rtol; 5188 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5189 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5190 for (i = 0; i < n; i++) { 5191 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5192 err = PetscAbsScalar(e[i]); 5193 tola = PetscRealPart(atol[i]); 5194 if (tola > 0.) { 5195 suma += PetscSqr(err / tola); 5196 na_loc++; 5197 } 5198 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5199 if (tolr > 0.) { 5200 sumr += PetscSqr(err / tolr); 5201 nr_loc++; 5202 } 5203 tol = tola + tolr; 5204 if (tol > 0.) { 5205 sum += PetscSqr(err / tol); 5206 n_loc++; 5207 } 5208 } 5209 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5210 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5211 } else if (ts->vatol) { /* vector atol, scalar rtol */ 5212 const PetscScalar *atol; 5213 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5214 for (i = 0; i < n; i++) { 5215 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5216 err = PetscAbsScalar(e[i]); 5217 tola = PetscRealPart(atol[i]); 5218 if (tola > 0.) { 5219 suma += PetscSqr(err / tola); 5220 na_loc++; 5221 } 5222 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5223 if (tolr > 0.) { 5224 sumr += PetscSqr(err / tolr); 5225 nr_loc++; 5226 } 5227 tol = tola + tolr; 5228 if (tol > 0.) { 5229 sum += PetscSqr(err / tol); 5230 n_loc++; 5231 } 5232 } 5233 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5234 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 5235 const PetscScalar *rtol; 5236 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5237 for (i = 0; i < n; i++) { 5238 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5239 err = PetscAbsScalar(e[i]); 5240 tola = ts->atol; 5241 if (tola > 0.) { 5242 suma += PetscSqr(err / tola); 5243 na_loc++; 5244 } 5245 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5246 if (tolr > 0.) { 5247 sumr += PetscSqr(err / tolr); 5248 nr_loc++; 5249 } 5250 tol = tola + tolr; 5251 if (tol > 0.) { 5252 sum += PetscSqr(err / tol); 5253 n_loc++; 5254 } 5255 } 5256 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5257 } else { /* scalar atol, scalar rtol */ 5258 for (i = 0; i < n; i++) { 5259 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5260 err = PetscAbsScalar(e[i]); 5261 tola = ts->atol; 5262 if (tola > 0.) { 5263 suma += PetscSqr(err / tola); 5264 na_loc++; 5265 } 5266 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5267 if (tolr > 0.) { 5268 sumr += PetscSqr(err / tolr); 5269 nr_loc++; 5270 } 5271 tol = tola + tolr; 5272 if (tol > 0.) { 5273 sum += PetscSqr(err / tol); 5274 n_loc++; 5275 } 5276 } 5277 } 5278 PetscCall(VecRestoreArrayRead(E, &e)); 5279 PetscCall(VecRestoreArrayRead(U, &u)); 5280 PetscCall(VecRestoreArrayRead(Y, &y)); 5281 5282 err_loc[0] = sum; 5283 err_loc[1] = suma; 5284 err_loc[2] = sumr; 5285 err_loc[3] = (PetscReal)n_loc; 5286 err_loc[4] = (PetscReal)na_loc; 5287 err_loc[5] = (PetscReal)nr_loc; 5288 5289 PetscCall(MPIU_Allreduce(err_loc, err_glb, 6, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ts))); 5290 5291 gsum = err_glb[0]; 5292 gsuma = err_glb[1]; 5293 gsumr = err_glb[2]; 5294 n_glb = err_glb[3]; 5295 na_glb = err_glb[4]; 5296 nr_glb = err_glb[5]; 5297 5298 *norm = 0.; 5299 if (n_glb > 0.) *norm = PetscSqrtReal(gsum / n_glb); 5300 *norma = 0.; 5301 if (na_glb > 0.) *norma = PetscSqrtReal(gsuma / na_glb); 5302 *normr = 0.; 5303 if (nr_glb > 0.) *normr = PetscSqrtReal(gsumr / nr_glb); 5304 5305 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5306 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5307 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5308 PetscFunctionReturn(0); 5309 } 5310 5311 /*@ 5312 TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances 5313 5314 Collective on ts 5315 5316 Input Parameters: 5317 + ts - time stepping context 5318 . E - error vector 5319 . U - state vector, usually ts->vec_sol 5320 - Y - state vector, previous time step 5321 5322 Output Parameters: 5323 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 5324 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 5325 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 5326 5327 Level: developer 5328 5329 .seealso: [](chapter_ts), `TS`, `TSErrorWeightedENorm()`, `TSErrorWeightedENorm2()` 5330 @*/ 5331 PetscErrorCode TSErrorWeightedENormInfinity(TS ts, Vec E, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5332 { 5333 PetscInt i, n, N, rstart; 5334 const PetscScalar *e, *u, *y; 5335 PetscReal err, max, gmax, maxa, gmaxa, maxr, gmaxr; 5336 PetscReal tol, tola, tolr; 5337 PetscReal err_loc[3], err_glb[3]; 5338 5339 PetscFunctionBegin; 5340 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5341 PetscValidHeaderSpecific(E, VEC_CLASSID, 2); 5342 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 5343 PetscValidHeaderSpecific(Y, VEC_CLASSID, 4); 5344 PetscValidType(E, 2); 5345 PetscValidType(U, 3); 5346 PetscValidType(Y, 4); 5347 PetscCheckSameComm(E, 2, U, 3); 5348 PetscCheckSameComm(U, 3, Y, 4); 5349 PetscValidRealPointer(norm, 5); 5350 PetscValidRealPointer(norma, 6); 5351 PetscValidRealPointer(normr, 7); 5352 5353 PetscCall(VecGetSize(E, &N)); 5354 PetscCall(VecGetLocalSize(E, &n)); 5355 PetscCall(VecGetOwnershipRange(E, &rstart, NULL)); 5356 PetscCall(VecGetArrayRead(E, &e)); 5357 PetscCall(VecGetArrayRead(U, &u)); 5358 PetscCall(VecGetArrayRead(Y, &y)); 5359 5360 max = 0.; 5361 maxa = 0.; 5362 maxr = 0.; 5363 5364 if (ts->vatol && ts->vrtol) { /* vector atol, vector rtol */ 5365 const PetscScalar *atol, *rtol; 5366 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5367 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5368 5369 for (i = 0; i < n; i++) { 5370 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5371 err = PetscAbsScalar(e[i]); 5372 tola = PetscRealPart(atol[i]); 5373 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5374 tol = tola + tolr; 5375 if (tola > 0.) maxa = PetscMax(maxa, err / tola); 5376 if (tolr > 0.) maxr = PetscMax(maxr, err / tolr); 5377 if (tol > 0.) max = PetscMax(max, err / tol); 5378 } 5379 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5380 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5381 } else if (ts->vatol) { /* vector atol, scalar rtol */ 5382 const PetscScalar *atol; 5383 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5384 for (i = 0; i < n; i++) { 5385 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5386 err = PetscAbsScalar(e[i]); 5387 tola = PetscRealPart(atol[i]); 5388 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5389 tol = tola + tolr; 5390 if (tola > 0.) maxa = PetscMax(maxa, err / tola); 5391 if (tolr > 0.) maxr = PetscMax(maxr, err / tolr); 5392 if (tol > 0.) max = PetscMax(max, err / tol); 5393 } 5394 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5395 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 5396 const PetscScalar *rtol; 5397 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5398 5399 for (i = 0; i < n; i++) { 5400 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5401 err = PetscAbsScalar(e[i]); 5402 tola = ts->atol; 5403 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5404 tol = tola + tolr; 5405 if (tola > 0.) maxa = PetscMax(maxa, err / tola); 5406 if (tolr > 0.) maxr = PetscMax(maxr, err / tolr); 5407 if (tol > 0.) max = PetscMax(max, err / tol); 5408 } 5409 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5410 } else { /* scalar atol, scalar rtol */ 5411 5412 for (i = 0; i < n; i++) { 5413 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5414 err = PetscAbsScalar(e[i]); 5415 tola = ts->atol; 5416 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5417 tol = tola + tolr; 5418 if (tola > 0.) maxa = PetscMax(maxa, err / tola); 5419 if (tolr > 0.) maxr = PetscMax(maxr, err / tolr); 5420 if (tol > 0.) max = PetscMax(max, err / tol); 5421 } 5422 } 5423 PetscCall(VecRestoreArrayRead(E, &e)); 5424 PetscCall(VecRestoreArrayRead(U, &u)); 5425 PetscCall(VecRestoreArrayRead(Y, &y)); 5426 err_loc[0] = max; 5427 err_loc[1] = maxa; 5428 err_loc[2] = maxr; 5429 PetscCall(MPIU_Allreduce(err_loc, err_glb, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)ts))); 5430 gmax = err_glb[0]; 5431 gmaxa = err_glb[1]; 5432 gmaxr = err_glb[2]; 5433 5434 *norm = gmax; 5435 *norma = gmaxa; 5436 *normr = gmaxr; 5437 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5438 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5439 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5440 PetscFunctionReturn(0); 5441 } 5442 5443 /*@ 5444 TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances 5445 5446 Collective on ts 5447 5448 Input Parameters: 5449 + ts - time stepping context 5450 . E - error vector 5451 . U - state vector, usually ts->vec_sol 5452 . Y - state vector, previous time step 5453 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5454 5455 Output Parameters: 5456 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5457 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5458 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5459 5460 Options Database Key: 5461 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5462 5463 Level: developer 5464 5465 .seealso: [](chapter_ts), `TS`, `TSErrorWeightedENormInfinity()`, `TSErrorWeightedENorm2()`, `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()` 5466 @*/ 5467 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5468 { 5469 PetscFunctionBegin; 5470 if (wnormtype == NORM_2) PetscCall(TSErrorWeightedENorm2(ts, E, U, Y, norm, norma, normr)); 5471 else if (wnormtype == NORM_INFINITY) PetscCall(TSErrorWeightedENormInfinity(ts, E, U, Y, norm, norma, normr)); 5472 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 5473 PetscFunctionReturn(0); 5474 } 5475 5476 /*@ 5477 TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler 5478 5479 Logically Collective on ts 5480 5481 Input Parameters: 5482 + ts - time stepping context 5483 - cfltime - maximum stable time step if using forward Euler (value can be different on each process) 5484 5485 Note: 5486 After calling this function, the global CFL time can be obtained by calling TSGetCFLTime() 5487 5488 Level: intermediate 5489 5490 .seealso: [](chapter_ts), `TSGetCFLTime()`, `TSADAPTCFL` 5491 @*/ 5492 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime) 5493 { 5494 PetscFunctionBegin; 5495 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5496 ts->cfltime_local = cfltime; 5497 ts->cfltime = -1.; 5498 PetscFunctionReturn(0); 5499 } 5500 5501 /*@ 5502 TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler 5503 5504 Collective on ts 5505 5506 Input Parameter: 5507 . ts - time stepping context 5508 5509 Output Parameter: 5510 . cfltime - maximum stable time step for forward Euler 5511 5512 Level: advanced 5513 5514 .seealso: [](chapter_ts), `TSSetCFLTimeLocal()` 5515 @*/ 5516 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime) 5517 { 5518 PetscFunctionBegin; 5519 if (ts->cfltime < 0) PetscCall(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts))); 5520 *cfltime = ts->cfltime; 5521 PetscFunctionReturn(0); 5522 } 5523 5524 /*@ 5525 TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu 5526 5527 Input Parameters: 5528 + ts - the `TS` context. 5529 . xl - lower bound. 5530 - xu - upper bound. 5531 5532 Level: advanced 5533 5534 Note: 5535 If this routine is not called then the lower and upper bounds are set to 5536 `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`. 5537 5538 .seealso: [](chapter_ts), `TS` 5539 @*/ 5540 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) 5541 { 5542 SNES snes; 5543 5544 PetscFunctionBegin; 5545 PetscCall(TSGetSNES(ts, &snes)); 5546 PetscCall(SNESVISetVariableBounds(snes, xl, xu)); 5547 PetscFunctionReturn(0); 5548 } 5549 5550 /*@ 5551 TSComputeLinearStability - computes the linear stability function at a point 5552 5553 Collective on ts 5554 5555 Input Parameters: 5556 + ts - the `TS` context 5557 - xr,xi - real and imaginary part of input arguments 5558 5559 Output Parameters: 5560 . yr,yi - real and imaginary part of function value 5561 5562 Level: developer 5563 5564 .seealso: [](chapter_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()` 5565 @*/ 5566 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) 5567 { 5568 PetscFunctionBegin; 5569 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5570 PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi); 5571 PetscFunctionReturn(0); 5572 } 5573 5574 /*@ 5575 TSRestartStep - Flags the solver to restart the next step 5576 5577 Collective on ts 5578 5579 Input Parameter: 5580 . ts - the `TS` context obtained from `TSCreate()` 5581 5582 Level: advanced 5583 5584 Notes: 5585 Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of 5586 discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution 5587 vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For 5588 the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce 5589 discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with 5590 discontinuous source terms). 5591 5592 .seealso: [](chapter_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()` 5593 @*/ 5594 PetscErrorCode TSRestartStep(TS ts) 5595 { 5596 PetscFunctionBegin; 5597 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5598 ts->steprestart = PETSC_TRUE; 5599 PetscFunctionReturn(0); 5600 } 5601 5602 /*@ 5603 TSRollBack - Rolls back one time step 5604 5605 Collective on ts 5606 5607 Input Parameter: 5608 . ts - the `TS` context obtained from `TSCreate()` 5609 5610 Level: advanced 5611 5612 .seealso: [](chapter_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()` 5613 @*/ 5614 PetscErrorCode TSRollBack(TS ts) 5615 { 5616 PetscFunctionBegin; 5617 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5618 PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called"); 5619 PetscUseTypeMethod(ts, rollback); 5620 ts->time_step = ts->ptime - ts->ptime_prev; 5621 ts->ptime = ts->ptime_prev; 5622 ts->ptime_prev = ts->ptime_prev_rollback; 5623 ts->steps--; 5624 ts->steprollback = PETSC_TRUE; 5625 PetscFunctionReturn(0); 5626 } 5627 5628 /*@ 5629 TSGetStages - Get the number of stages and stage values 5630 5631 Input Parameter: 5632 . ts - the `TS` context obtained from `TSCreate()` 5633 5634 Output Parameters: 5635 + ns - the number of stages 5636 - Y - the current stage vectors 5637 5638 Level: advanced 5639 5640 Note: 5641 Both ns and Y can be NULL. 5642 5643 .seealso: [](chapter_ts), `TS`, `TSCreate()` 5644 @*/ 5645 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y) 5646 { 5647 PetscFunctionBegin; 5648 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5649 if (ns) PetscValidIntPointer(ns, 2); 5650 if (Y) PetscValidPointer(Y, 3); 5651 if (!ts->ops->getstages) { 5652 if (ns) *ns = 0; 5653 if (Y) *Y = NULL; 5654 } else PetscUseTypeMethod(ts, getstages, ns, Y); 5655 PetscFunctionReturn(0); 5656 } 5657 5658 /*@C 5659 TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity. 5660 5661 Collective on ts 5662 5663 Input Parameters: 5664 + ts - the `TS` context 5665 . t - current timestep 5666 . U - state vector 5667 . Udot - time derivative of state vector 5668 . shift - shift to apply, see note below 5669 - ctx - an optional user context 5670 5671 Output Parameters: 5672 + J - Jacobian matrix (not altered in this routine) 5673 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J) 5674 5675 Level: intermediate 5676 5677 Notes: 5678 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 5679 5680 dF/dU + shift*dF/dUdot 5681 5682 Most users should not need to explicitly call this routine, as it 5683 is used internally within the nonlinear solvers. 5684 5685 This will first try to get the coloring from the `DM`. If the `DM` type has no coloring 5686 routine, then it will try to get the coloring from the matrix. This requires that the 5687 matrix have nonzero entries precomputed. 5688 5689 .seealso: [](chapter_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5690 @*/ 5691 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx) 5692 { 5693 SNES snes; 5694 MatFDColoring color; 5695 PetscBool hascolor, matcolor = PETSC_FALSE; 5696 5697 PetscFunctionBegin; 5698 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL)); 5699 PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color)); 5700 if (!color) { 5701 DM dm; 5702 ISColoring iscoloring; 5703 5704 PetscCall(TSGetDM(ts, &dm)); 5705 PetscCall(DMHasColoring(dm, &hascolor)); 5706 if (hascolor && !matcolor) { 5707 PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 5708 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5709 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5710 PetscCall(MatFDColoringSetFromOptions(color)); 5711 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5712 PetscCall(ISColoringDestroy(&iscoloring)); 5713 } else { 5714 MatColoring mc; 5715 5716 PetscCall(MatColoringCreate(B, &mc)); 5717 PetscCall(MatColoringSetDistance(mc, 2)); 5718 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5719 PetscCall(MatColoringSetFromOptions(mc)); 5720 PetscCall(MatColoringApply(mc, &iscoloring)); 5721 PetscCall(MatColoringDestroy(&mc)); 5722 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5723 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5724 PetscCall(MatFDColoringSetFromOptions(color)); 5725 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5726 PetscCall(ISColoringDestroy(&iscoloring)); 5727 } 5728 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color)); 5729 PetscCall(PetscObjectDereference((PetscObject)color)); 5730 } 5731 PetscCall(TSGetSNES(ts, &snes)); 5732 PetscCall(MatFDColoringApply(B, color, U, snes)); 5733 if (J != B) { 5734 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 5735 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 5736 } 5737 PetscFunctionReturn(0); 5738 } 5739 5740 /*@ 5741 TSSetFunctionDomainError - Set a function that tests if the current state vector is valid 5742 5743 Input Parameters: 5744 + ts - the `TS` context 5745 - func - function called within `TSFunctionDomainError()` 5746 5747 Calling sequence of func: 5748 $ PetscErrorCode func(TS ts,PetscReal time,Vec state,PetscBool reject) 5749 5750 + ts - the TS context 5751 . time - the current time (of the stage) 5752 . state - the state to check if it is valid 5753 - reject - (output parameter) PETSC_FALSE if the state is acceptable, PETSC_TRUE if not acceptable 5754 5755 Level: intermediate 5756 5757 Notes: 5758 If an implicit ODE solver is being used then, in addition to providing this routine, the 5759 user's code should call `SNESSetFunctionDomainError()` when domain errors occur during 5760 function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`. 5761 Use `TSGetSNES()` to obtain the `SNES` object 5762 5763 Developer Note: 5764 The naming of this function is inconsistent with the `SNESSetFunctionDomainError()` 5765 since one takes a function pointer and the other does not. 5766 5767 .seealso: [](chapter_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()` 5768 @*/ 5769 5770 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS, PetscReal, Vec, PetscBool *)) 5771 { 5772 PetscFunctionBegin; 5773 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5774 ts->functiondomainerror = func; 5775 PetscFunctionReturn(0); 5776 } 5777 5778 /*@ 5779 TSFunctionDomainError - Checks if the current state is valid 5780 5781 Input Parameters: 5782 + ts - the `TS` context 5783 . stagetime - time of the simulation 5784 - Y - state vector to check. 5785 5786 Output Parameter: 5787 . accept - Set to `PETSC_FALSE` if the current state vector is valid. 5788 5789 Level: developer 5790 5791 Note: 5792 This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`) 5793 to check if the current state is valid. 5794 5795 .seealso: [](chapter_ts), `TS`, `TSSetFunctionDomainError()` 5796 @*/ 5797 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept) 5798 { 5799 PetscFunctionBegin; 5800 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5801 *accept = PETSC_TRUE; 5802 if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept)); 5803 PetscFunctionReturn(0); 5804 } 5805 5806 /*@C 5807 TSClone - This function clones a time step object. 5808 5809 Collective 5810 5811 Input Parameter: 5812 . tsin - The input `TS` 5813 5814 Output Parameter: 5815 . tsout - The output `TS` (cloned) 5816 5817 Level: developer 5818 5819 Notes: 5820 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. 5821 It will likely be replaced in the future with a mechanism of switching methods on the fly. 5822 5823 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); 5824 5825 .seealso: [](chapter_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()` 5826 @*/ 5827 PetscErrorCode TSClone(TS tsin, TS *tsout) 5828 { 5829 TS t; 5830 SNES snes_start; 5831 DM dm; 5832 TSType type; 5833 5834 PetscFunctionBegin; 5835 PetscValidPointer(tsin, 1); 5836 *tsout = NULL; 5837 5838 PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView)); 5839 5840 /* General TS description */ 5841 t->numbermonitors = 0; 5842 t->monitorFrequency = 1; 5843 t->setupcalled = 0; 5844 t->ksp_its = 0; 5845 t->snes_its = 0; 5846 t->nwork = 0; 5847 t->rhsjacobian.time = PETSC_MIN_REAL; 5848 t->rhsjacobian.scale = 1.; 5849 t->ijacobian.shift = 1.; 5850 5851 PetscCall(TSGetSNES(tsin, &snes_start)); 5852 PetscCall(TSSetSNES(t, snes_start)); 5853 5854 PetscCall(TSGetDM(tsin, &dm)); 5855 PetscCall(TSSetDM(t, dm)); 5856 5857 t->adapt = tsin->adapt; 5858 PetscCall(PetscObjectReference((PetscObject)t->adapt)); 5859 5860 t->trajectory = tsin->trajectory; 5861 PetscCall(PetscObjectReference((PetscObject)t->trajectory)); 5862 5863 t->event = tsin->event; 5864 if (t->event) t->event->refct++; 5865 5866 t->problem_type = tsin->problem_type; 5867 t->ptime = tsin->ptime; 5868 t->ptime_prev = tsin->ptime_prev; 5869 t->time_step = tsin->time_step; 5870 t->max_time = tsin->max_time; 5871 t->steps = tsin->steps; 5872 t->max_steps = tsin->max_steps; 5873 t->equation_type = tsin->equation_type; 5874 t->atol = tsin->atol; 5875 t->rtol = tsin->rtol; 5876 t->max_snes_failures = tsin->max_snes_failures; 5877 t->max_reject = tsin->max_reject; 5878 t->errorifstepfailed = tsin->errorifstepfailed; 5879 5880 PetscCall(TSGetType(tsin, &type)); 5881 PetscCall(TSSetType(t, type)); 5882 5883 t->vec_sol = NULL; 5884 5885 t->cfltime = tsin->cfltime; 5886 t->cfltime_local = tsin->cfltime_local; 5887 t->exact_final_time = tsin->exact_final_time; 5888 5889 PetscCall(PetscMemcpy(t->ops, tsin->ops, sizeof(struct _TSOps))); 5890 5891 if (((PetscObject)tsin)->fortran_func_pointers) { 5892 PetscInt i; 5893 PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers)); 5894 for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i]; 5895 } 5896 *tsout = t; 5897 PetscFunctionReturn(0); 5898 } 5899 5900 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y) 5901 { 5902 TS ts = (TS)ctx; 5903 5904 PetscFunctionBegin; 5905 PetscCall(TSComputeRHSFunction(ts, 0, x, y)); 5906 PetscFunctionReturn(0); 5907 } 5908 5909 /*@ 5910 TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5911 5912 Logically Collective on ts 5913 5914 Input Parameters: 5915 TS - the time stepping routine 5916 5917 Output Parameter: 5918 . flg - `PETSC_TRUE` if the multiply is likely correct 5919 5920 Options Database Key: 5921 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator 5922 5923 Level: advanced 5924 5925 Note: 5926 This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian 5927 5928 .seealso: [](chapter_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()` 5929 @*/ 5930 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg) 5931 { 5932 Mat J, B; 5933 TSRHSJacobian func; 5934 void *ctx; 5935 5936 PetscFunctionBegin; 5937 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5938 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5939 PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5940 PetscFunctionReturn(0); 5941 } 5942 5943 /*@C 5944 TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5945 5946 Logically Collective on ts 5947 5948 Input Parameters: 5949 TS - the time stepping routine 5950 5951 Output Parameter: 5952 . flg - `PETSC_TRUE` if the multiply is likely correct 5953 5954 Options Database Key: 5955 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator 5956 5957 Level: advanced 5958 5959 Notes: 5960 This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian 5961 5962 .seealso: [](chapter_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()` 5963 @*/ 5964 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg) 5965 { 5966 Mat J, B; 5967 void *ctx; 5968 TSRHSJacobian func; 5969 5970 PetscFunctionBegin; 5971 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5972 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5973 PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5974 PetscFunctionReturn(0); 5975 } 5976 5977 /*@ 5978 TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used. 5979 5980 Logically collective 5981 5982 Input Parameters: 5983 + ts - timestepping context 5984 - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5985 5986 Options Database Key: 5987 . -ts_use_splitrhsfunction - <true,false> 5988 5989 Level: intermediate 5990 5991 Note: 5992 This is only useful for multirate methods 5993 5994 .seealso: [](chapter_ts), `TS`, `TSGetUseSplitRHSFunction()` 5995 @*/ 5996 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) 5997 { 5998 PetscFunctionBegin; 5999 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6000 ts->use_splitrhsfunction = use_splitrhsfunction; 6001 PetscFunctionReturn(0); 6002 } 6003 6004 /*@ 6005 TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used. 6006 6007 Not collective 6008 6009 Input Parameter: 6010 . ts - timestepping context 6011 6012 Output Parameter: 6013 . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 6014 6015 Level: intermediate 6016 6017 .seealso: [](chapter_ts), `TS`, `TSSetUseSplitRHSFunction()` 6018 @*/ 6019 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) 6020 { 6021 PetscFunctionBegin; 6022 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6023 *use_splitrhsfunction = ts->use_splitrhsfunction; 6024 PetscFunctionReturn(0); 6025 } 6026 6027 /*@ 6028 TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix. 6029 6030 Logically Collective on ts 6031 6032 Input Parameters: 6033 + ts - the time-stepper 6034 - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`) 6035 6036 Level: intermediate 6037 6038 Note: 6039 When the relationship between the nonzero structures is known and supplied the solution process can be much faster 6040 6041 .seealso: [](chapter_ts), `TS`, `MatAXPY()`, `MatStructure` 6042 @*/ 6043 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str) 6044 { 6045 PetscFunctionBegin; 6046 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6047 ts->axpy_pattern = str; 6048 PetscFunctionReturn(0); 6049 } 6050 6051 /*@ 6052 TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span 6053 6054 Collective on ts 6055 6056 Input Parameters: 6057 + ts - the time-stepper 6058 . n - number of the time points (>=2) 6059 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 6060 6061 Options Database Key: 6062 . -ts_time_span <t0,...tf> - Sets the time span 6063 6064 Level: intermediate 6065 6066 Notes: 6067 The elements in tspan must be all increasing. They correspond to the intermediate points for time integration. 6068 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 6069 The intermediate solutions are saved in a vector array that can be accessed with `TSGetTimeSpanSolutions()`. Thus using time span may 6070 pressure the memory system when using a large number of span points. 6071 6072 .seealso: [](chapter_ts), `TS`, `TSGetTimeSpan()`, `TSGetTimeSpanSolutions()` 6073 @*/ 6074 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times) 6075 { 6076 PetscFunctionBegin; 6077 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6078 PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n); 6079 if (ts->tspan && n != ts->tspan->num_span_times) { 6080 PetscCall(PetscFree(ts->tspan->span_times)); 6081 PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol)); 6082 PetscCall(PetscMalloc1(n, &ts->tspan->span_times)); 6083 } 6084 if (!ts->tspan) { 6085 TSTimeSpan tspan; 6086 PetscCall(PetscNew(&tspan)); 6087 PetscCall(PetscMalloc1(n, &tspan->span_times)); 6088 tspan->reltol = 1e-6; 6089 tspan->abstol = 10 * PETSC_MACHINE_EPSILON; 6090 ts->tspan = tspan; 6091 } 6092 ts->tspan->num_span_times = n; 6093 PetscCall(PetscArraycpy(ts->tspan->span_times, span_times, n)); 6094 PetscCall(TSSetTime(ts, ts->tspan->span_times[0])); 6095 PetscCall(TSSetMaxTime(ts, ts->tspan->span_times[n - 1])); 6096 PetscFunctionReturn(0); 6097 } 6098 6099 /*@C 6100 TSGetTimeSpan - gets the time span. 6101 6102 Not Collective 6103 6104 Input Parameter: 6105 . ts - the time-stepper 6106 6107 Output Parameters: 6108 + n - number of the time points (>=2) 6109 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 6110 The values are valid until the `TS` object is destroyed. 6111 6112 Level: beginner 6113 6114 Note: 6115 Both n and span_times can be NULL. 6116 6117 .seealso: [](chapter_ts), `TS`, `TSSetTimeSpan()`, `TSGetTimeSpanSolutions()` 6118 @*/ 6119 PetscErrorCode TSGetTimeSpan(TS ts, PetscInt *n, const PetscReal **span_times) 6120 { 6121 PetscFunctionBegin; 6122 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6123 if (n) PetscValidIntPointer(n, 2); 6124 if (span_times) PetscValidPointer(span_times, 3); 6125 if (!ts->tspan) { 6126 if (n) *n = 0; 6127 if (span_times) *span_times = NULL; 6128 } else { 6129 if (n) *n = ts->tspan->num_span_times; 6130 if (span_times) *span_times = ts->tspan->span_times; 6131 } 6132 PetscFunctionReturn(0); 6133 } 6134 6135 /*@ 6136 TSGetTimeSpanSolutions - Get the number of solutions and the solutions at the time points specified by the time span. 6137 6138 Input Parameter: 6139 . ts - the `TS` context obtained from `TSCreate()` 6140 6141 Output Parameters: 6142 + nsol - the number of solutions 6143 - Sols - the solution vectors 6144 6145 Level: intermediate 6146 6147 Notes: 6148 Both nsol and Sols can be NULL. 6149 6150 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()`. 6151 For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain points in the span. 6152 6153 .seealso: [](chapter_ts), `TS`, `TSSetTimeSpan()` 6154 @*/ 6155 PetscErrorCode TSGetTimeSpanSolutions(TS ts, PetscInt *nsol, Vec **Sols) 6156 { 6157 PetscFunctionBegin; 6158 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6159 if (nsol) PetscValidIntPointer(nsol, 2); 6160 if (Sols) PetscValidPointer(Sols, 3); 6161 if (!ts->tspan) { 6162 if (nsol) *nsol = 0; 6163 if (Sols) *Sols = NULL; 6164 } else { 6165 if (nsol) *nsol = ts->tspan->spanctr; 6166 if (Sols) *Sols = ts->tspan->vecs_sol; 6167 } 6168 PetscFunctionReturn(0); 6169 } 6170 6171 /*@C 6172 TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information. 6173 6174 Collective on TS 6175 6176 Input Parameters: 6177 + ts - the TS context 6178 . J - Jacobian matrix (not altered in this routine) 6179 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J) 6180 6181 Level: intermediate 6182 6183 Notes: 6184 This function improves the `MatMFFD` coloring performance when the Jacobian matrix is overallocated or contains 6185 many constant zeros entries, which is typically the case when the matrix is generated by a DM 6186 and multiple fields are involved. 6187 6188 Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity 6189 structure. For `MatMFFD` coloring, the values of nonzero entries are not important. So one can 6190 usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian. 6191 `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`. 6192 6193 .seealso: `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 6194 @*/ 6195 PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B) 6196 { 6197 MatColoring mc = NULL; 6198 ISColoring iscoloring = NULL; 6199 MatFDColoring matfdcoloring = NULL; 6200 6201 PetscFunctionBegin; 6202 /* Generate new coloring after eliminating zeros in the matrix */ 6203 PetscCall(MatEliminateZeros(B)); 6204 PetscCall(MatColoringCreate(B, &mc)); 6205 PetscCall(MatColoringSetDistance(mc, 2)); 6206 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 6207 PetscCall(MatColoringSetFromOptions(mc)); 6208 PetscCall(MatColoringApply(mc, &iscoloring)); 6209 PetscCall(MatColoringDestroy(&mc)); 6210 /* Replace the old coloring with the new one */ 6211 PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring)); 6212 PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 6213 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 6214 PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring)); 6215 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring)); 6216 PetscCall(PetscObjectDereference((PetscObject)matfdcoloring)); 6217 PetscCall(ISColoringDestroy(&iscoloring)); 6218 PetscFunctionReturn(0); 6219 } 6220