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