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