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(PetscLogObjectParent((PetscObject)ts, (PetscObject)ts->snes)); 2704 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1)); 2705 if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm)); 2706 if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY)); 2707 } 2708 *snes = ts->snes; 2709 PetscFunctionReturn(0); 2710 } 2711 2712 /*@ 2713 TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context 2714 2715 Collective 2716 2717 Input Parameters: 2718 + ts - the TS context obtained from TSCreate() 2719 - snes - the nonlinear solver context 2720 2721 Notes: 2722 Most users should have the TS created by calling TSGetSNES() 2723 2724 Level: developer 2725 2726 @*/ 2727 PetscErrorCode TSSetSNES(TS ts, SNES snes) { 2728 PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *); 2729 2730 PetscFunctionBegin; 2731 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2732 PetscValidHeaderSpecific(snes, SNES_CLASSID, 2); 2733 PetscCall(PetscObjectReference((PetscObject)snes)); 2734 PetscCall(SNESDestroy(&ts->snes)); 2735 2736 ts->snes = snes; 2737 2738 PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts)); 2739 PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL)); 2740 if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts)); 2741 PetscFunctionReturn(0); 2742 } 2743 2744 /*@ 2745 TSGetKSP - Returns the KSP (linear solver) associated with 2746 a TS (timestepper) context. 2747 2748 Not Collective, but KSP is parallel if TS is parallel 2749 2750 Input Parameter: 2751 . ts - the TS context obtained from TSCreate() 2752 2753 Output Parameter: 2754 . ksp - the nonlinear solver context 2755 2756 Notes: 2757 The user can then directly manipulate the KSP context to set various 2758 options, etc. Likewise, the user can then extract and manipulate the 2759 KSP and PC contexts as well. 2760 2761 TSGetKSP() does not work for integrators that do not use KSP; 2762 in this case TSGetKSP() returns NULL in ksp. 2763 2764 Level: beginner 2765 2766 @*/ 2767 PetscErrorCode TSGetKSP(TS ts, KSP *ksp) { 2768 SNES snes; 2769 2770 PetscFunctionBegin; 2771 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2772 PetscValidPointer(ksp, 2); 2773 PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first"); 2774 PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()"); 2775 PetscCall(TSGetSNES(ts, &snes)); 2776 PetscCall(SNESGetKSP(snes, ksp)); 2777 PetscFunctionReturn(0); 2778 } 2779 2780 /* ----------- Routines to set solver parameters ---------- */ 2781 2782 /*@ 2783 TSSetMaxSteps - Sets the maximum number of steps to use. 2784 2785 Logically Collective on TS 2786 2787 Input Parameters: 2788 + ts - the TS context obtained from TSCreate() 2789 - maxsteps - maximum number of steps to use 2790 2791 Options Database Keys: 2792 . -ts_max_steps <maxsteps> - Sets maxsteps 2793 2794 Notes: 2795 The default maximum number of steps is 5000 2796 2797 Level: intermediate 2798 2799 .seealso: `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()` 2800 @*/ 2801 PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps) { 2802 PetscFunctionBegin; 2803 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2804 PetscValidLogicalCollectiveInt(ts, maxsteps, 2); 2805 PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative"); 2806 ts->max_steps = maxsteps; 2807 PetscFunctionReturn(0); 2808 } 2809 2810 /*@ 2811 TSGetMaxSteps - Gets the maximum number of steps to use. 2812 2813 Not Collective 2814 2815 Input Parameters: 2816 . ts - the TS context obtained from TSCreate() 2817 2818 Output Parameter: 2819 . maxsteps - maximum number of steps to use 2820 2821 Level: advanced 2822 2823 .seealso: `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()` 2824 @*/ 2825 PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps) { 2826 PetscFunctionBegin; 2827 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2828 PetscValidIntPointer(maxsteps, 2); 2829 *maxsteps = ts->max_steps; 2830 PetscFunctionReturn(0); 2831 } 2832 2833 /*@ 2834 TSSetMaxTime - Sets the maximum (or final) time for timestepping. 2835 2836 Logically Collective on TS 2837 2838 Input Parameters: 2839 + ts - the TS context obtained from TSCreate() 2840 - maxtime - final time to step to 2841 2842 Options Database Keys: 2843 . -ts_max_time <maxtime> - Sets maxtime 2844 2845 Notes: 2846 The default maximum time is 5.0 2847 2848 Level: intermediate 2849 2850 .seealso: `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()` 2851 @*/ 2852 PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime) { 2853 PetscFunctionBegin; 2854 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2855 PetscValidLogicalCollectiveReal(ts, maxtime, 2); 2856 ts->max_time = maxtime; 2857 PetscFunctionReturn(0); 2858 } 2859 2860 /*@ 2861 TSGetMaxTime - Gets the maximum (or final) time for timestepping. 2862 2863 Not Collective 2864 2865 Input Parameters: 2866 . ts - the TS context obtained from TSCreate() 2867 2868 Output Parameter: 2869 . maxtime - final time to step to 2870 2871 Level: advanced 2872 2873 .seealso: `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()` 2874 @*/ 2875 PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime) { 2876 PetscFunctionBegin; 2877 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2878 PetscValidRealPointer(maxtime, 2); 2879 *maxtime = ts->max_time; 2880 PetscFunctionReturn(0); 2881 } 2882 2883 /*@ 2884 TSSetInitialTimeStep - Deprecated, use TSSetTime() and TSSetTimeStep(). 2885 2886 Level: deprecated 2887 2888 @*/ 2889 PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step) { 2890 PetscFunctionBegin; 2891 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2892 PetscCall(TSSetTime(ts, initial_time)); 2893 PetscCall(TSSetTimeStep(ts, time_step)); 2894 PetscFunctionReturn(0); 2895 } 2896 2897 /*@ 2898 TSGetDuration - Deprecated, use TSGetMaxSteps() and TSGetMaxTime(). 2899 2900 Level: deprecated 2901 2902 @*/ 2903 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime) { 2904 PetscFunctionBegin; 2905 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2906 if (maxsteps) { 2907 PetscValidIntPointer(maxsteps, 2); 2908 *maxsteps = ts->max_steps; 2909 } 2910 if (maxtime) { 2911 PetscValidRealPointer(maxtime, 3); 2912 *maxtime = ts->max_time; 2913 } 2914 PetscFunctionReturn(0); 2915 } 2916 2917 /*@ 2918 TSSetDuration - Deprecated, use TSSetMaxSteps() and TSSetMaxTime(). 2919 2920 Level: deprecated 2921 2922 @*/ 2923 PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime) { 2924 PetscFunctionBegin; 2925 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2926 PetscValidLogicalCollectiveInt(ts, maxsteps, 2); 2927 PetscValidLogicalCollectiveReal(ts, maxtime, 3); 2928 if (maxsteps >= 0) ts->max_steps = maxsteps; 2929 if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime; 2930 PetscFunctionReturn(0); 2931 } 2932 2933 /*@ 2934 TSGetTimeStepNumber - Deprecated, use TSGetStepNumber(). 2935 2936 Level: deprecated 2937 2938 @*/ 2939 PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps) { 2940 return TSGetStepNumber(ts, steps); 2941 } 2942 2943 /*@ 2944 TSGetTotalSteps - Deprecated, use TSGetStepNumber(). 2945 2946 Level: deprecated 2947 2948 @*/ 2949 PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps) { 2950 return TSGetStepNumber(ts, steps); 2951 } 2952 2953 /*@ 2954 TSSetSolution - Sets the initial solution vector 2955 for use by the TS routines. 2956 2957 Logically Collective on TS 2958 2959 Input Parameters: 2960 + ts - the TS context obtained from TSCreate() 2961 - u - the solution vector 2962 2963 Level: beginner 2964 2965 .seealso: `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()` 2966 @*/ 2967 PetscErrorCode TSSetSolution(TS ts, Vec u) { 2968 DM dm; 2969 2970 PetscFunctionBegin; 2971 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2972 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 2973 PetscCall(PetscObjectReference((PetscObject)u)); 2974 PetscCall(VecDestroy(&ts->vec_sol)); 2975 ts->vec_sol = u; 2976 2977 PetscCall(TSGetDM(ts, &dm)); 2978 PetscCall(DMShellSetGlobalVector(dm, u)); 2979 PetscFunctionReturn(0); 2980 } 2981 2982 /*@C 2983 TSSetPreStep - Sets the general-purpose function 2984 called once at the beginning of each time step. 2985 2986 Logically Collective on TS 2987 2988 Input Parameters: 2989 + ts - The TS context obtained from TSCreate() 2990 - func - The function 2991 2992 Calling sequence of func: 2993 .vb 2994 PetscErrorCode func (TS ts); 2995 .ve 2996 2997 Level: intermediate 2998 2999 .seealso: `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()` 3000 @*/ 3001 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS)) { 3002 PetscFunctionBegin; 3003 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3004 ts->prestep = func; 3005 PetscFunctionReturn(0); 3006 } 3007 3008 /*@ 3009 TSPreStep - Runs the user-defined pre-step function. 3010 3011 Collective on TS 3012 3013 Input Parameters: 3014 . ts - The TS context obtained from TSCreate() 3015 3016 Notes: 3017 TSPreStep() is typically used within time stepping implementations, 3018 so most users would not generally call this routine themselves. 3019 3020 Level: developer 3021 3022 .seealso: `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()` 3023 @*/ 3024 PetscErrorCode TSPreStep(TS ts) { 3025 PetscFunctionBegin; 3026 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3027 if (ts->prestep) { 3028 Vec U; 3029 PetscObjectId idprev; 3030 PetscBool sameObject; 3031 PetscObjectState sprev, spost; 3032 3033 PetscCall(TSGetSolution(ts, &U)); 3034 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3035 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3036 PetscCallBack("TS callback preset", (*ts->prestep)(ts)); 3037 PetscCall(TSGetSolution(ts, &U)); 3038 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3039 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3040 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3041 } 3042 PetscFunctionReturn(0); 3043 } 3044 3045 /*@C 3046 TSSetPreStage - Sets the general-purpose function 3047 called once at the beginning of each stage. 3048 3049 Logically Collective on TS 3050 3051 Input Parameters: 3052 + ts - The TS context obtained from TSCreate() 3053 - func - The function 3054 3055 Calling sequence of func: 3056 .vb 3057 PetscErrorCode func(TS ts, PetscReal stagetime); 3058 .ve 3059 3060 Level: intermediate 3061 3062 Note: 3063 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3064 The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being 3065 attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime(). 3066 3067 .seealso: `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3068 @*/ 3069 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS, PetscReal)) { 3070 PetscFunctionBegin; 3071 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3072 ts->prestage = func; 3073 PetscFunctionReturn(0); 3074 } 3075 3076 /*@C 3077 TSSetPostStage - Sets the general-purpose function 3078 called once at the end of each stage. 3079 3080 Logically Collective on TS 3081 3082 Input Parameters: 3083 + ts - The TS context obtained from TSCreate() 3084 - func - The function 3085 3086 Calling sequence of func: 3087 .vb 3088 PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y); 3089 .ve 3090 3091 Level: intermediate 3092 3093 Note: 3094 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3095 The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being 3096 attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime(). 3097 3098 .seealso: `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3099 @*/ 3100 PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS, PetscReal, PetscInt, Vec *)) { 3101 PetscFunctionBegin; 3102 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3103 ts->poststage = func; 3104 PetscFunctionReturn(0); 3105 } 3106 3107 /*@C 3108 TSSetPostEvaluate - Sets the general-purpose function 3109 called once at the end of each step evaluation. 3110 3111 Logically Collective on TS 3112 3113 Input Parameters: 3114 + ts - The TS context obtained from TSCreate() 3115 - func - The function 3116 3117 Calling sequence of func: 3118 .vb 3119 PetscErrorCode func(TS ts); 3120 .ve 3121 3122 Level: intermediate 3123 3124 Note: 3125 Semantically, TSSetPostEvaluate() differs from TSSetPostStep() since the function it sets is called before event-handling 3126 thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, TSPostStep() 3127 may be passed a different solution, possibly changed by the event handler. TSPostEvaluate() is called after the next step 3128 solution is evaluated allowing to modify it, if need be. The solution can be obtained with TSGetSolution(), the time step 3129 with TSGetTimeStep(), and the time at the start of the step is available via TSGetTime() 3130 3131 .seealso: `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3132 @*/ 3133 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS)) { 3134 PetscFunctionBegin; 3135 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3136 ts->postevaluate = func; 3137 PetscFunctionReturn(0); 3138 } 3139 3140 /*@ 3141 TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage() 3142 3143 Collective on TS 3144 3145 Input Parameters: 3146 . ts - The TS context obtained from TSCreate() 3147 stagetime - The absolute time of the current stage 3148 3149 Notes: 3150 TSPreStage() is typically used within time stepping implementations, 3151 most users would not generally call this routine themselves. 3152 3153 Level: developer 3154 3155 .seealso: `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3156 @*/ 3157 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime) { 3158 PetscFunctionBegin; 3159 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3160 if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime)); 3161 PetscFunctionReturn(0); 3162 } 3163 3164 /*@ 3165 TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage() 3166 3167 Collective on TS 3168 3169 Input Parameters: 3170 . ts - The TS context obtained from TSCreate() 3171 stagetime - The absolute time of the current stage 3172 stageindex - Stage number 3173 Y - Array of vectors (of size = total number 3174 of stages) with the stage solutions 3175 3176 Notes: 3177 TSPostStage() is typically used within time stepping implementations, 3178 most users would not generally call this routine themselves. 3179 3180 Level: developer 3181 3182 .seealso: `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3183 @*/ 3184 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y) { 3185 PetscFunctionBegin; 3186 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3187 if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y)); 3188 PetscFunctionReturn(0); 3189 } 3190 3191 /*@ 3192 TSPostEvaluate - Runs the user-defined post-evaluate function set using TSSetPostEvaluate() 3193 3194 Collective on TS 3195 3196 Input Parameters: 3197 . ts - The TS context obtained from TSCreate() 3198 3199 Notes: 3200 TSPostEvaluate() is typically used within time stepping implementations, 3201 most users would not generally call this routine themselves. 3202 3203 Level: developer 3204 3205 .seealso: `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3206 @*/ 3207 PetscErrorCode TSPostEvaluate(TS ts) { 3208 PetscFunctionBegin; 3209 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3210 if (ts->postevaluate) { 3211 Vec U; 3212 PetscObjectState sprev, spost; 3213 3214 PetscCall(TSGetSolution(ts, &U)); 3215 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3216 PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts)); 3217 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3218 if (sprev != spost) PetscCall(TSRestartStep(ts)); 3219 } 3220 PetscFunctionReturn(0); 3221 } 3222 3223 /*@C 3224 TSSetPostStep - Sets the general-purpose function 3225 called once at the end of each time step. 3226 3227 Logically Collective on TS 3228 3229 Input Parameters: 3230 + ts - The TS context obtained from TSCreate() 3231 - func - The function 3232 3233 Calling sequence of func: 3234 $ func (TS ts); 3235 3236 Notes: 3237 The function set by TSSetPostStep() is called after each successful step. The solution vector X 3238 obtained by TSGetSolution() may be different than that computed at the step end if the event handler 3239 locates an event and TSPostEvent() modifies it. Use TSSetPostEvaluate() if an unmodified solution is needed instead. 3240 3241 Level: intermediate 3242 3243 .seealso: `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()` 3244 @*/ 3245 PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS)) { 3246 PetscFunctionBegin; 3247 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3248 ts->poststep = func; 3249 PetscFunctionReturn(0); 3250 } 3251 3252 /*@ 3253 TSPostStep - Runs the user-defined post-step function. 3254 3255 Collective on TS 3256 3257 Input Parameters: 3258 . ts - The TS context obtained from TSCreate() 3259 3260 Notes: 3261 TSPostStep() is typically used within time stepping implementations, 3262 so most users would not generally call this routine themselves. 3263 3264 Level: developer 3265 3266 @*/ 3267 PetscErrorCode TSPostStep(TS ts) { 3268 PetscFunctionBegin; 3269 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3270 if (ts->poststep) { 3271 Vec U; 3272 PetscObjectId idprev; 3273 PetscBool sameObject; 3274 PetscObjectState sprev, spost; 3275 3276 PetscCall(TSGetSolution(ts, &U)); 3277 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3278 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3279 PetscCallBack("TS callback poststep", (*ts->poststep)(ts)); 3280 PetscCall(TSGetSolution(ts, &U)); 3281 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3282 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3283 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3284 } 3285 PetscFunctionReturn(0); 3286 } 3287 3288 /*@ 3289 TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval 3290 3291 Collective on TS 3292 3293 Input Parameters: 3294 + ts - time stepping context 3295 - t - time to interpolate to 3296 3297 Output Parameter: 3298 . U - state at given time 3299 3300 Level: intermediate 3301 3302 Developer Notes: 3303 TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints. 3304 3305 .seealso: `TSSetExactFinalTime()`, `TSSolve()` 3306 @*/ 3307 PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U) { 3308 PetscFunctionBegin; 3309 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3310 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3311 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); 3312 PetscUseTypeMethod(ts, interpolate, t, U); 3313 PetscFunctionReturn(0); 3314 } 3315 3316 /*@ 3317 TSStep - Steps one time step 3318 3319 Collective on TS 3320 3321 Input Parameter: 3322 . ts - the TS context obtained from TSCreate() 3323 3324 Level: developer 3325 3326 Notes: 3327 The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine. 3328 3329 The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may 3330 be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages. 3331 3332 This may over-step the final time provided in TSSetMaxTime() depending on the time-step used. TSSolve() interpolates to exactly the 3333 time provided in TSSetMaxTime(). One can use TSInterpolate() to determine an interpolated solution within the final timestep. 3334 3335 .seealso: `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()` 3336 @*/ 3337 PetscErrorCode TSStep(TS ts) { 3338 static PetscBool cite = PETSC_FALSE; 3339 PetscReal ptime; 3340 3341 PetscFunctionBegin; 3342 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3343 PetscCall(PetscCitationsRegister("@article{tspaper,\n" 3344 " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n" 3345 " author = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n" 3346 " journal = {arXiv e-preprints},\n" 3347 " eprint = {1806.01437},\n" 3348 " archivePrefix = {arXiv},\n" 3349 " year = {2018}\n}\n", 3350 &cite)); 3351 PetscCall(TSSetUp(ts)); 3352 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 3353 3354 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>"); 3355 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()"); 3356 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"); 3357 3358 if (!ts->steps) ts->ptime_prev = ts->ptime; 3359 ptime = ts->ptime; 3360 ts->ptime_prev_rollback = ts->ptime_prev; 3361 ts->reason = TS_CONVERGED_ITERATING; 3362 3363 PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0)); 3364 PetscUseTypeMethod(ts, step); 3365 PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0)); 3366 3367 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) 3368 PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[ts->tspan->spanctr++])); 3369 if (ts->reason >= 0) { 3370 ts->ptime_prev = ptime; 3371 ts->steps++; 3372 ts->steprollback = PETSC_FALSE; 3373 ts->steprestart = PETSC_FALSE; 3374 } 3375 if (!ts->reason) { 3376 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 3377 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 3378 } 3379 3380 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]); 3381 PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]); 3382 PetscFunctionReturn(0); 3383 } 3384 3385 /*@ 3386 TSEvaluateWLTE - Evaluate the weighted local truncation error norm 3387 at the end of a time step with a given order of accuracy. 3388 3389 Collective on TS 3390 3391 Input Parameters: 3392 + ts - time stepping context 3393 - wnormtype - norm type, either NORM_2 or NORM_INFINITY 3394 3395 Input/Output Parameter: 3396 . order - optional, desired order for the error evaluation or PETSC_DECIDE; 3397 on output, the actual order of the error evaluation 3398 3399 Output Parameter: 3400 . wlte - the weighted local truncation error norm 3401 3402 Level: advanced 3403 3404 Notes: 3405 If the timestepper cannot evaluate the error in a particular step 3406 (eg. in the first step or restart steps after event handling), 3407 this routine returns wlte=-1.0 . 3408 3409 .seealso: `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()` 3410 @*/ 3411 PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte) { 3412 PetscFunctionBegin; 3413 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3414 PetscValidType(ts, 1); 3415 PetscValidLogicalCollectiveEnum(ts, wnormtype, 2); 3416 if (order) PetscValidIntPointer(order, 3); 3417 if (order) PetscValidLogicalCollectiveInt(ts, *order, 3); 3418 PetscValidRealPointer(wlte, 4); 3419 PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 3420 PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte); 3421 PetscFunctionReturn(0); 3422 } 3423 3424 /*@ 3425 TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy. 3426 3427 Collective on TS 3428 3429 Input Parameters: 3430 + ts - time stepping context 3431 . order - desired order of accuracy 3432 - done - whether the step was evaluated at this order (pass NULL to generate an error if not available) 3433 3434 Output Parameter: 3435 . U - state at the end of the current step 3436 3437 Level: advanced 3438 3439 Notes: 3440 This function cannot be called until all stages have been evaluated. 3441 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. 3442 3443 .seealso: `TSStep()`, `TSAdapt` 3444 @*/ 3445 PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done) { 3446 PetscFunctionBegin; 3447 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3448 PetscValidType(ts, 1); 3449 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3450 PetscUseTypeMethod(ts, evaluatestep, order, U, done); 3451 PetscFunctionReturn(0); 3452 } 3453 3454 /*@C 3455 TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping. 3456 3457 Not collective 3458 3459 Input Parameter: 3460 . ts - time stepping context 3461 3462 Output Parameter: 3463 . initConditions - The function which computes an initial condition 3464 3465 Level: advanced 3466 3467 Notes: 3468 The calling sequence for the function is 3469 $ initCondition(TS ts, Vec u) 3470 $ ts - The timestepping context 3471 $ u - The input vector in which the initial condition is stored 3472 3473 .seealso: `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()` 3474 @*/ 3475 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS, Vec)) { 3476 PetscFunctionBegin; 3477 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3478 PetscValidPointer(initCondition, 2); 3479 *initCondition = ts->ops->initcondition; 3480 PetscFunctionReturn(0); 3481 } 3482 3483 /*@C 3484 TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping. 3485 3486 Logically collective on ts 3487 3488 Input Parameters: 3489 + ts - time stepping context 3490 - initCondition - The function which computes an initial condition 3491 3492 Level: advanced 3493 3494 Calling sequence for initCondition: 3495 $ PetscErrorCode initCondition(TS ts, Vec u) 3496 3497 + ts - The timestepping context 3498 - u - The input vector in which the initial condition is to be stored 3499 3500 .seealso: `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()` 3501 @*/ 3502 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS, Vec)) { 3503 PetscFunctionBegin; 3504 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3505 PetscValidFunction(initCondition, 2); 3506 ts->ops->initcondition = initCondition; 3507 PetscFunctionReturn(0); 3508 } 3509 3510 /*@ 3511 TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set. 3512 3513 Collective on ts 3514 3515 Input Parameters: 3516 + ts - time stepping context 3517 - u - The Vec to store the condition in which will be used in TSSolve() 3518 3519 Level: advanced 3520 3521 .seealso: `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3522 @*/ 3523 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u) { 3524 PetscFunctionBegin; 3525 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3526 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3527 PetscTryTypeMethod(ts, initcondition, u); 3528 PetscFunctionReturn(0); 3529 } 3530 3531 /*@C 3532 TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping. 3533 3534 Not collective 3535 3536 Input Parameter: 3537 . ts - time stepping context 3538 3539 Output Parameter: 3540 . exactError - The function which computes the solution error 3541 3542 Level: advanced 3543 3544 Calling sequence for exactError: 3545 $ PetscErrorCode exactError(TS ts, Vec u) 3546 3547 + ts - The timestepping context 3548 . u - The approximate solution vector 3549 - e - The input vector in which the error is stored 3550 3551 .seealso: `TSGetComputeExactError()`, `TSComputeExactError()` 3552 @*/ 3553 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS, Vec, Vec)) { 3554 PetscFunctionBegin; 3555 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3556 PetscValidPointer(exactError, 2); 3557 *exactError = ts->ops->exacterror; 3558 PetscFunctionReturn(0); 3559 } 3560 3561 /*@C 3562 TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping. 3563 3564 Logically collective on ts 3565 3566 Input Parameters: 3567 + ts - time stepping context 3568 - exactError - The function which computes the solution error 3569 3570 Level: advanced 3571 3572 Calling sequence for exactError: 3573 $ PetscErrorCode exactError(TS ts, Vec u) 3574 3575 + ts - The timestepping context 3576 . u - The approximate solution vector 3577 - e - The input vector in which the error is stored 3578 3579 .seealso: `TSGetComputeExactError()`, `TSComputeExactError()` 3580 @*/ 3581 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS, Vec, Vec)) { 3582 PetscFunctionBegin; 3583 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3584 PetscValidFunction(exactError, 2); 3585 ts->ops->exacterror = exactError; 3586 PetscFunctionReturn(0); 3587 } 3588 3589 /*@ 3590 TSComputeExactError - Compute the solution error for the timestepping using the function previously set. 3591 3592 Collective on ts 3593 3594 Input Parameters: 3595 + ts - time stepping context 3596 . u - The approximate solution 3597 - e - The Vec used to store the error 3598 3599 Level: advanced 3600 3601 .seealso: `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3602 @*/ 3603 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e) { 3604 PetscFunctionBegin; 3605 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3606 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3607 PetscValidHeaderSpecific(e, VEC_CLASSID, 3); 3608 PetscTryTypeMethod(ts, exacterror, u, e); 3609 PetscFunctionReturn(0); 3610 } 3611 3612 /*@ 3613 TSSolve - Steps the requested number of timesteps. 3614 3615 Collective on TS 3616 3617 Input Parameters: 3618 + ts - the TS context obtained from TSCreate() 3619 - u - the solution vector (can be null if TSSetSolution() was used and TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP) was not used, 3620 otherwise must contain the initial conditions and will contain the solution at the final requested time 3621 3622 Level: beginner 3623 3624 Notes: 3625 The final time returned by this function may be different from the time of the internally 3626 held state accessible by TSGetSolution() and TSGetTime() because the method may have 3627 stepped over the final time. 3628 3629 .seealso: `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()` 3630 @*/ 3631 PetscErrorCode TSSolve(TS ts, Vec u) { 3632 Vec solution; 3633 3634 PetscFunctionBegin; 3635 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3636 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3637 3638 PetscCall(TSSetExactFinalTimeDefault(ts)); 3639 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 */ 3640 if (!ts->vec_sol || u == ts->vec_sol) { 3641 PetscCall(VecDuplicate(u, &solution)); 3642 PetscCall(TSSetSolution(ts, solution)); 3643 PetscCall(VecDestroy(&solution)); /* grant ownership */ 3644 } 3645 PetscCall(VecCopy(u, ts->vec_sol)); 3646 PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE"); 3647 } else if (u) PetscCall(TSSetSolution(ts, u)); 3648 PetscCall(TSSetUp(ts)); 3649 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 3650 3651 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>"); 3652 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()"); 3653 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"); 3654 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"); 3655 3656 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 */ 3657 PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[0])); 3658 ts->tspan->spanctr = 1; 3659 } 3660 3661 if (ts->forward_solve) PetscCall(TSForwardSetUp(ts)); 3662 3663 /* reset number of steps only when the step is not restarted. ARKIMEX 3664 restarts the step after an event. Resetting these counters in such case causes 3665 TSTrajectory to incorrectly save the output files 3666 */ 3667 /* reset time step and iteration counters */ 3668 if (!ts->steps) { 3669 ts->ksp_its = 0; 3670 ts->snes_its = 0; 3671 ts->num_snes_failures = 0; 3672 ts->reject = 0; 3673 ts->steprestart = PETSC_TRUE; 3674 ts->steprollback = PETSC_FALSE; 3675 ts->rhsjacobian.time = PETSC_MIN_REAL; 3676 } 3677 3678 /* make sure initial time step does not overshoot final time or the next point in tspan */ 3679 if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 3680 PetscReal maxdt; 3681 PetscReal dt = ts->time_step; 3682 3683 if (ts->tspan) maxdt = ts->tspan->span_times[ts->tspan->spanctr] - ts->ptime; 3684 else maxdt = ts->max_time - ts->ptime; 3685 ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt); 3686 } 3687 ts->reason = TS_CONVERGED_ITERATING; 3688 3689 { 3690 PetscViewer viewer; 3691 PetscViewerFormat format; 3692 PetscBool flg; 3693 static PetscBool incall = PETSC_FALSE; 3694 3695 if (!incall) { 3696 /* Estimate the convergence rate of the time discretization */ 3697 PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg)); 3698 if (flg) { 3699 PetscConvEst conv; 3700 DM dm; 3701 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 3702 PetscInt Nf; 3703 PetscBool checkTemporal = PETSC_TRUE; 3704 3705 incall = PETSC_TRUE; 3706 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg)); 3707 PetscCall(TSGetDM(ts, &dm)); 3708 PetscCall(DMGetNumFields(dm, &Nf)); 3709 PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha)); 3710 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv)); 3711 PetscCall(PetscConvEstUseTS(conv, checkTemporal)); 3712 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts)); 3713 PetscCall(PetscConvEstSetFromOptions(conv)); 3714 PetscCall(PetscConvEstSetUp(conv)); 3715 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 3716 PetscCall(PetscViewerPushFormat(viewer, format)); 3717 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 3718 PetscCall(PetscViewerPopFormat(viewer)); 3719 PetscCall(PetscViewerDestroy(&viewer)); 3720 PetscCall(PetscConvEstDestroy(&conv)); 3721 PetscCall(PetscFree(alpha)); 3722 incall = PETSC_FALSE; 3723 } 3724 } 3725 } 3726 3727 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre")); 3728 3729 if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */ 3730 PetscUseTypeMethod(ts, solve); 3731 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 3732 ts->solvetime = ts->ptime; 3733 solution = ts->vec_sol; 3734 } else { /* Step the requested number of timesteps. */ 3735 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 3736 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 3737 3738 if (!ts->steps) { 3739 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 3740 PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol)); 3741 } 3742 3743 while (!ts->reason) { 3744 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 3745 if (!ts->steprollback) PetscCall(TSPreStep(ts)); 3746 PetscCall(TSStep(ts)); 3747 if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL)); 3748 if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL)); 3749 if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */ 3750 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 3751 PetscCall(TSForwardCostIntegral(ts)); 3752 if (ts->reason >= 0) ts->steps++; 3753 } 3754 if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */ 3755 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 3756 PetscCall(TSForwardStep(ts)); 3757 if (ts->reason >= 0) ts->steps++; 3758 } 3759 PetscCall(TSPostEvaluate(ts)); 3760 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. */ 3761 if (ts->steprollback) PetscCall(TSPostEvaluate(ts)); 3762 if (!ts->steprollback) { 3763 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 3764 PetscCall(TSPostStep(ts)); 3765 } 3766 } 3767 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 3768 3769 if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) { 3770 PetscCall(TSInterpolate(ts, ts->max_time, u)); 3771 ts->solvetime = ts->max_time; 3772 solution = u; 3773 PetscCall(TSMonitor(ts, -1, ts->solvetime, solution)); 3774 } else { 3775 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 3776 ts->solvetime = ts->ptime; 3777 solution = ts->vec_sol; 3778 } 3779 } 3780 3781 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view")); 3782 PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution")); 3783 PetscCall(PetscObjectSAWsBlock((PetscObject)ts)); 3784 if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts)); 3785 PetscFunctionReturn(0); 3786 } 3787 3788 /*@ 3789 TSGetTime - Gets the time of the most recently completed step. 3790 3791 Not Collective 3792 3793 Input Parameter: 3794 . ts - the TS context obtained from TSCreate() 3795 3796 Output Parameter: 3797 . t - the current time. This time may not corresponds to the final time set with TSSetMaxTime(), use TSGetSolveTime(). 3798 3799 Level: beginner 3800 3801 Note: 3802 When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(), 3803 TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated. 3804 3805 .seealso: `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()` 3806 3807 @*/ 3808 PetscErrorCode TSGetTime(TS ts, PetscReal *t) { 3809 PetscFunctionBegin; 3810 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3811 PetscValidRealPointer(t, 2); 3812 *t = ts->ptime; 3813 PetscFunctionReturn(0); 3814 } 3815 3816 /*@ 3817 TSGetPrevTime - Gets the starting time of the previously completed step. 3818 3819 Not Collective 3820 3821 Input Parameter: 3822 . ts - the TS context obtained from TSCreate() 3823 3824 Output Parameter: 3825 . t - the previous time 3826 3827 Level: beginner 3828 3829 .seealso: `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()` 3830 3831 @*/ 3832 PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t) { 3833 PetscFunctionBegin; 3834 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3835 PetscValidRealPointer(t, 2); 3836 *t = ts->ptime_prev; 3837 PetscFunctionReturn(0); 3838 } 3839 3840 /*@ 3841 TSSetTime - Allows one to reset the time. 3842 3843 Logically Collective on TS 3844 3845 Input Parameters: 3846 + ts - the TS context obtained from TSCreate() 3847 - time - the time 3848 3849 Level: intermediate 3850 3851 .seealso: `TSGetTime()`, `TSSetMaxSteps()` 3852 3853 @*/ 3854 PetscErrorCode TSSetTime(TS ts, PetscReal t) { 3855 PetscFunctionBegin; 3856 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3857 PetscValidLogicalCollectiveReal(ts, t, 2); 3858 ts->ptime = t; 3859 PetscFunctionReturn(0); 3860 } 3861 3862 /*@C 3863 TSSetOptionsPrefix - Sets the prefix used for searching for all 3864 TS options in the database. 3865 3866 Logically Collective on TS 3867 3868 Input Parameters: 3869 + ts - The TS context 3870 - prefix - The prefix to prepend to all option names 3871 3872 Notes: 3873 A hyphen (-) must NOT be given at the beginning of the prefix name. 3874 The first character of all runtime options is AUTOMATICALLY the 3875 hyphen. 3876 3877 Level: advanced 3878 3879 .seealso: `TSSetFromOptions()` 3880 3881 @*/ 3882 PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[]) { 3883 SNES snes; 3884 3885 PetscFunctionBegin; 3886 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3887 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix)); 3888 PetscCall(TSGetSNES(ts, &snes)); 3889 PetscCall(SNESSetOptionsPrefix(snes, prefix)); 3890 PetscFunctionReturn(0); 3891 } 3892 3893 /*@C 3894 TSAppendOptionsPrefix - Appends to the prefix used for searching for all 3895 TS options in the database. 3896 3897 Logically Collective on TS 3898 3899 Input Parameters: 3900 + ts - The TS context 3901 - prefix - The prefix to prepend to all option names 3902 3903 Notes: 3904 A hyphen (-) must NOT be given at the beginning of the prefix name. 3905 The first character of all runtime options is AUTOMATICALLY the 3906 hyphen. 3907 3908 Level: advanced 3909 3910 .seealso: `TSGetOptionsPrefix()` 3911 3912 @*/ 3913 PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[]) { 3914 SNES snes; 3915 3916 PetscFunctionBegin; 3917 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3918 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix)); 3919 PetscCall(TSGetSNES(ts, &snes)); 3920 PetscCall(SNESAppendOptionsPrefix(snes, prefix)); 3921 PetscFunctionReturn(0); 3922 } 3923 3924 /*@C 3925 TSGetOptionsPrefix - Sets the prefix used for searching for all 3926 TS options in the database. 3927 3928 Not Collective 3929 3930 Input Parameter: 3931 . ts - The TS context 3932 3933 Output Parameter: 3934 . prefix - A pointer to the prefix string used 3935 3936 Notes: 3937 On the fortran side, the user should pass in a string 'prifix' of 3938 sufficient length to hold the prefix. 3939 3940 Level: intermediate 3941 3942 .seealso: `TSAppendOptionsPrefix()` 3943 @*/ 3944 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[]) { 3945 PetscFunctionBegin; 3946 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3947 PetscValidPointer(prefix, 2); 3948 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix)); 3949 PetscFunctionReturn(0); 3950 } 3951 3952 /*@C 3953 TSGetRHSJacobian - Returns the Jacobian J at the present timestep. 3954 3955 Not Collective, but parallel objects are returned if TS is parallel 3956 3957 Input Parameter: 3958 . ts - The TS context obtained from TSCreate() 3959 3960 Output Parameters: 3961 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or NULL) 3962 . Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat (or NULL) 3963 . func - Function to compute the Jacobian of the RHS (or NULL) 3964 - ctx - User-defined context for Jacobian evaluation routine (or NULL) 3965 3966 Notes: 3967 You can pass in NULL for any return argument you do not need. 3968 3969 Level: intermediate 3970 3971 .seealso: `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 3972 3973 @*/ 3974 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobian *func, void **ctx) { 3975 DM dm; 3976 3977 PetscFunctionBegin; 3978 if (Amat || Pmat) { 3979 SNES snes; 3980 PetscCall(TSGetSNES(ts, &snes)); 3981 PetscCall(SNESSetUpMatrices(snes)); 3982 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 3983 } 3984 PetscCall(TSGetDM(ts, &dm)); 3985 PetscCall(DMTSGetRHSJacobian(dm, func, ctx)); 3986 PetscFunctionReturn(0); 3987 } 3988 3989 /*@C 3990 TSGetIJacobian - Returns the implicit Jacobian at the present timestep. 3991 3992 Not Collective, but parallel objects are returned if TS is parallel 3993 3994 Input Parameter: 3995 . ts - The TS context obtained from TSCreate() 3996 3997 Output Parameters: 3998 + Amat - The (approximate) Jacobian of F(t,U,U_t) 3999 . Pmat - The matrix from which the preconditioner is constructed, often the same as Amat 4000 . f - The function to compute the matrices 4001 - ctx - User-defined context for Jacobian evaluation routine 4002 4003 Notes: 4004 You can pass in NULL for any return argument you do not need. 4005 4006 Level: advanced 4007 4008 .seealso: `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4009 4010 @*/ 4011 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobian *f, void **ctx) { 4012 DM dm; 4013 4014 PetscFunctionBegin; 4015 if (Amat || Pmat) { 4016 SNES snes; 4017 PetscCall(TSGetSNES(ts, &snes)); 4018 PetscCall(SNESSetUpMatrices(snes)); 4019 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4020 } 4021 PetscCall(TSGetDM(ts, &dm)); 4022 PetscCall(DMTSGetIJacobian(dm, f, ctx)); 4023 PetscFunctionReturn(0); 4024 } 4025 4026 #include <petsc/private/dmimpl.h> 4027 /*@ 4028 TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS 4029 4030 Logically Collective on ts 4031 4032 Input Parameters: 4033 + ts - the ODE integrator object 4034 - dm - the dm, cannot be NULL 4035 4036 Notes: 4037 A DM can only be used for solving one problem at a time because information about the problem is stored on the DM, 4038 even when not using interfaces like DMTSSetIFunction(). Use DMClone() to get a distinct DM when solving 4039 different problems using the same function space. 4040 4041 Level: intermediate 4042 4043 .seealso: `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()` 4044 @*/ 4045 PetscErrorCode TSSetDM(TS ts, DM dm) { 4046 SNES snes; 4047 DMTS tsdm; 4048 4049 PetscFunctionBegin; 4050 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4051 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 4052 PetscCall(PetscObjectReference((PetscObject)dm)); 4053 if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */ 4054 if (ts->dm->dmts && !dm->dmts) { 4055 PetscCall(DMCopyDMTS(ts->dm, dm)); 4056 PetscCall(DMGetDMTS(ts->dm, &tsdm)); 4057 /* Grant write privileges to the replacement DM */ 4058 if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm; 4059 } 4060 PetscCall(DMDestroy(&ts->dm)); 4061 } 4062 ts->dm = dm; 4063 4064 PetscCall(TSGetSNES(ts, &snes)); 4065 PetscCall(SNESSetDM(snes, dm)); 4066 PetscFunctionReturn(0); 4067 } 4068 4069 /*@ 4070 TSGetDM - Gets the DM that may be used by some preconditioners 4071 4072 Not Collective 4073 4074 Input Parameter: 4075 . ts - the preconditioner context 4076 4077 Output Parameter: 4078 . dm - the dm 4079 4080 Level: intermediate 4081 4082 .seealso: `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()` 4083 @*/ 4084 PetscErrorCode TSGetDM(TS ts, DM *dm) { 4085 PetscFunctionBegin; 4086 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4087 if (!ts->dm) { 4088 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm)); 4089 if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm)); 4090 } 4091 *dm = ts->dm; 4092 PetscFunctionReturn(0); 4093 } 4094 4095 /*@ 4096 SNESTSFormFunction - Function to evaluate nonlinear residual 4097 4098 Logically Collective on SNES 4099 4100 Input Parameters: 4101 + snes - nonlinear solver 4102 . U - the current state at which to evaluate the residual 4103 - ctx - user context, must be a TS 4104 4105 Output Parameter: 4106 . F - the nonlinear residual 4107 4108 Notes: 4109 This function is not normally called by users and is automatically registered with the SNES used by TS. 4110 It is most frequently passed to MatFDColoringSetFunction(). 4111 4112 Level: advanced 4113 4114 .seealso: `SNESSetFunction()`, `MatFDColoringSetFunction()` 4115 @*/ 4116 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx) { 4117 TS ts = (TS)ctx; 4118 4119 PetscFunctionBegin; 4120 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4121 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4122 PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 4123 PetscValidHeaderSpecific(ts, TS_CLASSID, 4); 4124 PetscCall((ts->ops->snesfunction)(snes, U, F, ts)); 4125 PetscFunctionReturn(0); 4126 } 4127 4128 /*@ 4129 SNESTSFormJacobian - Function to evaluate the Jacobian 4130 4131 Collective on SNES 4132 4133 Input Parameters: 4134 + snes - nonlinear solver 4135 . U - the current state at which to evaluate the residual 4136 - ctx - user context, must be a TS 4137 4138 Output Parameters: 4139 + A - the Jacobian 4140 - B - the preconditioning matrix (may be the same as A) 4141 4142 Notes: 4143 This function is not normally called by users and is automatically registered with the SNES used by TS. 4144 4145 Level: developer 4146 4147 .seealso: `SNESSetJacobian()` 4148 @*/ 4149 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx) { 4150 TS ts = (TS)ctx; 4151 4152 PetscFunctionBegin; 4153 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4154 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4155 PetscValidPointer(A, 3); 4156 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 4157 PetscValidPointer(B, 4); 4158 PetscValidHeaderSpecific(B, MAT_CLASSID, 4); 4159 PetscValidHeaderSpecific(ts, TS_CLASSID, 5); 4160 PetscCall((ts->ops->snesjacobian)(snes, U, A, B, ts)); 4161 PetscFunctionReturn(0); 4162 } 4163 4164 /*@C 4165 TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only 4166 4167 Collective on TS 4168 4169 Input Parameters: 4170 + ts - time stepping context 4171 . t - time at which to evaluate 4172 . U - state at which to evaluate 4173 - ctx - context 4174 4175 Output Parameter: 4176 . F - right hand side 4177 4178 Level: intermediate 4179 4180 Notes: 4181 This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems. 4182 The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian(). 4183 4184 .seealso: `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 4185 @*/ 4186 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx) { 4187 Mat Arhs, Brhs; 4188 4189 PetscFunctionBegin; 4190 PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs)); 4191 /* undo the damage caused by shifting */ 4192 PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs)); 4193 PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs)); 4194 PetscCall(MatMult(Arhs, U, F)); 4195 PetscFunctionReturn(0); 4196 } 4197 4198 /*@C 4199 TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent. 4200 4201 Collective on TS 4202 4203 Input Parameters: 4204 + ts - time stepping context 4205 . t - time at which to evaluate 4206 . U - state at which to evaluate 4207 - ctx - context 4208 4209 Output Parameters: 4210 + A - pointer to operator 4211 - B - pointer to preconditioning matrix 4212 4213 Level: intermediate 4214 4215 Notes: 4216 This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems. 4217 4218 .seealso: `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()` 4219 @*/ 4220 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx) { 4221 PetscFunctionBegin; 4222 PetscFunctionReturn(0); 4223 } 4224 4225 /*@C 4226 TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only 4227 4228 Collective on TS 4229 4230 Input Parameters: 4231 + ts - time stepping context 4232 . t - time at which to evaluate 4233 . U - state at which to evaluate 4234 . Udot - time derivative of state vector 4235 - ctx - context 4236 4237 Output Parameter: 4238 . F - left hand side 4239 4240 Level: intermediate 4241 4242 Notes: 4243 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 4244 user is required to write their own TSComputeIFunction. 4245 This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems. 4246 The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian(). 4247 4248 Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U 4249 4250 .seealso: `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()` 4251 @*/ 4252 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx) { 4253 Mat A, B; 4254 4255 PetscFunctionBegin; 4256 PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL)); 4257 PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE)); 4258 PetscCall(MatMult(A, Udot, F)); 4259 PetscFunctionReturn(0); 4260 } 4261 4262 /*@C 4263 TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE 4264 4265 Collective on TS 4266 4267 Input Parameters: 4268 + ts - time stepping context 4269 . t - time at which to evaluate 4270 . U - state at which to evaluate 4271 . Udot - time derivative of state vector 4272 . shift - shift to apply 4273 - ctx - context 4274 4275 Output Parameters: 4276 + A - pointer to operator 4277 - B - pointer to preconditioning matrix 4278 4279 Level: advanced 4280 4281 Notes: 4282 This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems. 4283 4284 It is only appropriate for problems of the form 4285 4286 $ M Udot = F(U,t) 4287 4288 where M is constant and F is non-stiff. The user must pass M to TSSetIJacobian(). The current implementation only 4289 works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing 4290 an implicit operator of the form 4291 4292 $ shift*M + J 4293 4294 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 4295 a copy of M or reassemble it when requested. 4296 4297 .seealso: `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()` 4298 @*/ 4299 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx) { 4300 PetscFunctionBegin; 4301 PetscCall(MatScale(A, shift / ts->ijacobian.shift)); 4302 ts->ijacobian.shift = shift; 4303 PetscFunctionReturn(0); 4304 } 4305 4306 /*@ 4307 TSGetEquationType - Gets the type of the equation that TS is solving. 4308 4309 Not Collective 4310 4311 Input Parameter: 4312 . ts - the TS context 4313 4314 Output Parameter: 4315 . equation_type - see TSEquationType 4316 4317 Level: beginner 4318 4319 .seealso: `TSSetEquationType()`, `TSEquationType` 4320 @*/ 4321 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type) { 4322 PetscFunctionBegin; 4323 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4324 PetscValidPointer(equation_type, 2); 4325 *equation_type = ts->equation_type; 4326 PetscFunctionReturn(0); 4327 } 4328 4329 /*@ 4330 TSSetEquationType - Sets the type of the equation that TS is solving. 4331 4332 Not Collective 4333 4334 Input Parameters: 4335 + ts - the TS context 4336 - equation_type - see TSEquationType 4337 4338 Level: advanced 4339 4340 .seealso: `TSGetEquationType()`, `TSEquationType` 4341 @*/ 4342 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type) { 4343 PetscFunctionBegin; 4344 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4345 ts->equation_type = equation_type; 4346 PetscFunctionReturn(0); 4347 } 4348 4349 /*@ 4350 TSGetConvergedReason - Gets the reason the TS iteration was stopped. 4351 4352 Not Collective 4353 4354 Input Parameter: 4355 . ts - the TS context 4356 4357 Output Parameter: 4358 . reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the 4359 manual pages for the individual convergence tests for complete lists 4360 4361 Level: beginner 4362 4363 Notes: 4364 Can only be called after the call to TSSolve() is complete. 4365 4366 .seealso: `TSSetConvergenceTest()`, `TSConvergedReason` 4367 @*/ 4368 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason) { 4369 PetscFunctionBegin; 4370 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4371 PetscValidPointer(reason, 2); 4372 *reason = ts->reason; 4373 PetscFunctionReturn(0); 4374 } 4375 4376 /*@ 4377 TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve. 4378 4379 Logically Collective; reason must contain common value 4380 4381 Input Parameters: 4382 + ts - the TS context 4383 - reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the 4384 manual pages for the individual convergence tests for complete lists 4385 4386 Level: advanced 4387 4388 Notes: 4389 Can only be called while TSSolve() is active. 4390 4391 .seealso: `TSConvergedReason` 4392 @*/ 4393 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason) { 4394 PetscFunctionBegin; 4395 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4396 ts->reason = reason; 4397 PetscFunctionReturn(0); 4398 } 4399 4400 /*@ 4401 TSGetSolveTime - Gets the time after a call to TSSolve() 4402 4403 Not Collective 4404 4405 Input Parameter: 4406 . ts - the TS context 4407 4408 Output Parameter: 4409 . ftime - the final time. This time corresponds to the final time set with TSSetMaxTime() 4410 4411 Level: beginner 4412 4413 Notes: 4414 Can only be called after the call to TSSolve() is complete. 4415 4416 .seealso: `TSSetConvergenceTest()`, `TSConvergedReason` 4417 @*/ 4418 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime) { 4419 PetscFunctionBegin; 4420 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4421 PetscValidRealPointer(ftime, 2); 4422 *ftime = ts->solvetime; 4423 PetscFunctionReturn(0); 4424 } 4425 4426 /*@ 4427 TSGetSNESIterations - Gets the total number of nonlinear iterations 4428 used by the time integrator. 4429 4430 Not Collective 4431 4432 Input Parameter: 4433 . ts - TS context 4434 4435 Output Parameter: 4436 . nits - number of nonlinear iterations 4437 4438 Notes: 4439 This counter is reset to zero for each successive call to TSSolve(). 4440 4441 Level: intermediate 4442 4443 .seealso: `TSGetKSPIterations()` 4444 @*/ 4445 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits) { 4446 PetscFunctionBegin; 4447 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4448 PetscValidIntPointer(nits, 2); 4449 *nits = ts->snes_its; 4450 PetscFunctionReturn(0); 4451 } 4452 4453 /*@ 4454 TSGetKSPIterations - Gets the total number of linear iterations 4455 used by the time integrator. 4456 4457 Not Collective 4458 4459 Input Parameter: 4460 . ts - TS context 4461 4462 Output Parameter: 4463 . lits - number of linear iterations 4464 4465 Notes: 4466 This counter is reset to zero for each successive call to TSSolve(). 4467 4468 Level: intermediate 4469 4470 .seealso: `TSGetSNESIterations()`, `SNESGetKSPIterations()` 4471 @*/ 4472 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits) { 4473 PetscFunctionBegin; 4474 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4475 PetscValidIntPointer(lits, 2); 4476 *lits = ts->ksp_its; 4477 PetscFunctionReturn(0); 4478 } 4479 4480 /*@ 4481 TSGetStepRejections - Gets the total number of rejected steps. 4482 4483 Not Collective 4484 4485 Input Parameter: 4486 . ts - TS context 4487 4488 Output Parameter: 4489 . rejects - number of steps rejected 4490 4491 Notes: 4492 This counter is reset to zero for each successive call to TSSolve(). 4493 4494 Level: intermediate 4495 4496 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()` 4497 @*/ 4498 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects) { 4499 PetscFunctionBegin; 4500 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4501 PetscValidIntPointer(rejects, 2); 4502 *rejects = ts->reject; 4503 PetscFunctionReturn(0); 4504 } 4505 4506 /*@ 4507 TSGetSNESFailures - Gets the total number of failed SNES solves 4508 4509 Not Collective 4510 4511 Input Parameter: 4512 . ts - TS context 4513 4514 Output Parameter: 4515 . fails - number of failed nonlinear solves 4516 4517 Notes: 4518 This counter is reset to zero for each successive call to TSSolve(). 4519 4520 Level: intermediate 4521 4522 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()` 4523 @*/ 4524 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails) { 4525 PetscFunctionBegin; 4526 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4527 PetscValidIntPointer(fails, 2); 4528 *fails = ts->num_snes_failures; 4529 PetscFunctionReturn(0); 4530 } 4531 4532 /*@ 4533 TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails 4534 4535 Not Collective 4536 4537 Input Parameters: 4538 + ts - TS context 4539 - rejects - maximum number of rejected steps, pass -1 for unlimited 4540 4541 Notes: 4542 The counter is reset to zero for each step 4543 4544 Options Database Key: 4545 . -ts_max_reject - Maximum number of step rejections before a step fails 4546 4547 Level: intermediate 4548 4549 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4550 @*/ 4551 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects) { 4552 PetscFunctionBegin; 4553 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4554 ts->max_reject = rejects; 4555 PetscFunctionReturn(0); 4556 } 4557 4558 /*@ 4559 TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves 4560 4561 Not Collective 4562 4563 Input Parameters: 4564 + ts - TS context 4565 - fails - maximum number of failed nonlinear solves, pass -1 for unlimited 4566 4567 Notes: 4568 The counter is reset to zero for each successive call to TSSolve(). 4569 4570 Options Database Key: 4571 . -ts_max_snes_failures - Maximum number of nonlinear solve failures 4572 4573 Level: intermediate 4574 4575 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()` 4576 @*/ 4577 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails) { 4578 PetscFunctionBegin; 4579 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4580 ts->max_snes_failures = fails; 4581 PetscFunctionReturn(0); 4582 } 4583 4584 /*@ 4585 TSSetErrorIfStepFails - Error if no step succeeds 4586 4587 Not Collective 4588 4589 Input Parameters: 4590 + ts - TS context 4591 - err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure 4592 4593 Options Database Key: 4594 . -ts_error_if_step_fails - Error if no step succeeds 4595 4596 Level: intermediate 4597 4598 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()` 4599 @*/ 4600 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err) { 4601 PetscFunctionBegin; 4602 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4603 ts->errorifstepfailed = err; 4604 PetscFunctionReturn(0); 4605 } 4606 4607 /*@ 4608 TSGetAdapt - Get the adaptive controller context for the current method 4609 4610 Collective on TS if controller has not been created yet 4611 4612 Input Parameter: 4613 . ts - time stepping context 4614 4615 Output Parameter: 4616 . adapt - adaptive controller 4617 4618 Level: intermediate 4619 4620 .seealso: `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()` 4621 @*/ 4622 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt) { 4623 PetscFunctionBegin; 4624 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4625 PetscValidPointer(adapt, 2); 4626 if (!ts->adapt) { 4627 PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt)); 4628 PetscCall(PetscLogObjectParent((PetscObject)ts, (PetscObject)ts->adapt)); 4629 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1)); 4630 } 4631 *adapt = ts->adapt; 4632 PetscFunctionReturn(0); 4633 } 4634 4635 /*@ 4636 TSSetTolerances - Set tolerances for local truncation error when using adaptive controller 4637 4638 Logically Collective 4639 4640 Input Parameters: 4641 + ts - time integration context 4642 . atol - scalar absolute tolerances, PETSC_DECIDE to leave current value 4643 . vatol - vector of absolute tolerances or NULL, used in preference to atol if present 4644 . rtol - scalar relative tolerances, PETSC_DECIDE to leave current value 4645 - vrtol - vector of relative tolerances or NULL, used in preference to atol if present 4646 4647 Options Database keys: 4648 + -ts_rtol <rtol> - relative tolerance for local truncation error 4649 - -ts_atol <atol> - Absolute tolerance for local truncation error 4650 4651 Notes: 4652 With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error 4653 (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be 4654 computed only for the differential or the algebraic part then this can be done using the vector of 4655 tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the 4656 differential part and infinity for the algebraic part, the LTE calculation will include only the 4657 differential variables. 4658 4659 Level: beginner 4660 4661 .seealso: `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()` 4662 @*/ 4663 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol) { 4664 PetscFunctionBegin; 4665 if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol; 4666 if (vatol) { 4667 PetscCall(PetscObjectReference((PetscObject)vatol)); 4668 PetscCall(VecDestroy(&ts->vatol)); 4669 ts->vatol = vatol; 4670 } 4671 if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol; 4672 if (vrtol) { 4673 PetscCall(PetscObjectReference((PetscObject)vrtol)); 4674 PetscCall(VecDestroy(&ts->vrtol)); 4675 ts->vrtol = vrtol; 4676 } 4677 PetscFunctionReturn(0); 4678 } 4679 4680 /*@ 4681 TSGetTolerances - Get tolerances for local truncation error when using adaptive controller 4682 4683 Logically Collective 4684 4685 Input Parameter: 4686 . ts - time integration context 4687 4688 Output Parameters: 4689 + atol - scalar absolute tolerances, NULL to ignore 4690 . vatol - vector of absolute tolerances, NULL to ignore 4691 . rtol - scalar relative tolerances, NULL to ignore 4692 - vrtol - vector of relative tolerances, NULL to ignore 4693 4694 Level: beginner 4695 4696 .seealso: `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()` 4697 @*/ 4698 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol) { 4699 PetscFunctionBegin; 4700 if (atol) *atol = ts->atol; 4701 if (vatol) *vatol = ts->vatol; 4702 if (rtol) *rtol = ts->rtol; 4703 if (vrtol) *vrtol = ts->vrtol; 4704 PetscFunctionReturn(0); 4705 } 4706 4707 /*@ 4708 TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors 4709 4710 Collective on TS 4711 4712 Input Parameters: 4713 + ts - time stepping context 4714 . U - state vector, usually ts->vec_sol 4715 - Y - state vector to be compared to U 4716 4717 Output Parameters: 4718 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 4719 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 4720 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 4721 4722 Level: developer 4723 4724 .seealso: `TSErrorWeightedNorm()`, `TSErrorWeightedNormInfinity()` 4725 @*/ 4726 PetscErrorCode TSErrorWeightedNorm2(TS ts, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) { 4727 PetscInt i, n, N, rstart; 4728 PetscInt n_loc, na_loc, nr_loc; 4729 PetscReal n_glb, na_glb, nr_glb; 4730 const PetscScalar *u, *y; 4731 PetscReal sum, suma, sumr, gsum, gsuma, gsumr, diff; 4732 PetscReal tol, tola, tolr; 4733 PetscReal err_loc[6], err_glb[6]; 4734 4735 PetscFunctionBegin; 4736 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4737 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4738 PetscValidHeaderSpecific(Y, VEC_CLASSID, 3); 4739 PetscValidType(U, 2); 4740 PetscValidType(Y, 3); 4741 PetscCheckSameComm(U, 2, Y, 3); 4742 PetscValidRealPointer(norm, 4); 4743 PetscValidRealPointer(norma, 5); 4744 PetscValidRealPointer(normr, 6); 4745 PetscCheck(U != Y, PetscObjectComm((PetscObject)U), PETSC_ERR_ARG_IDN, "U and Y cannot be the same vector"); 4746 4747 PetscCall(VecGetSize(U, &N)); 4748 PetscCall(VecGetLocalSize(U, &n)); 4749 PetscCall(VecGetOwnershipRange(U, &rstart, NULL)); 4750 PetscCall(VecGetArrayRead(U, &u)); 4751 PetscCall(VecGetArrayRead(Y, &y)); 4752 sum = 0.; 4753 n_loc = 0; 4754 suma = 0.; 4755 na_loc = 0; 4756 sumr = 0.; 4757 nr_loc = 0; 4758 if (ts->vatol && ts->vrtol) { 4759 const PetscScalar *atol, *rtol; 4760 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 4761 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 4762 for (i = 0; i < n; i++) { 4763 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4764 diff = PetscAbsScalar(y[i] - u[i]); 4765 tola = PetscRealPart(atol[i]); 4766 if (tola > 0.) { 4767 suma += PetscSqr(diff / tola); 4768 na_loc++; 4769 } 4770 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4771 if (tolr > 0.) { 4772 sumr += PetscSqr(diff / tolr); 4773 nr_loc++; 4774 } 4775 tol = tola + tolr; 4776 if (tol > 0.) { 4777 sum += PetscSqr(diff / tol); 4778 n_loc++; 4779 } 4780 } 4781 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 4782 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 4783 } else if (ts->vatol) { /* vector atol, scalar rtol */ 4784 const PetscScalar *atol; 4785 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 4786 for (i = 0; i < n; i++) { 4787 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4788 diff = PetscAbsScalar(y[i] - u[i]); 4789 tola = PetscRealPart(atol[i]); 4790 if (tola > 0.) { 4791 suma += PetscSqr(diff / tola); 4792 na_loc++; 4793 } 4794 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4795 if (tolr > 0.) { 4796 sumr += PetscSqr(diff / tolr); 4797 nr_loc++; 4798 } 4799 tol = tola + tolr; 4800 if (tol > 0.) { 4801 sum += PetscSqr(diff / tol); 4802 n_loc++; 4803 } 4804 } 4805 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 4806 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 4807 const PetscScalar *rtol; 4808 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 4809 for (i = 0; i < n; i++) { 4810 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4811 diff = PetscAbsScalar(y[i] - u[i]); 4812 tola = ts->atol; 4813 if (tola > 0.) { 4814 suma += PetscSqr(diff / tola); 4815 na_loc++; 4816 } 4817 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4818 if (tolr > 0.) { 4819 sumr += PetscSqr(diff / tolr); 4820 nr_loc++; 4821 } 4822 tol = tola + tolr; 4823 if (tol > 0.) { 4824 sum += PetscSqr(diff / tol); 4825 n_loc++; 4826 } 4827 } 4828 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 4829 } else { /* scalar atol, scalar rtol */ 4830 for (i = 0; i < n; i++) { 4831 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4832 diff = PetscAbsScalar(y[i] - u[i]); 4833 tola = ts->atol; 4834 if (tola > 0.) { 4835 suma += PetscSqr(diff / tola); 4836 na_loc++; 4837 } 4838 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4839 if (tolr > 0.) { 4840 sumr += PetscSqr(diff / tolr); 4841 nr_loc++; 4842 } 4843 tol = tola + tolr; 4844 if (tol > 0.) { 4845 sum += PetscSqr(diff / tol); 4846 n_loc++; 4847 } 4848 } 4849 } 4850 PetscCall(VecRestoreArrayRead(U, &u)); 4851 PetscCall(VecRestoreArrayRead(Y, &y)); 4852 4853 err_loc[0] = sum; 4854 err_loc[1] = suma; 4855 err_loc[2] = sumr; 4856 err_loc[3] = (PetscReal)n_loc; 4857 err_loc[4] = (PetscReal)na_loc; 4858 err_loc[5] = (PetscReal)nr_loc; 4859 4860 PetscCall(MPIU_Allreduce(err_loc, err_glb, 6, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ts))); 4861 4862 gsum = err_glb[0]; 4863 gsuma = err_glb[1]; 4864 gsumr = err_glb[2]; 4865 n_glb = err_glb[3]; 4866 na_glb = err_glb[4]; 4867 nr_glb = err_glb[5]; 4868 4869 *norm = 0.; 4870 if (n_glb > 0.) *norm = PetscSqrtReal(gsum / n_glb); 4871 *norma = 0.; 4872 if (na_glb > 0.) *norma = PetscSqrtReal(gsuma / na_glb); 4873 *normr = 0.; 4874 if (nr_glb > 0.) *normr = PetscSqrtReal(gsumr / nr_glb); 4875 4876 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 4877 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 4878 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 4879 PetscFunctionReturn(0); 4880 } 4881 4882 /*@ 4883 TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors 4884 4885 Collective on TS 4886 4887 Input Parameters: 4888 + ts - time stepping context 4889 . U - state vector, usually ts->vec_sol 4890 - Y - state vector to be compared to U 4891 4892 Output Parameters: 4893 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 4894 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 4895 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 4896 4897 Level: developer 4898 4899 .seealso: `TSErrorWeightedNorm()`, `TSErrorWeightedNorm2()` 4900 @*/ 4901 PetscErrorCode TSErrorWeightedNormInfinity(TS ts, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) { 4902 PetscInt i, n, N, rstart; 4903 const PetscScalar *u, *y; 4904 PetscReal max, gmax, maxa, gmaxa, maxr, gmaxr; 4905 PetscReal tol, tola, tolr, diff; 4906 PetscReal err_loc[3], err_glb[3]; 4907 4908 PetscFunctionBegin; 4909 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4910 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4911 PetscValidHeaderSpecific(Y, VEC_CLASSID, 3); 4912 PetscValidType(U, 2); 4913 PetscValidType(Y, 3); 4914 PetscCheckSameComm(U, 2, Y, 3); 4915 PetscValidRealPointer(norm, 4); 4916 PetscValidRealPointer(norma, 5); 4917 PetscValidRealPointer(normr, 6); 4918 PetscCheck(U != Y, PetscObjectComm((PetscObject)U), PETSC_ERR_ARG_IDN, "U and Y cannot be the same vector"); 4919 4920 PetscCall(VecGetSize(U, &N)); 4921 PetscCall(VecGetLocalSize(U, &n)); 4922 PetscCall(VecGetOwnershipRange(U, &rstart, NULL)); 4923 PetscCall(VecGetArrayRead(U, &u)); 4924 PetscCall(VecGetArrayRead(Y, &y)); 4925 4926 max = 0.; 4927 maxa = 0.; 4928 maxr = 0.; 4929 4930 if (ts->vatol && ts->vrtol) { /* vector atol, vector rtol */ 4931 const PetscScalar *atol, *rtol; 4932 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 4933 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 4934 4935 for (i = 0; i < n; i++) { 4936 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4937 diff = PetscAbsScalar(y[i] - u[i]); 4938 tola = PetscRealPart(atol[i]); 4939 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4940 tol = tola + tolr; 4941 if (tola > 0.) maxa = PetscMax(maxa, diff / tola); 4942 if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr); 4943 if (tol > 0.) max = PetscMax(max, diff / tol); 4944 } 4945 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 4946 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 4947 } else if (ts->vatol) { /* vector atol, scalar rtol */ 4948 const PetscScalar *atol; 4949 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 4950 for (i = 0; i < n; i++) { 4951 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4952 diff = PetscAbsScalar(y[i] - u[i]); 4953 tola = PetscRealPart(atol[i]); 4954 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4955 tol = tola + tolr; 4956 if (tola > 0.) maxa = PetscMax(maxa, diff / tola); 4957 if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr); 4958 if (tol > 0.) max = PetscMax(max, diff / tol); 4959 } 4960 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 4961 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 4962 const PetscScalar *rtol; 4963 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 4964 4965 for (i = 0; i < n; i++) { 4966 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4967 diff = PetscAbsScalar(y[i] - u[i]); 4968 tola = ts->atol; 4969 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4970 tol = tola + tolr; 4971 if (tola > 0.) maxa = PetscMax(maxa, diff / tola); 4972 if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr); 4973 if (tol > 0.) max = PetscMax(max, diff / tol); 4974 } 4975 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 4976 } else { /* scalar atol, scalar rtol */ 4977 4978 for (i = 0; i < n; i++) { 4979 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 4980 diff = PetscAbsScalar(y[i] - u[i]); 4981 tola = ts->atol; 4982 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 4983 tol = tola + tolr; 4984 if (tola > 0.) maxa = PetscMax(maxa, diff / tola); 4985 if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr); 4986 if (tol > 0.) max = PetscMax(max, diff / tol); 4987 } 4988 } 4989 PetscCall(VecRestoreArrayRead(U, &u)); 4990 PetscCall(VecRestoreArrayRead(Y, &y)); 4991 err_loc[0] = max; 4992 err_loc[1] = maxa; 4993 err_loc[2] = maxr; 4994 PetscCall(MPIU_Allreduce(err_loc, err_glb, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)ts))); 4995 gmax = err_glb[0]; 4996 gmaxa = err_glb[1]; 4997 gmaxr = err_glb[2]; 4998 4999 *norm = gmax; 5000 *norma = gmaxa; 5001 *normr = gmaxr; 5002 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5003 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5004 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5005 PetscFunctionReturn(0); 5006 } 5007 5008 /*@ 5009 TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances 5010 5011 Collective on TS 5012 5013 Input Parameters: 5014 + ts - time stepping context 5015 . U - state vector, usually ts->vec_sol 5016 . Y - state vector to be compared to U 5017 - wnormtype - norm type, either NORM_2 or NORM_INFINITY 5018 5019 Output Parameters: 5020 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5021 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5022 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5023 5024 Options Database Keys: 5025 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5026 5027 Level: developer 5028 5029 .seealso: `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()`, `TSErrorWeightedENorm` 5030 @*/ 5031 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) { 5032 PetscFunctionBegin; 5033 if (wnormtype == NORM_2) PetscCall(TSErrorWeightedNorm2(ts, U, Y, norm, norma, normr)); 5034 else if (wnormtype == NORM_INFINITY) PetscCall(TSErrorWeightedNormInfinity(ts, U, Y, norm, norma, normr)); 5035 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 5036 PetscFunctionReturn(0); 5037 } 5038 5039 /*@ 5040 TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances 5041 5042 Collective on TS 5043 5044 Input Parameters: 5045 + ts - time stepping context 5046 . E - error vector 5047 . U - state vector, usually ts->vec_sol 5048 - Y - state vector, previous time step 5049 5050 Output Parameters: 5051 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 5052 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 5053 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 5054 5055 Level: developer 5056 5057 .seealso: `TSErrorWeightedENorm()`, `TSErrorWeightedENormInfinity()` 5058 @*/ 5059 PetscErrorCode TSErrorWeightedENorm2(TS ts, Vec E, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) { 5060 PetscInt i, n, N, rstart; 5061 PetscInt n_loc, na_loc, nr_loc; 5062 PetscReal n_glb, na_glb, nr_glb; 5063 const PetscScalar *e, *u, *y; 5064 PetscReal err, sum, suma, sumr, gsum, gsuma, gsumr; 5065 PetscReal tol, tola, tolr; 5066 PetscReal err_loc[6], err_glb[6]; 5067 5068 PetscFunctionBegin; 5069 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5070 PetscValidHeaderSpecific(E, VEC_CLASSID, 2); 5071 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 5072 PetscValidHeaderSpecific(Y, VEC_CLASSID, 4); 5073 PetscValidType(E, 2); 5074 PetscValidType(U, 3); 5075 PetscValidType(Y, 4); 5076 PetscCheckSameComm(E, 2, U, 3); 5077 PetscCheckSameComm(U, 3, Y, 4); 5078 PetscValidRealPointer(norm, 5); 5079 PetscValidRealPointer(norma, 6); 5080 PetscValidRealPointer(normr, 7); 5081 5082 PetscCall(VecGetSize(E, &N)); 5083 PetscCall(VecGetLocalSize(E, &n)); 5084 PetscCall(VecGetOwnershipRange(E, &rstart, NULL)); 5085 PetscCall(VecGetArrayRead(E, &e)); 5086 PetscCall(VecGetArrayRead(U, &u)); 5087 PetscCall(VecGetArrayRead(Y, &y)); 5088 sum = 0.; 5089 n_loc = 0; 5090 suma = 0.; 5091 na_loc = 0; 5092 sumr = 0.; 5093 nr_loc = 0; 5094 if (ts->vatol && ts->vrtol) { 5095 const PetscScalar *atol, *rtol; 5096 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5097 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5098 for (i = 0; i < n; i++) { 5099 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5100 err = PetscAbsScalar(e[i]); 5101 tola = PetscRealPart(atol[i]); 5102 if (tola > 0.) { 5103 suma += PetscSqr(err / tola); 5104 na_loc++; 5105 } 5106 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5107 if (tolr > 0.) { 5108 sumr += PetscSqr(err / tolr); 5109 nr_loc++; 5110 } 5111 tol = tola + tolr; 5112 if (tol > 0.) { 5113 sum += PetscSqr(err / tol); 5114 n_loc++; 5115 } 5116 } 5117 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5118 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5119 } else if (ts->vatol) { /* vector atol, scalar rtol */ 5120 const PetscScalar *atol; 5121 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5122 for (i = 0; i < n; i++) { 5123 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5124 err = PetscAbsScalar(e[i]); 5125 tola = PetscRealPart(atol[i]); 5126 if (tola > 0.) { 5127 suma += PetscSqr(err / tola); 5128 na_loc++; 5129 } 5130 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5131 if (tolr > 0.) { 5132 sumr += PetscSqr(err / tolr); 5133 nr_loc++; 5134 } 5135 tol = tola + tolr; 5136 if (tol > 0.) { 5137 sum += PetscSqr(err / tol); 5138 n_loc++; 5139 } 5140 } 5141 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5142 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 5143 const PetscScalar *rtol; 5144 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5145 for (i = 0; i < n; i++) { 5146 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5147 err = PetscAbsScalar(e[i]); 5148 tola = ts->atol; 5149 if (tola > 0.) { 5150 suma += PetscSqr(err / tola); 5151 na_loc++; 5152 } 5153 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5154 if (tolr > 0.) { 5155 sumr += PetscSqr(err / tolr); 5156 nr_loc++; 5157 } 5158 tol = tola + tolr; 5159 if (tol > 0.) { 5160 sum += PetscSqr(err / tol); 5161 n_loc++; 5162 } 5163 } 5164 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5165 } else { /* scalar atol, scalar rtol */ 5166 for (i = 0; i < n; i++) { 5167 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5168 err = PetscAbsScalar(e[i]); 5169 tola = ts->atol; 5170 if (tola > 0.) { 5171 suma += PetscSqr(err / tola); 5172 na_loc++; 5173 } 5174 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5175 if (tolr > 0.) { 5176 sumr += PetscSqr(err / tolr); 5177 nr_loc++; 5178 } 5179 tol = tola + tolr; 5180 if (tol > 0.) { 5181 sum += PetscSqr(err / tol); 5182 n_loc++; 5183 } 5184 } 5185 } 5186 PetscCall(VecRestoreArrayRead(E, &e)); 5187 PetscCall(VecRestoreArrayRead(U, &u)); 5188 PetscCall(VecRestoreArrayRead(Y, &y)); 5189 5190 err_loc[0] = sum; 5191 err_loc[1] = suma; 5192 err_loc[2] = sumr; 5193 err_loc[3] = (PetscReal)n_loc; 5194 err_loc[4] = (PetscReal)na_loc; 5195 err_loc[5] = (PetscReal)nr_loc; 5196 5197 PetscCall(MPIU_Allreduce(err_loc, err_glb, 6, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ts))); 5198 5199 gsum = err_glb[0]; 5200 gsuma = err_glb[1]; 5201 gsumr = err_glb[2]; 5202 n_glb = err_glb[3]; 5203 na_glb = err_glb[4]; 5204 nr_glb = err_glb[5]; 5205 5206 *norm = 0.; 5207 if (n_glb > 0.) *norm = PetscSqrtReal(gsum / n_glb); 5208 *norma = 0.; 5209 if (na_glb > 0.) *norma = PetscSqrtReal(gsuma / na_glb); 5210 *normr = 0.; 5211 if (nr_glb > 0.) *normr = PetscSqrtReal(gsumr / nr_glb); 5212 5213 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5214 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5215 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5216 PetscFunctionReturn(0); 5217 } 5218 5219 /*@ 5220 TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances 5221 Collective on TS 5222 5223 Input Parameters: 5224 + ts - time stepping context 5225 . E - error vector 5226 . U - state vector, usually ts->vec_sol 5227 - Y - state vector, previous time step 5228 5229 Output Parameters: 5230 + norm - weighted norm, a value of 1.0 means that the error matches the tolerances 5231 . norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances 5232 - normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances 5233 5234 Level: developer 5235 5236 .seealso: `TSErrorWeightedENorm()`, `TSErrorWeightedENorm2()` 5237 @*/ 5238 PetscErrorCode TSErrorWeightedENormInfinity(TS ts, Vec E, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) { 5239 PetscInt i, n, N, rstart; 5240 const PetscScalar *e, *u, *y; 5241 PetscReal err, max, gmax, maxa, gmaxa, maxr, gmaxr; 5242 PetscReal tol, tola, tolr; 5243 PetscReal err_loc[3], err_glb[3]; 5244 5245 PetscFunctionBegin; 5246 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5247 PetscValidHeaderSpecific(E, VEC_CLASSID, 2); 5248 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 5249 PetscValidHeaderSpecific(Y, VEC_CLASSID, 4); 5250 PetscValidType(E, 2); 5251 PetscValidType(U, 3); 5252 PetscValidType(Y, 4); 5253 PetscCheckSameComm(E, 2, U, 3); 5254 PetscCheckSameComm(U, 3, Y, 4); 5255 PetscValidRealPointer(norm, 5); 5256 PetscValidRealPointer(norma, 6); 5257 PetscValidRealPointer(normr, 7); 5258 5259 PetscCall(VecGetSize(E, &N)); 5260 PetscCall(VecGetLocalSize(E, &n)); 5261 PetscCall(VecGetOwnershipRange(E, &rstart, NULL)); 5262 PetscCall(VecGetArrayRead(E, &e)); 5263 PetscCall(VecGetArrayRead(U, &u)); 5264 PetscCall(VecGetArrayRead(Y, &y)); 5265 5266 max = 0.; 5267 maxa = 0.; 5268 maxr = 0.; 5269 5270 if (ts->vatol && ts->vrtol) { /* vector atol, vector rtol */ 5271 const PetscScalar *atol, *rtol; 5272 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5273 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5274 5275 for (i = 0; i < n; i++) { 5276 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5277 err = PetscAbsScalar(e[i]); 5278 tola = PetscRealPart(atol[i]); 5279 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5280 tol = tola + tolr; 5281 if (tola > 0.) maxa = PetscMax(maxa, err / tola); 5282 if (tolr > 0.) maxr = PetscMax(maxr, err / tolr); 5283 if (tol > 0.) max = PetscMax(max, err / tol); 5284 } 5285 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5286 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5287 } else if (ts->vatol) { /* vector atol, scalar rtol */ 5288 const PetscScalar *atol; 5289 PetscCall(VecGetArrayRead(ts->vatol, &atol)); 5290 for (i = 0; i < n; i++) { 5291 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5292 err = PetscAbsScalar(e[i]); 5293 tola = PetscRealPart(atol[i]); 5294 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5295 tol = tola + tolr; 5296 if (tola > 0.) maxa = PetscMax(maxa, err / tola); 5297 if (tolr > 0.) maxr = PetscMax(maxr, err / tolr); 5298 if (tol > 0.) max = PetscMax(max, err / tol); 5299 } 5300 PetscCall(VecRestoreArrayRead(ts->vatol, &atol)); 5301 } else if (ts->vrtol) { /* scalar atol, vector rtol */ 5302 const PetscScalar *rtol; 5303 PetscCall(VecGetArrayRead(ts->vrtol, &rtol)); 5304 5305 for (i = 0; i < n; i++) { 5306 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5307 err = PetscAbsScalar(e[i]); 5308 tola = ts->atol; 5309 tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5310 tol = tola + tolr; 5311 if (tola > 0.) maxa = PetscMax(maxa, err / tola); 5312 if (tolr > 0.) maxr = PetscMax(maxr, err / tolr); 5313 if (tol > 0.) max = PetscMax(max, err / tol); 5314 } 5315 PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol)); 5316 } else { /* scalar atol, scalar rtol */ 5317 5318 for (i = 0; i < n; i++) { 5319 SkipSmallValue(y[i], u[i], ts->adapt->ignore_max); 5320 err = PetscAbsScalar(e[i]); 5321 tola = ts->atol; 5322 tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i])); 5323 tol = tola + tolr; 5324 if (tola > 0.) maxa = PetscMax(maxa, err / tola); 5325 if (tolr > 0.) maxr = PetscMax(maxr, err / tolr); 5326 if (tol > 0.) max = PetscMax(max, err / tol); 5327 } 5328 } 5329 PetscCall(VecRestoreArrayRead(E, &e)); 5330 PetscCall(VecRestoreArrayRead(U, &u)); 5331 PetscCall(VecRestoreArrayRead(Y, &y)); 5332 err_loc[0] = max; 5333 err_loc[1] = maxa; 5334 err_loc[2] = maxr; 5335 PetscCall(MPIU_Allreduce(err_loc, err_glb, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)ts))); 5336 gmax = err_glb[0]; 5337 gmaxa = err_glb[1]; 5338 gmaxr = err_glb[2]; 5339 5340 *norm = gmax; 5341 *norma = gmaxa; 5342 *normr = gmaxr; 5343 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5344 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5345 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5346 PetscFunctionReturn(0); 5347 } 5348 5349 /*@ 5350 TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances 5351 5352 Collective on TS 5353 5354 Input Parameters: 5355 + ts - time stepping context 5356 . E - error vector 5357 . U - state vector, usually ts->vec_sol 5358 . Y - state vector, previous time step 5359 - wnormtype - norm type, either NORM_2 or NORM_INFINITY 5360 5361 Output Parameters: 5362 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5363 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5364 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5365 5366 Options Database Keys: 5367 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5368 5369 Level: developer 5370 5371 .seealso: `TSErrorWeightedENormInfinity()`, `TSErrorWeightedENorm2()`, `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()` 5372 @*/ 5373 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) { 5374 PetscFunctionBegin; 5375 if (wnormtype == NORM_2) PetscCall(TSErrorWeightedENorm2(ts, E, U, Y, norm, norma, normr)); 5376 else if (wnormtype == NORM_INFINITY) PetscCall(TSErrorWeightedENormInfinity(ts, E, U, Y, norm, norma, normr)); 5377 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 5378 PetscFunctionReturn(0); 5379 } 5380 5381 /*@ 5382 TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler 5383 5384 Logically Collective on TS 5385 5386 Input Parameters: 5387 + ts - time stepping context 5388 - cfltime - maximum stable time step if using forward Euler (value can be different on each process) 5389 5390 Note: 5391 After calling this function, the global CFL time can be obtained by calling TSGetCFLTime() 5392 5393 Level: intermediate 5394 5395 .seealso: `TSGetCFLTime()`, `TSADAPTCFL` 5396 @*/ 5397 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime) { 5398 PetscFunctionBegin; 5399 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5400 ts->cfltime_local = cfltime; 5401 ts->cfltime = -1.; 5402 PetscFunctionReturn(0); 5403 } 5404 5405 /*@ 5406 TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler 5407 5408 Collective on TS 5409 5410 Input Parameter: 5411 . ts - time stepping context 5412 5413 Output Parameter: 5414 . cfltime - maximum stable time step for forward Euler 5415 5416 Level: advanced 5417 5418 .seealso: `TSSetCFLTimeLocal()` 5419 @*/ 5420 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime) { 5421 PetscFunctionBegin; 5422 if (ts->cfltime < 0) PetscCall(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts))); 5423 *cfltime = ts->cfltime; 5424 PetscFunctionReturn(0); 5425 } 5426 5427 /*@ 5428 TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu 5429 5430 Input Parameters: 5431 + ts - the TS context. 5432 . xl - lower bound. 5433 - xu - upper bound. 5434 5435 Notes: 5436 If this routine is not called then the lower and upper bounds are set to 5437 PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp(). 5438 5439 Level: advanced 5440 5441 @*/ 5442 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) { 5443 SNES snes; 5444 5445 PetscFunctionBegin; 5446 PetscCall(TSGetSNES(ts, &snes)); 5447 PetscCall(SNESVISetVariableBounds(snes, xl, xu)); 5448 PetscFunctionReturn(0); 5449 } 5450 5451 /*@ 5452 TSComputeLinearStability - computes the linear stability function at a point 5453 5454 Collective on TS 5455 5456 Input Parameters: 5457 + ts - the TS context 5458 - xr,xi - real and imaginary part of input arguments 5459 5460 Output Parameters: 5461 . yr,yi - real and imaginary part of function value 5462 5463 Level: developer 5464 5465 .seealso: `TSSetRHSFunction()`, `TSComputeIFunction()` 5466 @*/ 5467 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) { 5468 PetscFunctionBegin; 5469 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5470 PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi); 5471 PetscFunctionReturn(0); 5472 } 5473 5474 /*@ 5475 TSRestartStep - Flags the solver to restart the next step 5476 5477 Collective on TS 5478 5479 Input Parameter: 5480 . ts - the TS context obtained from TSCreate() 5481 5482 Level: advanced 5483 5484 Notes: 5485 Multistep methods like BDF or Runge-Kutta methods with FSAL property require restarting the solver in the event of 5486 discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution 5487 vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For 5488 the sake of correctness and maximum safety, users are expected to call TSRestart() whenever they introduce 5489 discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with 5490 discontinuous source terms). 5491 5492 .seealso: `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()` 5493 @*/ 5494 PetscErrorCode TSRestartStep(TS ts) { 5495 PetscFunctionBegin; 5496 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5497 ts->steprestart = PETSC_TRUE; 5498 PetscFunctionReturn(0); 5499 } 5500 5501 /*@ 5502 TSRollBack - Rolls back one time step 5503 5504 Collective on TS 5505 5506 Input Parameter: 5507 . ts - the TS context obtained from TSCreate() 5508 5509 Level: advanced 5510 5511 .seealso: `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()` 5512 @*/ 5513 PetscErrorCode TSRollBack(TS ts) { 5514 PetscFunctionBegin; 5515 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5516 PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called"); 5517 PetscUseTypeMethod(ts, rollback); 5518 ts->time_step = ts->ptime - ts->ptime_prev; 5519 ts->ptime = ts->ptime_prev; 5520 ts->ptime_prev = ts->ptime_prev_rollback; 5521 ts->steps--; 5522 ts->steprollback = PETSC_TRUE; 5523 PetscFunctionReturn(0); 5524 } 5525 5526 /*@ 5527 TSGetStages - Get the number of stages and stage values 5528 5529 Input Parameter: 5530 . ts - the TS context obtained from TSCreate() 5531 5532 Output Parameters: 5533 + ns - the number of stages 5534 - Y - the current stage vectors 5535 5536 Level: advanced 5537 5538 Notes: Both ns and Y can be NULL. 5539 5540 .seealso: `TSCreate()` 5541 @*/ 5542 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y) { 5543 PetscFunctionBegin; 5544 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5545 if (ns) PetscValidIntPointer(ns, 2); 5546 if (Y) PetscValidPointer(Y, 3); 5547 if (!ts->ops->getstages) { 5548 if (ns) *ns = 0; 5549 if (Y) *Y = NULL; 5550 } else PetscUseTypeMethod(ts, getstages, ns, Y); 5551 PetscFunctionReturn(0); 5552 } 5553 5554 /*@C 5555 TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity. 5556 5557 Collective on SNES 5558 5559 Input Parameters: 5560 + ts - the TS context 5561 . t - current timestep 5562 . U - state vector 5563 . Udot - time derivative of state vector 5564 . shift - shift to apply, see note below 5565 - ctx - an optional user context 5566 5567 Output Parameters: 5568 + J - Jacobian matrix (not altered in this routine) 5569 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J) 5570 5571 Level: intermediate 5572 5573 Notes: 5574 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 5575 5576 dF/dU + shift*dF/dUdot 5577 5578 Most users should not need to explicitly call this routine, as it 5579 is used internally within the nonlinear solvers. 5580 5581 This will first try to get the coloring from the DM. If the DM type has no coloring 5582 routine, then it will try to get the coloring from the matrix. This requires that the 5583 matrix have nonzero entries precomputed. 5584 5585 .seealso: `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5586 @*/ 5587 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx) { 5588 SNES snes; 5589 MatFDColoring color; 5590 PetscBool hascolor, matcolor = PETSC_FALSE; 5591 5592 PetscFunctionBegin; 5593 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL)); 5594 PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color)); 5595 if (!color) { 5596 DM dm; 5597 ISColoring iscoloring; 5598 5599 PetscCall(TSGetDM(ts, &dm)); 5600 PetscCall(DMHasColoring(dm, &hascolor)); 5601 if (hascolor && !matcolor) { 5602 PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 5603 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5604 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5605 PetscCall(MatFDColoringSetFromOptions(color)); 5606 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5607 PetscCall(ISColoringDestroy(&iscoloring)); 5608 } else { 5609 MatColoring mc; 5610 5611 PetscCall(MatColoringCreate(B, &mc)); 5612 PetscCall(MatColoringSetDistance(mc, 2)); 5613 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5614 PetscCall(MatColoringSetFromOptions(mc)); 5615 PetscCall(MatColoringApply(mc, &iscoloring)); 5616 PetscCall(MatColoringDestroy(&mc)); 5617 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5618 PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts)); 5619 PetscCall(MatFDColoringSetFromOptions(color)); 5620 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5621 PetscCall(ISColoringDestroy(&iscoloring)); 5622 } 5623 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color)); 5624 PetscCall(PetscObjectDereference((PetscObject)color)); 5625 } 5626 PetscCall(TSGetSNES(ts, &snes)); 5627 PetscCall(MatFDColoringApply(B, color, U, snes)); 5628 if (J != B) { 5629 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 5630 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 5631 } 5632 PetscFunctionReturn(0); 5633 } 5634 5635 /*@ 5636 TSSetFunctionDomainError - Set a function that tests if the current state vector is valid 5637 5638 Input Parameters: 5639 + ts - the TS context 5640 - func - function called within TSFunctionDomainError 5641 5642 Calling sequence of func: 5643 $ PetscErrorCode func(TS ts,PetscReal time,Vec state,PetscBool reject) 5644 5645 + ts - the TS context 5646 . time - the current time (of the stage) 5647 . state - the state to check if it is valid 5648 - reject - (output parameter) PETSC_FALSE if the state is acceptable, PETSC_TRUE if not acceptable 5649 5650 Level: intermediate 5651 5652 Notes: 5653 If an implicit ODE solver is being used then, in addition to providing this routine, the 5654 user's code should call SNESSetFunctionDomainError() when domain errors occur during 5655 function evaluations where the functions are provided by TSSetIFunction() or TSSetRHSFunction(). 5656 Use TSGetSNES() to obtain the SNES object 5657 5658 Developer Notes: 5659 The naming of this function is inconsistent with the SNESSetFunctionDomainError() 5660 since one takes a function pointer and the other does not. 5661 5662 .seealso: `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()` 5663 @*/ 5664 5665 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS, PetscReal, Vec, PetscBool *)) { 5666 PetscFunctionBegin; 5667 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5668 ts->functiondomainerror = func; 5669 PetscFunctionReturn(0); 5670 } 5671 5672 /*@ 5673 TSFunctionDomainError - Checks if the current state is valid 5674 5675 Input Parameters: 5676 + ts - the TS context 5677 . stagetime - time of the simulation 5678 - Y - state vector to check. 5679 5680 Output Parameter: 5681 . accept - Set to PETSC_FALSE if the current state vector is valid. 5682 5683 Note: 5684 This function is called by the TS integration routines and calls the user provided function (set with TSSetFunctionDomainError()) 5685 to check if the current state is valid. 5686 5687 Level: developer 5688 5689 .seealso: `TSSetFunctionDomainError()` 5690 @*/ 5691 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept) { 5692 PetscFunctionBegin; 5693 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5694 *accept = PETSC_TRUE; 5695 if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept)); 5696 PetscFunctionReturn(0); 5697 } 5698 5699 /*@C 5700 TSClone - This function clones a time step object. 5701 5702 Collective 5703 5704 Input Parameter: 5705 . tsin - The input TS 5706 5707 Output Parameter: 5708 . tsout - The output TS (cloned) 5709 5710 Notes: 5711 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. 5712 5713 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); 5714 5715 Level: developer 5716 5717 .seealso: `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()` 5718 @*/ 5719 PetscErrorCode TSClone(TS tsin, TS *tsout) { 5720 TS t; 5721 SNES snes_start; 5722 DM dm; 5723 TSType type; 5724 5725 PetscFunctionBegin; 5726 PetscValidPointer(tsin, 1); 5727 *tsout = NULL; 5728 5729 PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView)); 5730 5731 /* General TS description */ 5732 t->numbermonitors = 0; 5733 t->monitorFrequency = 1; 5734 t->setupcalled = 0; 5735 t->ksp_its = 0; 5736 t->snes_its = 0; 5737 t->nwork = 0; 5738 t->rhsjacobian.time = PETSC_MIN_REAL; 5739 t->rhsjacobian.scale = 1.; 5740 t->ijacobian.shift = 1.; 5741 5742 PetscCall(TSGetSNES(tsin, &snes_start)); 5743 PetscCall(TSSetSNES(t, snes_start)); 5744 5745 PetscCall(TSGetDM(tsin, &dm)); 5746 PetscCall(TSSetDM(t, dm)); 5747 5748 t->adapt = tsin->adapt; 5749 PetscCall(PetscObjectReference((PetscObject)t->adapt)); 5750 5751 t->trajectory = tsin->trajectory; 5752 PetscCall(PetscObjectReference((PetscObject)t->trajectory)); 5753 5754 t->event = tsin->event; 5755 if (t->event) t->event->refct++; 5756 5757 t->problem_type = tsin->problem_type; 5758 t->ptime = tsin->ptime; 5759 t->ptime_prev = tsin->ptime_prev; 5760 t->time_step = tsin->time_step; 5761 t->max_time = tsin->max_time; 5762 t->steps = tsin->steps; 5763 t->max_steps = tsin->max_steps; 5764 t->equation_type = tsin->equation_type; 5765 t->atol = tsin->atol; 5766 t->rtol = tsin->rtol; 5767 t->max_snes_failures = tsin->max_snes_failures; 5768 t->max_reject = tsin->max_reject; 5769 t->errorifstepfailed = tsin->errorifstepfailed; 5770 5771 PetscCall(TSGetType(tsin, &type)); 5772 PetscCall(TSSetType(t, type)); 5773 5774 t->vec_sol = NULL; 5775 5776 t->cfltime = tsin->cfltime; 5777 t->cfltime_local = tsin->cfltime_local; 5778 t->exact_final_time = tsin->exact_final_time; 5779 5780 PetscCall(PetscMemcpy(t->ops, tsin->ops, sizeof(struct _TSOps))); 5781 5782 if (((PetscObject)tsin)->fortran_func_pointers) { 5783 PetscInt i; 5784 PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers)); 5785 for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i]; 5786 } 5787 *tsout = t; 5788 PetscFunctionReturn(0); 5789 } 5790 5791 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y) { 5792 TS ts = (TS)ctx; 5793 5794 PetscFunctionBegin; 5795 PetscCall(TSComputeRHSFunction(ts, 0, x, y)); 5796 PetscFunctionReturn(0); 5797 } 5798 5799 /*@ 5800 TSRHSJacobianTest - Compares the multiply routine provided to the MATSHELL with differencing on the TS given RHS function. 5801 5802 Logically Collective on TS 5803 5804 Input Parameters: 5805 TS - the time stepping routine 5806 5807 Output Parameter: 5808 . flg - PETSC_TRUE if the multiply is likely correct 5809 5810 Options Database: 5811 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator 5812 5813 Level: advanced 5814 5815 Notes: 5816 This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian 5817 5818 .seealso: `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()` 5819 @*/ 5820 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg) { 5821 Mat J, B; 5822 TSRHSJacobian func; 5823 void *ctx; 5824 5825 PetscFunctionBegin; 5826 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5827 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5828 PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5829 PetscFunctionReturn(0); 5830 } 5831 5832 /*@C 5833 TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the MATSHELL with differencing on the TS given RHS function. 5834 5835 Logically Collective on TS 5836 5837 Input Parameters: 5838 TS - the time stepping routine 5839 5840 Output Parameter: 5841 . flg - PETSC_TRUE if the multiply is likely correct 5842 5843 Options Database: 5844 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator 5845 5846 Notes: 5847 This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian 5848 5849 Level: advanced 5850 5851 .seealso: `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()` 5852 @*/ 5853 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg) { 5854 Mat J, B; 5855 void *ctx; 5856 TSRHSJacobian func; 5857 5858 PetscFunctionBegin; 5859 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5860 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5861 PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5862 PetscFunctionReturn(0); 5863 } 5864 5865 /*@ 5866 TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used. 5867 5868 Logically collective 5869 5870 Input Parameters: 5871 + ts - timestepping context 5872 - use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used 5873 5874 Options Database: 5875 . -ts_use_splitrhsfunction - <true,false> 5876 5877 Notes: 5878 This is only useful for multirate methods 5879 5880 Level: intermediate 5881 5882 .seealso: `TSGetUseSplitRHSFunction()` 5883 @*/ 5884 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) { 5885 PetscFunctionBegin; 5886 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5887 ts->use_splitrhsfunction = use_splitrhsfunction; 5888 PetscFunctionReturn(0); 5889 } 5890 5891 /*@ 5892 TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used. 5893 5894 Not collective 5895 5896 Input Parameter: 5897 . ts - timestepping context 5898 5899 Output Parameter: 5900 . use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used 5901 5902 Level: intermediate 5903 5904 .seealso: `TSSetUseSplitRHSFunction()` 5905 @*/ 5906 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) { 5907 PetscFunctionBegin; 5908 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5909 *use_splitrhsfunction = ts->use_splitrhsfunction; 5910 PetscFunctionReturn(0); 5911 } 5912 5913 /*@ 5914 TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix. 5915 5916 Logically Collective on ts 5917 5918 Input Parameters: 5919 + ts - the time-stepper 5920 - str - the structure (the default is UNKNOWN_NONZERO_PATTERN) 5921 5922 Level: intermediate 5923 5924 Notes: 5925 When the relationship between the nonzero structures is known and supplied the solution process can be much faster 5926 5927 .seealso: `MatAXPY()`, `MatStructure` 5928 @*/ 5929 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str) { 5930 PetscFunctionBegin; 5931 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5932 ts->axpy_pattern = str; 5933 PetscFunctionReturn(0); 5934 } 5935 5936 /*@ 5937 TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested. 5938 5939 Collective on ts 5940 5941 Input Parameters: 5942 + ts - the time-stepper 5943 . n - number of the time points (>=2) 5944 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively. 5945 5946 Options Database Keys: 5947 . -ts_time_span <t0,...tf> - Sets the time span 5948 5949 Level: beginner 5950 5951 Notes: 5952 The elements in tspan must be all increasing. They correspond to the intermediate points for time integration. 5953 TS_EXACTFINALTIME_MATCHSTEP must be used to make the last time step in each sub-interval match the intermediate points specified. 5954 The intermediate solutions are saved in a vector array that can be accessed with TSGetSolutions(). Thus using time span may 5955 pressure the memory system when using a large number of span points. 5956 5957 .seealso: `TSGetTimeSpan()`, `TSGetSolutions()` 5958 @*/ 5959 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times) { 5960 PetscFunctionBegin; 5961 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5962 PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n); 5963 if (ts->tspan && n != ts->tspan->num_span_times) { 5964 PetscCall(PetscFree(ts->tspan->span_times)); 5965 PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol)); 5966 PetscCall(PetscMalloc1(n, &ts->tspan->span_times)); 5967 } 5968 if (!ts->tspan) { 5969 TSTimeSpan tspan; 5970 PetscCall(PetscNew(&tspan)); 5971 PetscCall(PetscMalloc1(n, &tspan->span_times)); 5972 tspan->reltol = 1e-6; 5973 tspan->abstol = 10 * PETSC_MACHINE_EPSILON; 5974 ts->tspan = tspan; 5975 } 5976 ts->tspan->num_span_times = n; 5977 PetscCall(PetscArraycpy(ts->tspan->span_times, span_times, n)); 5978 PetscCall(TSSetTime(ts, ts->tspan->span_times[0])); 5979 PetscCall(TSSetMaxTime(ts, ts->tspan->span_times[n - 1])); 5980 PetscFunctionReturn(0); 5981 } 5982 5983 /*@C 5984 TSGetTimeSpan - gets the time span. 5985 5986 Not Collective 5987 5988 Input Parameter: 5989 . ts - the time-stepper 5990 5991 Output Parameters: 5992 + n - number of the time points (>=2) 5993 - 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. 5994 5995 Level: beginner 5996 Notes: Both n and span_times can be NULL. 5997 5998 .seealso: `TSSetTimeSpan()`, `TSGetSolutions()` 5999 @*/ 6000 PetscErrorCode TSGetTimeSpan(TS ts, PetscInt *n, const PetscReal **span_times) { 6001 PetscFunctionBegin; 6002 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6003 if (n) PetscValidIntPointer(n, 2); 6004 if (span_times) PetscValidPointer(span_times, 3); 6005 if (!ts->tspan) { 6006 if (n) *n = 0; 6007 if (span_times) *span_times = NULL; 6008 } else { 6009 if (n) *n = ts->tspan->num_span_times; 6010 if (span_times) *span_times = ts->tspan->span_times; 6011 } 6012 PetscFunctionReturn(0); 6013 } 6014 6015 /*@ 6016 TSGetTimeSpanSolutions - Get the number of solutions and the solutions at the time points specified by the time span. 6017 6018 Input Parameter: 6019 . ts - the TS context obtained from TSCreate() 6020 6021 Output Parameters: 6022 + nsol - the number of solutions 6023 - Sols - the solution vectors 6024 6025 Level: beginner 6026 6027 Notes: 6028 Both nsol and Sols can be NULL. 6029 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. 6030 6031 .seealso: `TSSetTimeSpan()` 6032 @*/ 6033 PetscErrorCode TSGetTimeSpanSolutions(TS ts, PetscInt *nsol, Vec **Sols) { 6034 PetscFunctionBegin; 6035 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6036 if (nsol) PetscValidIntPointer(nsol, 2); 6037 if (Sols) PetscValidPointer(Sols, 3); 6038 if (!ts->tspan) { 6039 if (nsol) *nsol = 0; 6040 if (Sols) *Sols = NULL; 6041 } else { 6042 if (nsol) *nsol = ts->tspan->spanctr; 6043 if (Sols) *Sols = ts->tspan->vecs_sol; 6044 } 6045 PetscFunctionReturn(0); 6046 } 6047