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