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