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, PetscCtx))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, PetscCtx 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, PetscCtx 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, PetscCtx 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, PetscCtx 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, PetscCtx 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, PetscCtxRt 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, PetscCtxRt 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, PetscCtx 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, PetscCtx 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, PetscCtxRt 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, PetscCtx 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, PetscCtxRt 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, PetscCtx 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, PetscCtx 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 or a `PetscObject`. Declare `ctx` with 2065 .vb 2066 type(tUsertype), pointer :: ctx 2067 .ve 2068 2069 .seealso: [](ch_ts), `TS`, `TSSetApplicationContext()` 2070 @*/ 2071 PetscErrorCode TSGetApplicationContext(TS ts, PetscCtxRt ctx) 2072 { 2073 PetscFunctionBegin; 2074 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2075 *(void **)ctx = ts->ctx; 2076 PetscFunctionReturn(PETSC_SUCCESS); 2077 } 2078 2079 /*@ 2080 TSGetStepNumber - Gets the number of time steps completed. 2081 2082 Not Collective 2083 2084 Input Parameter: 2085 . ts - the `TS` context obtained from `TSCreate()` 2086 2087 Output Parameter: 2088 . steps - number of steps completed so far 2089 2090 Level: intermediate 2091 2092 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetTimeStep()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()` 2093 @*/ 2094 PetscErrorCode TSGetStepNumber(TS ts, PetscInt *steps) 2095 { 2096 PetscFunctionBegin; 2097 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2098 PetscAssertPointer(steps, 2); 2099 *steps = ts->steps; 2100 PetscFunctionReturn(PETSC_SUCCESS); 2101 } 2102 2103 /*@ 2104 TSSetStepNumber - Sets the number of steps completed. 2105 2106 Logically Collective 2107 2108 Input Parameters: 2109 + ts - the `TS` context 2110 - steps - number of steps completed so far 2111 2112 Level: developer 2113 2114 Note: 2115 For most uses of the `TS` solvers the user need not explicitly call 2116 `TSSetStepNumber()`, as the step counter is appropriately updated in 2117 `TSSolve()`/`TSStep()`/`TSRollBack()`. Power users may call this routine to 2118 reinitialize timestepping by setting the step counter to zero (and time 2119 to the initial time) to solve a similar problem with different initial 2120 conditions or parameters. Other possible use case is to continue 2121 timestepping from a previously interrupted run in such a way that `TS` 2122 monitors will be called with a initial nonzero step counter. 2123 2124 .seealso: [](ch_ts), `TS`, `TSGetStepNumber()`, `TSSetTime()`, `TSSetTimeStep()`, `TSSetSolution()` 2125 @*/ 2126 PetscErrorCode TSSetStepNumber(TS ts, PetscInt steps) 2127 { 2128 PetscFunctionBegin; 2129 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2130 PetscValidLogicalCollectiveInt(ts, steps, 2); 2131 PetscCheck(steps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Step number must be non-negative"); 2132 ts->steps = steps; 2133 PetscFunctionReturn(PETSC_SUCCESS); 2134 } 2135 2136 /*@ 2137 TSSetTimeStep - Allows one to reset the timestep at any time. 2138 2139 Logically Collective 2140 2141 Input Parameters: 2142 + ts - the `TS` context obtained from `TSCreate()` 2143 - time_step - the size of the timestep 2144 2145 Options Database Key: 2146 . -ts_time_step <dt> - provide the initial time step 2147 2148 Level: intermediate 2149 2150 Notes: 2151 This is only a suggestion, the actual initial time step used may differ 2152 2153 If this is called after `TSSetUp()`, it will not change the initial time step value printed by `TSView()` 2154 2155 .seealso: [](ch_ts), `TS`, `TSPSEUDO`, `TSGetTimeStep()`, `TSSetTime()` 2156 @*/ 2157 PetscErrorCode TSSetTimeStep(TS ts, PetscReal time_step) 2158 { 2159 PetscFunctionBegin; 2160 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2161 PetscValidLogicalCollectiveReal(ts, time_step, 2); 2162 ts->time_step = time_step; 2163 if (ts->setupcalled == PETSC_FALSE) ts->initial_time_step = time_step; 2164 PetscFunctionReturn(PETSC_SUCCESS); 2165 } 2166 2167 /*@ 2168 TSSetExactFinalTime - Determines whether to adapt the final time step to 2169 match the exact final time, to interpolate the solution to the exact final time, 2170 or to just return at the final time `TS` computed (which may be slightly larger 2171 than the requested final time). 2172 2173 Logically Collective 2174 2175 Input Parameters: 2176 + ts - the time-step context 2177 - eftopt - exact final time option 2178 .vb 2179 TS_EXACTFINALTIME_STEPOVER - Don't do anything if final time is exceeded, just use it 2180 TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time if the final time is exceeded 2181 TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to ensure the computed final time exactly equals the requested final time 2182 .ve 2183 2184 Options Database Key: 2185 . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step approach at runtime 2186 2187 Level: beginner 2188 2189 Note: 2190 If you use the option `TS_EXACTFINALTIME_STEPOVER` the solution may be at a very different time 2191 then the final time you selected. 2192 2193 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSGetExactFinalTime()` 2194 @*/ 2195 PetscErrorCode TSSetExactFinalTime(TS ts, TSExactFinalTimeOption eftopt) 2196 { 2197 PetscFunctionBegin; 2198 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2199 PetscValidLogicalCollectiveEnum(ts, eftopt, 2); 2200 ts->exact_final_time = eftopt; 2201 PetscFunctionReturn(PETSC_SUCCESS); 2202 } 2203 2204 /*@ 2205 TSGetExactFinalTime - Gets the exact final time option set with `TSSetExactFinalTime()` 2206 2207 Not Collective 2208 2209 Input Parameter: 2210 . ts - the `TS` context 2211 2212 Output Parameter: 2213 . eftopt - exact final time option 2214 2215 Level: beginner 2216 2217 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSSetExactFinalTime()` 2218 @*/ 2219 PetscErrorCode TSGetExactFinalTime(TS ts, TSExactFinalTimeOption *eftopt) 2220 { 2221 PetscFunctionBegin; 2222 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2223 PetscAssertPointer(eftopt, 2); 2224 *eftopt = ts->exact_final_time; 2225 PetscFunctionReturn(PETSC_SUCCESS); 2226 } 2227 2228 /*@ 2229 TSGetTimeStep - Gets the current timestep size. 2230 2231 Not Collective 2232 2233 Input Parameter: 2234 . ts - the `TS` context obtained from `TSCreate()` 2235 2236 Output Parameter: 2237 . dt - the current timestep size 2238 2239 Level: intermediate 2240 2241 .seealso: [](ch_ts), `TS`, `TSSetTimeStep()`, `TSGetTime()` 2242 @*/ 2243 PetscErrorCode TSGetTimeStep(TS ts, PetscReal *dt) 2244 { 2245 PetscFunctionBegin; 2246 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2247 PetscAssertPointer(dt, 2); 2248 *dt = ts->time_step; 2249 PetscFunctionReturn(PETSC_SUCCESS); 2250 } 2251 2252 /*@ 2253 TSGetSolution - Returns the solution at the present timestep. It 2254 is valid to call this routine inside the function that you are evaluating 2255 in order to move to the new timestep. This vector not changed until 2256 the solution at the next timestep has been calculated. 2257 2258 Not Collective, but v returned is parallel if ts is parallel 2259 2260 Input Parameter: 2261 . ts - the `TS` context obtained from `TSCreate()` 2262 2263 Output Parameter: 2264 . v - the vector containing the solution 2265 2266 Level: intermediate 2267 2268 Note: 2269 If you used `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`); this does not return the solution at the requested 2270 final time. It returns the solution at the next timestep. 2271 2272 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()` 2273 @*/ 2274 PetscErrorCode TSGetSolution(TS ts, Vec *v) 2275 { 2276 PetscFunctionBegin; 2277 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2278 PetscAssertPointer(v, 2); 2279 *v = ts->vec_sol; 2280 PetscFunctionReturn(PETSC_SUCCESS); 2281 } 2282 2283 /*@ 2284 TSGetSolutionComponents - Returns any solution components at the present 2285 timestep, if available for the time integration method being used. 2286 Solution components are quantities that share the same size and 2287 structure as the solution vector. 2288 2289 Not Collective, but v returned is parallel if ts is parallel 2290 2291 Input Parameters: 2292 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2293 . n - If v is `NULL`, then the number of solution components is 2294 returned through n, else the n-th solution component is 2295 returned in v. 2296 - v - the vector containing the n-th solution component 2297 (may be `NULL` to use this function to find out 2298 the number of solutions components). 2299 2300 Level: advanced 2301 2302 .seealso: [](ch_ts), `TS`, `TSGetSolution()` 2303 @*/ 2304 PetscErrorCode TSGetSolutionComponents(TS ts, PetscInt *n, Vec *v) 2305 { 2306 PetscFunctionBegin; 2307 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2308 if (!ts->ops->getsolutioncomponents) *n = 0; 2309 else PetscUseTypeMethod(ts, getsolutioncomponents, n, v); 2310 PetscFunctionReturn(PETSC_SUCCESS); 2311 } 2312 2313 /*@ 2314 TSGetAuxSolution - Returns an auxiliary solution at the present 2315 timestep, if available for the time integration method being used. 2316 2317 Not Collective, but v returned is parallel if ts is parallel 2318 2319 Input Parameters: 2320 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2321 - v - the vector containing the auxiliary solution 2322 2323 Level: intermediate 2324 2325 .seealso: [](ch_ts), `TS`, `TSGetSolution()` 2326 @*/ 2327 PetscErrorCode TSGetAuxSolution(TS ts, Vec *v) 2328 { 2329 PetscFunctionBegin; 2330 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2331 if (ts->ops->getauxsolution) PetscUseTypeMethod(ts, getauxsolution, v); 2332 else PetscCall(VecZeroEntries(*v)); 2333 PetscFunctionReturn(PETSC_SUCCESS); 2334 } 2335 2336 /*@ 2337 TSGetTimeError - Returns the estimated error vector, if the chosen 2338 `TSType` has an error estimation functionality and `TSSetTimeError()` was called 2339 2340 Not Collective, but v returned is parallel if ts is parallel 2341 2342 Input Parameters: 2343 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2344 . n - current estimate (n=0) or previous one (n=-1) 2345 - v - the vector containing the error (same size as the solution). 2346 2347 Level: intermediate 2348 2349 Note: 2350 MUST call after `TSSetUp()` 2351 2352 .seealso: [](ch_ts), `TSGetSolution()`, `TSSetTimeError()` 2353 @*/ 2354 PetscErrorCode TSGetTimeError(TS ts, PetscInt n, Vec *v) 2355 { 2356 PetscFunctionBegin; 2357 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2358 if (ts->ops->gettimeerror) PetscUseTypeMethod(ts, gettimeerror, n, v); 2359 else PetscCall(VecZeroEntries(*v)); 2360 PetscFunctionReturn(PETSC_SUCCESS); 2361 } 2362 2363 /*@ 2364 TSSetTimeError - Sets the estimated error vector, if the chosen 2365 `TSType` has an error estimation functionality. This can be used 2366 to restart such a time integrator with a given error vector. 2367 2368 Not Collective, but v returned is parallel if ts is parallel 2369 2370 Input Parameters: 2371 + ts - the `TS` context obtained from `TSCreate()` (input parameter). 2372 - v - the vector containing the error (same size as the solution). 2373 2374 Level: intermediate 2375 2376 .seealso: [](ch_ts), `TS`, `TSSetSolution()`, `TSGetTimeError()` 2377 @*/ 2378 PetscErrorCode TSSetTimeError(TS ts, Vec v) 2379 { 2380 PetscFunctionBegin; 2381 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2382 PetscCheck(ts->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetUp() first"); 2383 PetscTryTypeMethod(ts, settimeerror, v); 2384 PetscFunctionReturn(PETSC_SUCCESS); 2385 } 2386 2387 /* ----- Routines to initialize and destroy a timestepper ---- */ 2388 /*@ 2389 TSSetProblemType - Sets the type of problem to be solved. 2390 2391 Not collective 2392 2393 Input Parameters: 2394 + ts - The `TS` 2395 - type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms 2396 .vb 2397 U_t - A U = 0 (linear) 2398 U_t - A(t) U = 0 (linear) 2399 F(t,U,U_t) = 0 (nonlinear) 2400 .ve 2401 2402 Level: beginner 2403 2404 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS` 2405 @*/ 2406 PetscErrorCode TSSetProblemType(TS ts, TSProblemType type) 2407 { 2408 PetscFunctionBegin; 2409 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2410 ts->problem_type = type; 2411 if (type == TS_LINEAR) { 2412 SNES snes; 2413 PetscCall(TSGetSNES(ts, &snes)); 2414 PetscCall(SNESSetType(snes, SNESKSPONLY)); 2415 } 2416 PetscFunctionReturn(PETSC_SUCCESS); 2417 } 2418 2419 /*@ 2420 TSGetProblemType - Gets the type of problem to be solved. 2421 2422 Not collective 2423 2424 Input Parameter: 2425 . ts - The `TS` 2426 2427 Output Parameter: 2428 . type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms 2429 .vb 2430 M U_t = A U 2431 M(t) U_t = A(t) U 2432 F(t,U,U_t) 2433 .ve 2434 2435 Level: beginner 2436 2437 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS` 2438 @*/ 2439 PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type) 2440 { 2441 PetscFunctionBegin; 2442 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2443 PetscAssertPointer(type, 2); 2444 *type = ts->problem_type; 2445 PetscFunctionReturn(PETSC_SUCCESS); 2446 } 2447 2448 /* 2449 Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp() 2450 */ 2451 static PetscErrorCode TSSetExactFinalTimeDefault(TS ts) 2452 { 2453 PetscBool isnone; 2454 2455 PetscFunctionBegin; 2456 PetscCall(TSGetAdapt(ts, &ts->adapt)); 2457 PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type)); 2458 2459 PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &isnone)); 2460 if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP; 2461 else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE; 2462 PetscFunctionReturn(PETSC_SUCCESS); 2463 } 2464 2465 /*@ 2466 TSSetUp - Sets up the internal data structures for the later use of a timestepper. 2467 2468 Collective 2469 2470 Input Parameter: 2471 . ts - the `TS` context obtained from `TSCreate()` 2472 2473 Level: advanced 2474 2475 Note: 2476 For basic use of the `TS` solvers the user need not explicitly call 2477 `TSSetUp()`, since these actions will automatically occur during 2478 the call to `TSStep()` or `TSSolve()`. However, if one wishes to control this 2479 phase separately, `TSSetUp()` should be called after `TSCreate()` 2480 and optional routines of the form TSSetXXX(), but before `TSStep()` and `TSSolve()`. 2481 2482 .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSStep()`, `TSDestroy()`, `TSSolve()` 2483 @*/ 2484 PetscErrorCode TSSetUp(TS ts) 2485 { 2486 DM dm; 2487 PetscErrorCode (*func)(SNES, Vec, Vec, void *); 2488 PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *); 2489 TSIFunctionFn *ifun; 2490 TSIJacobianFn *ijac; 2491 TSI2JacobianFn *i2jac; 2492 TSRHSJacobianFn *rhsjac; 2493 2494 PetscFunctionBegin; 2495 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2496 if (ts->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 2497 2498 if (!((PetscObject)ts)->type_name) { 2499 PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL)); 2500 PetscCall(TSSetType(ts, ifun ? TSBEULER : TSEULER)); 2501 } 2502 2503 if (!ts->vec_sol) { 2504 PetscCheck(ts->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetSolution() first"); 2505 PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol)); 2506 } 2507 2508 if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */ 2509 PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs)); 2510 ts->Jacp = ts->Jacprhs; 2511 } 2512 2513 if (ts->quadraturets) { 2514 PetscCall(TSSetUp(ts->quadraturets)); 2515 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2516 PetscCall(VecDuplicate(ts->quadraturets->vec_sol, &ts->vec_costintegrand)); 2517 } 2518 2519 PetscCall(TSGetRHSJacobian(ts, NULL, NULL, &rhsjac, NULL)); 2520 if (rhsjac == TSComputeRHSJacobianConstant) { 2521 Mat Amat, Pmat; 2522 SNES snes; 2523 PetscCall(TSGetSNES(ts, &snes)); 2524 PetscCall(SNESGetJacobian(snes, &Amat, &Pmat, NULL, NULL)); 2525 /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would 2526 * have displaced the RHS matrix */ 2527 if (Amat && Amat == ts->Arhs) { 2528 /* we need to copy the values of the matrix because for the constant Jacobian case the user will never set the numerical values in this new location */ 2529 PetscCall(MatDuplicate(ts->Arhs, MAT_COPY_VALUES, &Amat)); 2530 PetscCall(SNESSetJacobian(snes, Amat, NULL, NULL, NULL)); 2531 PetscCall(MatDestroy(&Amat)); 2532 } 2533 if (Pmat && Pmat == ts->Brhs) { 2534 PetscCall(MatDuplicate(ts->Brhs, MAT_COPY_VALUES, &Pmat)); 2535 PetscCall(SNESSetJacobian(snes, NULL, Pmat, NULL, NULL)); 2536 PetscCall(MatDestroy(&Pmat)); 2537 } 2538 } 2539 2540 PetscCall(TSGetAdapt(ts, &ts->adapt)); 2541 PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type)); 2542 2543 PetscTryTypeMethod(ts, setup); 2544 2545 PetscCall(TSSetExactFinalTimeDefault(ts)); 2546 2547 /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction 2548 to be set right but can't do it elsewhere due to the overreliance on ctx=ts. 2549 */ 2550 PetscCall(TSGetDM(ts, &dm)); 2551 PetscCall(DMSNESGetFunction(dm, &func, NULL)); 2552 if (!func) PetscCall(DMSNESSetFunction(dm, SNESTSFormFunction, ts)); 2553 2554 /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it. 2555 Otherwise, the SNES will use coloring internally to form the Jacobian. 2556 */ 2557 PetscCall(DMSNESGetJacobian(dm, &jac, NULL)); 2558 PetscCall(DMTSGetIJacobian(dm, &ijac, NULL)); 2559 PetscCall(DMTSGetI2Jacobian(dm, &i2jac, NULL)); 2560 PetscCall(DMTSGetRHSJacobian(dm, &rhsjac, NULL)); 2561 if (!jac && (ijac || i2jac || rhsjac)) PetscCall(DMSNESSetJacobian(dm, SNESTSFormJacobian, ts)); 2562 2563 /* if time integration scheme has a starting method, call it */ 2564 PetscTryTypeMethod(ts, startingmethod); 2565 2566 ts->setupcalled = PETSC_TRUE; 2567 PetscFunctionReturn(PETSC_SUCCESS); 2568 } 2569 2570 /*@ 2571 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 2572 2573 Collective 2574 2575 Input Parameter: 2576 . ts - the `TS` context obtained from `TSCreate()` 2577 2578 Level: developer 2579 2580 Notes: 2581 Any options set on the `TS` object, including those set with `TSSetFromOptions()` remain. 2582 2583 See also `TSSetResize()` to change the size of the system being integrated (for example by adaptive mesh refinement) during the time integration. 2584 2585 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSetResize()` 2586 @*/ 2587 PetscErrorCode TSReset(TS ts) 2588 { 2589 TS_RHSSplitLink ilink = ts->tsrhssplit, next; 2590 2591 PetscFunctionBegin; 2592 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2593 2594 PetscTryTypeMethod(ts, reset); 2595 if (ts->snes) PetscCall(SNESReset(ts->snes)); 2596 if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt)); 2597 2598 PetscCall(MatDestroy(&ts->Arhs)); 2599 PetscCall(MatDestroy(&ts->Brhs)); 2600 PetscCall(VecDestroy(&ts->Frhs)); 2601 PetscCall(VecDestroy(&ts->vec_sol)); 2602 PetscCall(VecDestroy(&ts->vec_sol0)); 2603 PetscCall(VecDestroy(&ts->vec_dot)); 2604 PetscCall(VecDestroy(&ts->vatol)); 2605 PetscCall(VecDestroy(&ts->vrtol)); 2606 PetscCall(VecDestroyVecs(ts->nwork, &ts->work)); 2607 2608 PetscCall(MatDestroy(&ts->Jacprhs)); 2609 PetscCall(MatDestroy(&ts->Jacp)); 2610 if (ts->forward_solve) PetscCall(TSForwardReset(ts)); 2611 if (ts->quadraturets) { 2612 PetscCall(TSReset(ts->quadraturets)); 2613 PetscCall(VecDestroy(&ts->vec_costintegrand)); 2614 } 2615 while (ilink) { 2616 next = ilink->next; 2617 PetscCall(TSDestroy(&ilink->ts)); 2618 PetscCall(PetscFree(ilink->splitname)); 2619 PetscCall(ISDestroy(&ilink->is)); 2620 PetscCall(PetscFree(ilink)); 2621 ilink = next; 2622 } 2623 ts->tsrhssplit = NULL; 2624 ts->num_rhs_splits = 0; 2625 if (ts->eval_times) { 2626 PetscCall(PetscFree(ts->eval_times->time_points)); 2627 PetscCall(PetscFree(ts->eval_times->sol_times)); 2628 PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs)); 2629 PetscCall(PetscFree(ts->eval_times)); 2630 } 2631 ts->rhsjacobian.time = PETSC_MIN_REAL; 2632 ts->rhsjacobian.scale = 1.0; 2633 ts->ijacobian.shift = 1.0; 2634 ts->setupcalled = PETSC_FALSE; 2635 PetscFunctionReturn(PETSC_SUCCESS); 2636 } 2637 2638 static PetscErrorCode TSResizeReset(TS); 2639 2640 /*@ 2641 TSDestroy - Destroys the timestepper context that was created 2642 with `TSCreate()`. 2643 2644 Collective 2645 2646 Input Parameter: 2647 . ts - the `TS` context obtained from `TSCreate()` 2648 2649 Level: beginner 2650 2651 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSSolve()` 2652 @*/ 2653 PetscErrorCode TSDestroy(TS *ts) 2654 { 2655 PetscFunctionBegin; 2656 if (!*ts) PetscFunctionReturn(PETSC_SUCCESS); 2657 PetscValidHeaderSpecific(*ts, TS_CLASSID, 1); 2658 if (--((PetscObject)*ts)->refct > 0) { 2659 *ts = NULL; 2660 PetscFunctionReturn(PETSC_SUCCESS); 2661 } 2662 2663 PetscCall(TSReset(*ts)); 2664 PetscCall(TSAdjointReset(*ts)); 2665 if ((*ts)->forward_solve) PetscCall(TSForwardReset(*ts)); 2666 PetscCall(TSResizeReset(*ts)); 2667 2668 /* if memory was published with SAWs then destroy it */ 2669 PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts)); 2670 PetscTryTypeMethod(*ts, destroy); 2671 2672 PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory)); 2673 2674 PetscCall(TSAdaptDestroy(&(*ts)->adapt)); 2675 PetscCall(TSEventDestroy(&(*ts)->event)); 2676 2677 PetscCall(SNESDestroy(&(*ts)->snes)); 2678 PetscCall(SNESDestroy(&(*ts)->snesrhssplit)); 2679 PetscCall(DMDestroy(&(*ts)->dm)); 2680 PetscCall(TSMonitorCancel(*ts)); 2681 PetscCall(TSAdjointMonitorCancel(*ts)); 2682 2683 PetscCall(TSDestroy(&(*ts)->quadraturets)); 2684 PetscCall(PetscHeaderDestroy(ts)); 2685 PetscFunctionReturn(PETSC_SUCCESS); 2686 } 2687 2688 /*@ 2689 TSGetSNES - Returns the `SNES` (nonlinear solver) associated with 2690 a `TS` (timestepper) context. Valid only for nonlinear problems. 2691 2692 Not Collective, but snes is parallel if ts is parallel 2693 2694 Input Parameter: 2695 . ts - the `TS` context obtained from `TSCreate()` 2696 2697 Output Parameter: 2698 . snes - the nonlinear solver context 2699 2700 Level: beginner 2701 2702 Notes: 2703 The user can then directly manipulate the `SNES` context to set various 2704 options, etc. Likewise, the user can then extract and manipulate the 2705 `KSP`, and `PC` contexts as well. 2706 2707 `TSGetSNES()` does not work for integrators that do not use `SNES`; in 2708 this case `TSGetSNES()` returns `NULL` in `snes`. 2709 2710 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()` 2711 @*/ 2712 PetscErrorCode TSGetSNES(TS ts, SNES *snes) 2713 { 2714 PetscFunctionBegin; 2715 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2716 PetscAssertPointer(snes, 2); 2717 if (!ts->snes) { 2718 PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts), &ts->snes)); 2719 PetscCall(PetscObjectSetOptions((PetscObject)ts->snes, ((PetscObject)ts)->options)); 2720 PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts)); 2721 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1)); 2722 if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm)); 2723 if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY)); 2724 } 2725 *snes = ts->snes; 2726 PetscFunctionReturn(PETSC_SUCCESS); 2727 } 2728 2729 /*@ 2730 TSSetSNES - Set the `SNES` (nonlinear solver) to be used by the `TS` timestepping context 2731 2732 Collective 2733 2734 Input Parameters: 2735 + ts - the `TS` context obtained from `TSCreate()` 2736 - snes - the nonlinear solver context 2737 2738 Level: developer 2739 2740 Note: 2741 Most users should have the `TS` created by calling `TSGetSNES()` 2742 2743 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()` 2744 @*/ 2745 PetscErrorCode TSSetSNES(TS ts, SNES snes) 2746 { 2747 PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *); 2748 2749 PetscFunctionBegin; 2750 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2751 PetscValidHeaderSpecific(snes, SNES_CLASSID, 2); 2752 PetscCall(PetscObjectReference((PetscObject)snes)); 2753 PetscCall(SNESDestroy(&ts->snes)); 2754 2755 ts->snes = snes; 2756 2757 PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts)); 2758 PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL)); 2759 if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts)); 2760 PetscFunctionReturn(PETSC_SUCCESS); 2761 } 2762 2763 /*@ 2764 TSGetKSP - Returns the `KSP` (linear solver) associated with 2765 a `TS` (timestepper) context. 2766 2767 Not Collective, but `ksp` is parallel if `ts` is parallel 2768 2769 Input Parameter: 2770 . ts - the `TS` context obtained from `TSCreate()` 2771 2772 Output Parameter: 2773 . ksp - the nonlinear solver context 2774 2775 Level: beginner 2776 2777 Notes: 2778 The user can then directly manipulate the `KSP` context to set various 2779 options, etc. Likewise, the user can then extract and manipulate the 2780 `PC` context as well. 2781 2782 `TSGetKSP()` does not work for integrators that do not use `KSP`; 2783 in this case `TSGetKSP()` returns `NULL` in `ksp`. 2784 2785 .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()` 2786 @*/ 2787 PetscErrorCode TSGetKSP(TS ts, KSP *ksp) 2788 { 2789 SNES snes; 2790 2791 PetscFunctionBegin; 2792 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2793 PetscAssertPointer(ksp, 2); 2794 PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first"); 2795 PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()"); 2796 PetscCall(TSGetSNES(ts, &snes)); 2797 PetscCall(SNESGetKSP(snes, ksp)); 2798 PetscFunctionReturn(PETSC_SUCCESS); 2799 } 2800 2801 /* ----------- Routines to set solver parameters ---------- */ 2802 2803 /*@ 2804 TSSetMaxSteps - Sets the maximum number of steps to use. 2805 2806 Logically Collective 2807 2808 Input Parameters: 2809 + ts - the `TS` context obtained from `TSCreate()` 2810 - maxsteps - maximum number of steps to use 2811 2812 Options Database Key: 2813 . -ts_max_steps <maxsteps> - Sets maxsteps 2814 2815 Level: intermediate 2816 2817 Note: 2818 Use `PETSC_DETERMINE` to reset the maximum number of steps to the default from when the object's type was set 2819 2820 The default maximum number of steps is 5,000 2821 2822 Fortran Note: 2823 Use `PETSC_DETERMINE_INTEGER` 2824 2825 .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()` 2826 @*/ 2827 PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps) 2828 { 2829 PetscFunctionBegin; 2830 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2831 PetscValidLogicalCollectiveInt(ts, maxsteps, 2); 2832 if (maxsteps == PETSC_DETERMINE) { 2833 ts->max_steps = ts->default_max_steps; 2834 } else { 2835 PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative"); 2836 ts->max_steps = maxsteps; 2837 } 2838 PetscFunctionReturn(PETSC_SUCCESS); 2839 } 2840 2841 /*@ 2842 TSGetMaxSteps - Gets the maximum number of steps to use. 2843 2844 Not Collective 2845 2846 Input Parameter: 2847 . ts - the `TS` context obtained from `TSCreate()` 2848 2849 Output Parameter: 2850 . maxsteps - maximum number of steps to use 2851 2852 Level: advanced 2853 2854 .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()` 2855 @*/ 2856 PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps) 2857 { 2858 PetscFunctionBegin; 2859 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2860 PetscAssertPointer(maxsteps, 2); 2861 *maxsteps = ts->max_steps; 2862 PetscFunctionReturn(PETSC_SUCCESS); 2863 } 2864 2865 /*@ 2866 TSSetRunSteps - Sets the maximum number of steps to take in each call to `TSSolve()`. 2867 2868 If the step count when `TSSolve()` is `start_step`, this will stop the simulation once `current_step - start_step >= run_steps`. 2869 Comparatively, `TSSetMaxSteps()` will stop if `current_step >= max_steps`. 2870 The simulation will stop when either condition is reached. 2871 2872 Logically Collective 2873 2874 Input Parameters: 2875 + ts - the `TS` context obtained from `TSCreate()` 2876 - runsteps - maximum number of steps to take in each call to `TSSolve()`; 2877 2878 Options Database Key: 2879 . -ts_run_steps <runsteps> - Sets runsteps 2880 2881 Level: intermediate 2882 2883 Note: 2884 The default is `PETSC_UNLIMITED` 2885 2886 .seealso: [](ch_ts), `TS`, `TSGetRunSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()`, `TSSetMaxSteps()` 2887 @*/ 2888 PetscErrorCode TSSetRunSteps(TS ts, PetscInt runsteps) 2889 { 2890 PetscFunctionBegin; 2891 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2892 PetscValidLogicalCollectiveInt(ts, runsteps, 2); 2893 if (runsteps == PETSC_DETERMINE) { 2894 ts->run_steps = PETSC_UNLIMITED; 2895 } else { 2896 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"); 2897 ts->run_steps = runsteps; 2898 } 2899 PetscFunctionReturn(PETSC_SUCCESS); 2900 } 2901 2902 /*@ 2903 TSGetRunSteps - Gets the maximum number of steps to take in each call to `TSSolve()`. 2904 2905 Not Collective 2906 2907 Input Parameter: 2908 . ts - the `TS` context obtained from `TSCreate()` 2909 2910 Output Parameter: 2911 . runsteps - maximum number of steps to take in each call to `TSSolve`. 2912 2913 Level: advanced 2914 2915 .seealso: [](ch_ts), `TS`, `TSSetRunSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()`, `TSGetMaxSteps()` 2916 @*/ 2917 PetscErrorCode TSGetRunSteps(TS ts, PetscInt *runsteps) 2918 { 2919 PetscFunctionBegin; 2920 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2921 PetscAssertPointer(runsteps, 2); 2922 *runsteps = ts->run_steps; 2923 PetscFunctionReturn(PETSC_SUCCESS); 2924 } 2925 2926 /*@ 2927 TSSetMaxTime - Sets the maximum (or final) time for timestepping. 2928 2929 Logically Collective 2930 2931 Input Parameters: 2932 + ts - the `TS` context obtained from `TSCreate()` 2933 - maxtime - final time to step to 2934 2935 Options Database Key: 2936 . -ts_max_time <maxtime> - Sets maxtime 2937 2938 Level: intermediate 2939 2940 Notes: 2941 Use `PETSC_DETERMINE` to reset the maximum time to the default from when the object's type was set 2942 2943 The default maximum time is 5.0 2944 2945 Fortran Note: 2946 Use `PETSC_DETERMINE_REAL` 2947 2948 .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()` 2949 @*/ 2950 PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime) 2951 { 2952 PetscFunctionBegin; 2953 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2954 PetscValidLogicalCollectiveReal(ts, maxtime, 2); 2955 if (maxtime == PETSC_DETERMINE) { 2956 ts->max_time = ts->default_max_time; 2957 } else { 2958 ts->max_time = maxtime; 2959 } 2960 PetscFunctionReturn(PETSC_SUCCESS); 2961 } 2962 2963 /*@ 2964 TSGetMaxTime - Gets the maximum (or final) time for timestepping. 2965 2966 Not Collective 2967 2968 Input Parameter: 2969 . ts - the `TS` context obtained from `TSCreate()` 2970 2971 Output Parameter: 2972 . maxtime - final time to step to 2973 2974 Level: advanced 2975 2976 .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()` 2977 @*/ 2978 PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime) 2979 { 2980 PetscFunctionBegin; 2981 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2982 PetscAssertPointer(maxtime, 2); 2983 *maxtime = ts->max_time; 2984 PetscFunctionReturn(PETSC_SUCCESS); 2985 } 2986 2987 // PetscClangLinter pragma disable: -fdoc-* 2988 /*@ 2989 TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`. 2990 2991 Level: deprecated 2992 2993 @*/ 2994 PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step) 2995 { 2996 PetscFunctionBegin; 2997 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 2998 PetscCall(TSSetTime(ts, initial_time)); 2999 PetscCall(TSSetTimeStep(ts, time_step)); 3000 PetscFunctionReturn(PETSC_SUCCESS); 3001 } 3002 3003 // PetscClangLinter pragma disable: -fdoc-* 3004 /*@ 3005 TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`. 3006 3007 Level: deprecated 3008 3009 @*/ 3010 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime) 3011 { 3012 PetscFunctionBegin; 3013 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3014 if (maxsteps) { 3015 PetscAssertPointer(maxsteps, 2); 3016 *maxsteps = ts->max_steps; 3017 } 3018 if (maxtime) { 3019 PetscAssertPointer(maxtime, 3); 3020 *maxtime = ts->max_time; 3021 } 3022 PetscFunctionReturn(PETSC_SUCCESS); 3023 } 3024 3025 // PetscClangLinter pragma disable: -fdoc-* 3026 /*@ 3027 TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`. 3028 3029 Level: deprecated 3030 3031 @*/ 3032 PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime) 3033 { 3034 PetscFunctionBegin; 3035 if (maxsteps != PETSC_CURRENT) PetscCall(TSSetMaxSteps(ts, maxsteps)); 3036 if (maxtime != (PetscReal)PETSC_CURRENT) PetscCall(TSSetMaxTime(ts, maxtime)); 3037 PetscFunctionReturn(PETSC_SUCCESS); 3038 } 3039 3040 // PetscClangLinter pragma disable: -fdoc-* 3041 /*@ 3042 TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`. 3043 3044 Level: deprecated 3045 3046 @*/ 3047 PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps) 3048 { 3049 return TSGetStepNumber(ts, steps); 3050 } 3051 3052 // PetscClangLinter pragma disable: -fdoc-* 3053 /*@ 3054 TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`. 3055 3056 Level: deprecated 3057 3058 @*/ 3059 PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps) 3060 { 3061 return TSGetStepNumber(ts, steps); 3062 } 3063 3064 /*@ 3065 TSSetSolution - Sets the initial solution vector 3066 for use by the `TS` routines. 3067 3068 Logically Collective 3069 3070 Input Parameters: 3071 + ts - the `TS` context obtained from `TSCreate()` 3072 - u - the solution vector 3073 3074 Level: beginner 3075 3076 .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()` 3077 @*/ 3078 PetscErrorCode TSSetSolution(TS ts, Vec u) 3079 { 3080 DM dm; 3081 3082 PetscFunctionBegin; 3083 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3084 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3085 PetscCall(PetscObjectReference((PetscObject)u)); 3086 PetscCall(VecDestroy(&ts->vec_sol)); 3087 ts->vec_sol = u; 3088 3089 PetscCall(TSGetDM(ts, &dm)); 3090 PetscCall(DMShellSetGlobalVector(dm, u)); 3091 PetscFunctionReturn(PETSC_SUCCESS); 3092 } 3093 3094 /*@C 3095 TSSetPreStep - Sets the general-purpose function 3096 called once at the beginning of each time step. 3097 3098 Logically Collective 3099 3100 Input Parameters: 3101 + ts - The `TS` context obtained from `TSCreate()` 3102 - func - The function 3103 3104 Calling sequence of `func`: 3105 . ts - the `TS` context 3106 3107 Level: intermediate 3108 3109 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()` 3110 @*/ 3111 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS ts)) 3112 { 3113 PetscFunctionBegin; 3114 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3115 ts->prestep = func; 3116 PetscFunctionReturn(PETSC_SUCCESS); 3117 } 3118 3119 /*@ 3120 TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()` 3121 3122 Collective 3123 3124 Input Parameter: 3125 . ts - The `TS` context obtained from `TSCreate()` 3126 3127 Level: developer 3128 3129 Note: 3130 `TSPreStep()` is typically used within time stepping implementations, 3131 so most users would not generally call this routine themselves. 3132 3133 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()` 3134 @*/ 3135 PetscErrorCode TSPreStep(TS ts) 3136 { 3137 PetscFunctionBegin; 3138 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3139 if (ts->prestep) { 3140 Vec U; 3141 PetscObjectId idprev; 3142 PetscBool sameObject; 3143 PetscObjectState sprev, spost; 3144 3145 PetscCall(TSGetSolution(ts, &U)); 3146 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3147 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3148 PetscCallBack("TS callback preset", (*ts->prestep)(ts)); 3149 PetscCall(TSGetSolution(ts, &U)); 3150 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3151 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3152 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3153 } 3154 PetscFunctionReturn(PETSC_SUCCESS); 3155 } 3156 3157 /*@C 3158 TSSetPreStage - Sets the general-purpose function 3159 called once at the beginning of each stage. 3160 3161 Logically Collective 3162 3163 Input Parameters: 3164 + ts - The `TS` context obtained from `TSCreate()` 3165 - func - The function 3166 3167 Calling sequence of `func`: 3168 + ts - the `TS` context 3169 - stagetime - the stage time 3170 3171 Level: intermediate 3172 3173 Note: 3174 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3175 The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being 3176 attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`. 3177 3178 .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3179 @*/ 3180 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime)) 3181 { 3182 PetscFunctionBegin; 3183 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3184 ts->prestage = func; 3185 PetscFunctionReturn(PETSC_SUCCESS); 3186 } 3187 3188 /*@C 3189 TSSetPostStage - Sets the general-purpose function 3190 called once at the end of each stage. 3191 3192 Logically Collective 3193 3194 Input Parameters: 3195 + ts - The `TS` context obtained from `TSCreate()` 3196 - func - The function 3197 3198 Calling sequence of `func`: 3199 + ts - the `TS` context 3200 . stagetime - the stage time 3201 . stageindex - the stage index 3202 - Y - Array of vectors (of size = total number of stages) with the stage solutions 3203 3204 Level: intermediate 3205 3206 Note: 3207 There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried. 3208 The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being 3209 attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`. 3210 3211 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3212 @*/ 3213 PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)) 3214 { 3215 PetscFunctionBegin; 3216 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3217 ts->poststage = func; 3218 PetscFunctionReturn(PETSC_SUCCESS); 3219 } 3220 3221 /*@C 3222 TSSetPostEvaluate - Sets the general-purpose function 3223 called at the end of each step evaluation. 3224 3225 Logically Collective 3226 3227 Input Parameters: 3228 + ts - The `TS` context obtained from `TSCreate()` 3229 - func - The function 3230 3231 Calling sequence of `func`: 3232 . ts - the `TS` context 3233 3234 Level: intermediate 3235 3236 Note: 3237 The function set by `TSSetPostEvaluate()` is called after the solution is evaluated, or after the step rollback. 3238 Inside the `func` callback, the solution vector can be obtained with `TSGetSolution()`, and modified, if need be. 3239 The time step can be obtained with `TSGetTimeStep()`, and the time at the start of the step - via `TSGetTime()`. 3240 The potential changes to the solution vector introduced by event handling (`postevent()`) are not relevant for `TSSetPostEvaluate()`, 3241 but are relevant for `TSSetPostStep()`, according to the function call scheme in `TSSolve()`, as shown below 3242 .vb 3243 ... 3244 Step() 3245 PostEvaluate() 3246 EventHandling() 3247 step_rollback ? PostEvaluate() : PostStep() 3248 ... 3249 .ve 3250 where EventHandling() may result in one of the following three outcomes 3251 .vb 3252 (1) | successful step | solution intact 3253 (2) | successful step | solution modified by `postevent()` 3254 (3) | step_rollback | solution rolled back 3255 .ve 3256 3257 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()` 3258 @*/ 3259 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS ts)) 3260 { 3261 PetscFunctionBegin; 3262 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3263 ts->postevaluate = func; 3264 PetscFunctionReturn(PETSC_SUCCESS); 3265 } 3266 3267 /*@ 3268 TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()` 3269 3270 Collective 3271 3272 Input Parameters: 3273 + ts - The `TS` context obtained from `TSCreate()` 3274 - stagetime - The absolute time of the current stage 3275 3276 Level: developer 3277 3278 Note: 3279 `TSPreStage()` is typically used within time stepping implementations, 3280 most users would not generally call this routine themselves. 3281 3282 .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3283 @*/ 3284 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime) 3285 { 3286 PetscFunctionBegin; 3287 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3288 if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime)); 3289 PetscFunctionReturn(PETSC_SUCCESS); 3290 } 3291 3292 /*@ 3293 TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()` 3294 3295 Collective 3296 3297 Input Parameters: 3298 + ts - The `TS` context obtained from `TSCreate()` 3299 . stagetime - The absolute time of the current stage 3300 . stageindex - Stage number 3301 - Y - Array of vectors (of size = total number of stages) with the stage solutions 3302 3303 Level: developer 3304 3305 Note: 3306 `TSPostStage()` is typically used within time stepping implementations, 3307 most users would not generally call this routine themselves. 3308 3309 .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3310 @*/ 3311 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec Y[]) 3312 { 3313 PetscFunctionBegin; 3314 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3315 if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y)); 3316 PetscFunctionReturn(PETSC_SUCCESS); 3317 } 3318 3319 /*@ 3320 TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()` 3321 3322 Collective 3323 3324 Input Parameter: 3325 . ts - The `TS` context obtained from `TSCreate()` 3326 3327 Level: developer 3328 3329 Note: 3330 `TSPostEvaluate()` is typically used within time stepping implementations, 3331 most users would not generally call this routine themselves. 3332 3333 .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()` 3334 @*/ 3335 PetscErrorCode TSPostEvaluate(TS ts) 3336 { 3337 PetscFunctionBegin; 3338 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3339 if (ts->postevaluate) { 3340 Vec U; 3341 PetscObjectState sprev, spost; 3342 3343 PetscCall(TSGetSolution(ts, &U)); 3344 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3345 PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts)); 3346 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3347 if (sprev != spost) PetscCall(TSRestartStep(ts)); 3348 } 3349 PetscFunctionReturn(PETSC_SUCCESS); 3350 } 3351 3352 /*@C 3353 TSSetPostStep - Sets the general-purpose function 3354 called once at the end of each successful time step. 3355 3356 Logically Collective 3357 3358 Input Parameters: 3359 + ts - The `TS` context obtained from `TSCreate()` 3360 - func - The function 3361 3362 Calling sequence of `func`: 3363 . ts - the `TS` context 3364 3365 Level: intermediate 3366 3367 Note: 3368 The function set by `TSSetPostStep()` is called after each successful step. If the event handler locates an event at the 3369 given step, and `postevent()` modifies the solution vector, the solution vector obtained by `TSGetSolution()` inside `func` will 3370 contain the changes. To get the solution without these changes, use `TSSetPostEvaluate()` to set the appropriate callback. 3371 The scheme of the relevant function calls in `TSSolve()` is shown below 3372 .vb 3373 ... 3374 Step() 3375 PostEvaluate() 3376 EventHandling() 3377 step_rollback ? PostEvaluate() : PostStep() 3378 ... 3379 .ve 3380 where EventHandling() may result in one of the following three outcomes 3381 .vb 3382 (1) | successful step | solution intact 3383 (2) | successful step | solution modified by `postevent()` 3384 (3) | step_rollback | solution rolled back 3385 .ve 3386 3387 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()` 3388 @*/ 3389 PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS ts)) 3390 { 3391 PetscFunctionBegin; 3392 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3393 ts->poststep = func; 3394 PetscFunctionReturn(PETSC_SUCCESS); 3395 } 3396 3397 /*@ 3398 TSPostStep - Runs the user-defined post-step function that was set with `TSSetPostStep()` 3399 3400 Collective 3401 3402 Input Parameter: 3403 . ts - The `TS` context obtained from `TSCreate()` 3404 3405 Note: 3406 `TSPostStep()` is typically used within time stepping implementations, 3407 so most users would not generally call this routine themselves. 3408 3409 Level: developer 3410 3411 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPostStep()` 3412 @*/ 3413 PetscErrorCode TSPostStep(TS ts) 3414 { 3415 PetscFunctionBegin; 3416 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3417 if (ts->poststep) { 3418 Vec U; 3419 PetscObjectId idprev; 3420 PetscBool sameObject; 3421 PetscObjectState sprev, spost; 3422 3423 PetscCall(TSGetSolution(ts, &U)); 3424 PetscCall(PetscObjectGetId((PetscObject)U, &idprev)); 3425 PetscCall(PetscObjectStateGet((PetscObject)U, &sprev)); 3426 PetscCallBack("TS callback poststep", (*ts->poststep)(ts)); 3427 PetscCall(TSGetSolution(ts, &U)); 3428 PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject)); 3429 PetscCall(PetscObjectStateGet((PetscObject)U, &spost)); 3430 if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts)); 3431 } 3432 PetscFunctionReturn(PETSC_SUCCESS); 3433 } 3434 3435 /*@ 3436 TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval 3437 3438 Collective 3439 3440 Input Parameters: 3441 + ts - time stepping context 3442 - t - time to interpolate to 3443 3444 Output Parameter: 3445 . U - state at given time 3446 3447 Level: intermediate 3448 3449 Developer Notes: 3450 `TSInterpolate()` and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints. 3451 3452 .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()` 3453 @*/ 3454 PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U) 3455 { 3456 PetscFunctionBegin; 3457 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3458 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3459 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); 3460 PetscUseTypeMethod(ts, interpolate, t, U); 3461 PetscFunctionReturn(PETSC_SUCCESS); 3462 } 3463 3464 /*@ 3465 TSStep - Steps one time step 3466 3467 Collective 3468 3469 Input Parameter: 3470 . ts - the `TS` context obtained from `TSCreate()` 3471 3472 Level: developer 3473 3474 Notes: 3475 The public interface for the ODE/DAE solvers is `TSSolve()`, you should almost for sure be using that routine and not this routine. 3476 3477 The hook set using `TSSetPreStep()` is called before each attempt to take the step. In general, the time step size may 3478 be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages. 3479 3480 This may over-step the final time provided in `TSSetMaxTime()` depending on the time-step used. `TSSolve()` interpolates to exactly the 3481 time provided in `TSSetMaxTime()`. One can use `TSInterpolate()` to determine an interpolated solution within the final timestep. 3482 3483 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()` 3484 @*/ 3485 PetscErrorCode TSStep(TS ts) 3486 { 3487 static PetscBool cite = PETSC_FALSE; 3488 PetscReal ptime; 3489 3490 PetscFunctionBegin; 3491 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3492 PetscCall(PetscCitationsRegister("@article{tspaper,\n" 3493 " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n" 3494 " author = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n" 3495 " journal = {arXiv e-preprints},\n" 3496 " eprint = {1806.01437},\n" 3497 " archivePrefix = {arXiv},\n" 3498 " year = {2018}\n}\n", 3499 &cite)); 3500 PetscCall(TSSetUp(ts)); 3501 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 3502 if (ts->eval_times) 3503 ts->eval_times->worktol = 0; /* In each step of TSSolve() 'eval_times->worktol' will be meaningfully defined (later) only once: 3504 in TSAdaptChoose() or TSEvent_dt_cap(), and then reused till the end of the step */ 3505 3506 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>"); 3507 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()"); 3508 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"); 3509 3510 if (!ts->vec_sol0) PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sol0)); 3511 PetscCall(VecCopy(ts->vec_sol, ts->vec_sol0)); 3512 ts->time_step0 = ts->time_step; 3513 3514 if (!ts->steps) ts->ptime_prev = ts->ptime; 3515 ptime = ts->ptime; 3516 3517 ts->ptime_prev_rollback = ts->ptime_prev; 3518 ts->reason = TS_CONVERGED_ITERATING; 3519 3520 PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0)); 3521 PetscUseTypeMethod(ts, step); 3522 PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0)); 3523 3524 if (ts->reason >= 0) { 3525 ts->ptime_prev = ptime; 3526 ts->steps++; 3527 ts->steprollback = PETSC_FALSE; 3528 ts->steprestart = PETSC_FALSE; 3529 ts->stepresize = PETSC_FALSE; 3530 } 3531 3532 if (ts->reason < 0 && ts->errorifstepfailed) { 3533 PetscCall(TSMonitorCancel(ts)); 3534 if (ts->usessnes && ts->snes) PetscCall(SNESMonitorCancel(ts->snes)); 3535 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]); 3536 SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]); 3537 } 3538 PetscFunctionReturn(PETSC_SUCCESS); 3539 } 3540 3541 /*@ 3542 TSEvaluateWLTE - Evaluate the weighted local truncation error norm 3543 at the end of a time step with a given order of accuracy. 3544 3545 Collective 3546 3547 Input Parameters: 3548 + ts - time stepping context 3549 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 3550 3551 Input/Output Parameter: 3552 . order - optional, desired order for the error evaluation or `PETSC_DECIDE`; 3553 on output, the actual order of the error evaluation 3554 3555 Output Parameter: 3556 . wlte - the weighted local truncation error norm 3557 3558 Level: advanced 3559 3560 Note: 3561 If the timestepper cannot evaluate the error in a particular step 3562 (eg. in the first step or restart steps after event handling), 3563 this routine returns wlte=-1.0 . 3564 3565 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()` 3566 @*/ 3567 PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte) 3568 { 3569 PetscFunctionBegin; 3570 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3571 PetscValidType(ts, 1); 3572 PetscValidLogicalCollectiveEnum(ts, wnormtype, 2); 3573 if (order) PetscAssertPointer(order, 3); 3574 if (order) PetscValidLogicalCollectiveInt(ts, *order, 3); 3575 PetscAssertPointer(wlte, 4); 3576 PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]); 3577 PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte); 3578 PetscFunctionReturn(PETSC_SUCCESS); 3579 } 3580 3581 /*@ 3582 TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy. 3583 3584 Collective 3585 3586 Input Parameters: 3587 + ts - time stepping context 3588 . order - desired order of accuracy 3589 - done - whether the step was evaluated at this order (pass `NULL` to generate an error if not available) 3590 3591 Output Parameter: 3592 . U - state at the end of the current step 3593 3594 Level: advanced 3595 3596 Notes: 3597 This function cannot be called until all stages have been evaluated. 3598 3599 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. 3600 3601 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt` 3602 @*/ 3603 PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done) 3604 { 3605 PetscFunctionBegin; 3606 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3607 PetscValidType(ts, 1); 3608 PetscValidHeaderSpecific(U, VEC_CLASSID, 3); 3609 PetscUseTypeMethod(ts, evaluatestep, order, U, done); 3610 PetscFunctionReturn(PETSC_SUCCESS); 3611 } 3612 3613 /*@C 3614 TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping. 3615 3616 Not collective 3617 3618 Input Parameter: 3619 . ts - time stepping context 3620 3621 Output Parameter: 3622 . initCondition - The function which computes an initial condition 3623 3624 Calling sequence of `initCondition`: 3625 + ts - The timestepping context 3626 - u - The input vector in which the initial condition is stored 3627 3628 Level: advanced 3629 3630 .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()` 3631 @*/ 3632 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS ts, Vec u)) 3633 { 3634 PetscFunctionBegin; 3635 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3636 PetscAssertPointer(initCondition, 2); 3637 *initCondition = ts->ops->initcondition; 3638 PetscFunctionReturn(PETSC_SUCCESS); 3639 } 3640 3641 /*@C 3642 TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping. 3643 3644 Logically collective 3645 3646 Input Parameters: 3647 + ts - time stepping context 3648 - initCondition - The function which computes an initial condition 3649 3650 Calling sequence of `initCondition`: 3651 + ts - The timestepping context 3652 - e - The input vector in which the initial condition is to be stored 3653 3654 Level: advanced 3655 3656 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()` 3657 @*/ 3658 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS ts, Vec e)) 3659 { 3660 PetscFunctionBegin; 3661 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3662 PetscValidFunction(initCondition, 2); 3663 ts->ops->initcondition = initCondition; 3664 PetscFunctionReturn(PETSC_SUCCESS); 3665 } 3666 3667 /*@ 3668 TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()` 3669 3670 Collective 3671 3672 Input Parameters: 3673 + ts - time stepping context 3674 - u - The `Vec` to store the condition in which will be used in `TSSolve()` 3675 3676 Level: advanced 3677 3678 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3679 @*/ 3680 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u) 3681 { 3682 PetscFunctionBegin; 3683 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3684 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3685 PetscTryTypeMethod(ts, initcondition, u); 3686 PetscFunctionReturn(PETSC_SUCCESS); 3687 } 3688 3689 /*@C 3690 TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping. 3691 3692 Not collective 3693 3694 Input Parameter: 3695 . ts - time stepping context 3696 3697 Output Parameter: 3698 . exactError - The function which computes the solution error 3699 3700 Calling sequence of `exactError`: 3701 + ts - The timestepping context 3702 . u - The approximate solution vector 3703 - e - The vector in which the error is stored 3704 3705 Level: advanced 3706 3707 .seealso: [](ch_ts), `TS`, `TSComputeExactError()` 3708 @*/ 3709 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS ts, Vec u, Vec e)) 3710 { 3711 PetscFunctionBegin; 3712 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3713 PetscAssertPointer(exactError, 2); 3714 *exactError = ts->ops->exacterror; 3715 PetscFunctionReturn(PETSC_SUCCESS); 3716 } 3717 3718 /*@C 3719 TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping. 3720 3721 Logically collective 3722 3723 Input Parameters: 3724 + ts - time stepping context 3725 - exactError - The function which computes the solution error 3726 3727 Calling sequence of `exactError`: 3728 + ts - The timestepping context 3729 . u - The approximate solution vector 3730 - e - The vector in which the error is stored 3731 3732 Level: advanced 3733 3734 .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()` 3735 @*/ 3736 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS ts, Vec u, Vec e)) 3737 { 3738 PetscFunctionBegin; 3739 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3740 PetscValidFunction(exactError, 2); 3741 ts->ops->exacterror = exactError; 3742 PetscFunctionReturn(PETSC_SUCCESS); 3743 } 3744 3745 /*@ 3746 TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()` 3747 3748 Collective 3749 3750 Input Parameters: 3751 + ts - time stepping context 3752 . u - The approximate solution 3753 - e - The `Vec` used to store the error 3754 3755 Level: advanced 3756 3757 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()` 3758 @*/ 3759 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e) 3760 { 3761 PetscFunctionBegin; 3762 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3763 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 3764 PetscValidHeaderSpecific(e, VEC_CLASSID, 3); 3765 PetscTryTypeMethod(ts, exacterror, u, e); 3766 PetscFunctionReturn(PETSC_SUCCESS); 3767 } 3768 3769 /*@C 3770 TSSetResize - Sets the resize callbacks. 3771 3772 Logically Collective 3773 3774 Input Parameters: 3775 + ts - The `TS` context obtained from `TSCreate()` 3776 . rollback - Whether a resize will restart the step 3777 . setup - The setup function 3778 . transfer - The transfer function 3779 - ctx - [optional] The user-defined context 3780 3781 Calling sequence of `setup`: 3782 + ts - the `TS` context 3783 . step - the current step 3784 . time - the current time 3785 . state - the current vector of state 3786 . resize - (output parameter) `PETSC_TRUE` if need resizing, `PETSC_FALSE` otherwise 3787 - ctx - user defined context 3788 3789 Calling sequence of `transfer`: 3790 + ts - the `TS` context 3791 . nv - the number of vectors to be transferred 3792 . vecsin - array of vectors to be transferred 3793 . vecsout - array of transferred vectors 3794 - ctx - user defined context 3795 3796 Notes: 3797 The `setup` function is called inside `TSSolve()` after `TSEventHandler()` or after `TSPostStep()` 3798 depending on the `rollback` value: if `rollback` is true, then these callbacks behave as error indicators 3799 and will flag the need to remesh and restart the current step. Otherwise, they will simply flag the solver 3800 that the size of the discrete problem has changed. 3801 In both cases, the solver will collect the needed vectors that will be 3802 transferred from the old to the new sizes using the `transfer` callback. These vectors will include the 3803 current solution vector, and other vectors needed by the specific solver used. 3804 For example, `TSBDF` uses previous solutions vectors to solve for the next time step. 3805 Other application specific objects associated with the solver, i.e. Jacobian matrices and `DM`, 3806 will be automatically reset if the sizes are changed and they must be specified again by the user 3807 inside the `transfer` function. 3808 The input and output arrays passed to `transfer` are allocated by PETSc. 3809 Vectors in `vecsout` must be created by the user. 3810 Ownership of vectors in `vecsout` is transferred to PETSc. 3811 3812 Level: advanced 3813 3814 .seealso: [](ch_ts), `TS`, `TSSetDM()`, `TSSetIJacobian()`, `TSSetRHSJacobian()` 3815 @*/ 3816 PetscErrorCode TSSetResize(TS ts, PetscBool rollback, PetscErrorCode (*setup)(TS ts, PetscInt step, PetscReal time, Vec state, PetscBool *resize, PetscCtx ctx), PetscErrorCode (*transfer)(TS ts, PetscInt nv, Vec vecsin[], Vec vecsout[], PetscCtx ctx), PetscCtx ctx) 3817 { 3818 PetscFunctionBegin; 3819 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3820 ts->resizerollback = rollback; 3821 ts->resizesetup = setup; 3822 ts->resizetransfer = transfer; 3823 ts->resizectx = ctx; 3824 PetscFunctionReturn(PETSC_SUCCESS); 3825 } 3826 3827 /* 3828 TSResizeRegisterOrRetrieve - Register or import vectors transferred with `TSResize()`. 3829 3830 Collective 3831 3832 Input Parameters: 3833 + ts - The `TS` context obtained from `TSCreate()` 3834 - 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. 3835 3836 Level: developer 3837 3838 Note: 3839 `TSResizeRegisterOrRetrieve()` is declared PETSC_INTERN since it is 3840 used within time stepping implementations, 3841 so most users would not generally call this routine themselves. 3842 3843 .seealso: [](ch_ts), `TS`, `TSSetResize()` 3844 @*/ 3845 static PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg) 3846 { 3847 PetscFunctionBegin; 3848 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3849 PetscTryTypeMethod(ts, resizeregister, flg); 3850 /* PetscTryTypeMethod(adapt, resizeregister, flg); */ 3851 PetscFunctionReturn(PETSC_SUCCESS); 3852 } 3853 3854 static PetscErrorCode TSResizeReset(TS ts) 3855 { 3856 PetscFunctionBegin; 3857 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3858 PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs)); 3859 PetscFunctionReturn(PETSC_SUCCESS); 3860 } 3861 3862 static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[]) 3863 { 3864 PetscFunctionBegin; 3865 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3866 PetscValidLogicalCollectiveInt(ts, cnt, 2); 3867 for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPush(vecsin[i])); 3868 if (ts->resizetransfer) { 3869 PetscCall(PetscInfo(ts, "Transferring %" PetscInt_FMT " vectors\n", cnt)); 3870 PetscCallBack("TS callback resize transfer", (*ts->resizetransfer)(ts, cnt, vecsin, vecsout, ts->resizectx)); 3871 } 3872 for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPop(vecsin[i])); 3873 PetscFunctionReturn(PETSC_SUCCESS); 3874 } 3875 3876 /*@C 3877 TSResizeRegisterVec - Register a vector to be transferred with `TSResize()`. 3878 3879 Collective 3880 3881 Input Parameters: 3882 + ts - The `TS` context obtained from `TSCreate()` 3883 . name - A string identifying the vector 3884 - vec - The vector 3885 3886 Level: developer 3887 3888 Note: 3889 `TSResizeRegisterVec()` is typically used within time stepping implementations, 3890 so most users would not generally call this routine themselves. 3891 3892 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()` 3893 @*/ 3894 PetscErrorCode TSResizeRegisterVec(TS ts, const char name[], Vec vec) 3895 { 3896 PetscFunctionBegin; 3897 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3898 PetscAssertPointer(name, 2); 3899 if (vec) PetscValidHeaderSpecific(vec, VEC_CLASSID, 3); 3900 PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec)); 3901 PetscFunctionReturn(PETSC_SUCCESS); 3902 } 3903 3904 /*@C 3905 TSResizeRetrieveVec - Retrieve a vector registered with `TSResizeRegisterVec()`. 3906 3907 Collective 3908 3909 Input Parameters: 3910 + ts - The `TS` context obtained from `TSCreate()` 3911 . name - A string identifying the vector 3912 - vec - The vector 3913 3914 Level: developer 3915 3916 Note: 3917 `TSResizeRetrieveVec()` is typically used within time stepping implementations, 3918 so most users would not generally call this routine themselves. 3919 3920 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()` 3921 @*/ 3922 PetscErrorCode TSResizeRetrieveVec(TS ts, const char name[], Vec *vec) 3923 { 3924 PetscFunctionBegin; 3925 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3926 PetscAssertPointer(name, 2); 3927 PetscAssertPointer(vec, 3); 3928 PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec)); 3929 PetscFunctionReturn(PETSC_SUCCESS); 3930 } 3931 3932 static PetscErrorCode TSResizeGetVecArray(TS ts, PetscInt *nv, const char **names[], Vec *vecs[]) 3933 { 3934 PetscInt cnt; 3935 PetscObjectList tmp; 3936 Vec *vecsin = NULL; 3937 const char **namesin = NULL; 3938 3939 PetscFunctionBegin; 3940 for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) 3941 if (tmp->obj && tmp->obj->classid == VEC_CLASSID) cnt++; 3942 if (names) PetscCall(PetscMalloc1(cnt, &namesin)); 3943 if (vecs) PetscCall(PetscMalloc1(cnt, &vecsin)); 3944 for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) { 3945 if (tmp->obj && tmp->obj->classid == VEC_CLASSID) { 3946 if (vecs) vecsin[cnt] = (Vec)tmp->obj; 3947 if (names) namesin[cnt] = tmp->name; 3948 cnt++; 3949 } 3950 } 3951 if (nv) *nv = cnt; 3952 if (names) *names = namesin; 3953 if (vecs) *vecs = vecsin; 3954 PetscFunctionReturn(PETSC_SUCCESS); 3955 } 3956 3957 /*@ 3958 TSResize - Runs the user-defined transfer functions provided with `TSSetResize()` 3959 3960 Collective 3961 3962 Input Parameter: 3963 . ts - The `TS` context obtained from `TSCreate()` 3964 3965 Level: developer 3966 3967 Note: 3968 `TSResize()` is typically used within time stepping implementations, 3969 so most users would not generally call this routine themselves. 3970 3971 .seealso: [](ch_ts), `TS`, `TSSetResize()` 3972 @*/ 3973 PetscErrorCode TSResize(TS ts) 3974 { 3975 PetscInt nv = 0; 3976 const char **names = NULL; 3977 Vec *vecsin = NULL; 3978 const char *solname = "ts:vec_sol"; 3979 3980 PetscFunctionBegin; 3981 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 3982 if (!ts->resizesetup) PetscFunctionReturn(PETSC_SUCCESS); 3983 if (ts->resizesetup) { 3984 PetscCall(VecLockReadPush(ts->vec_sol)); 3985 PetscCallBack("TS callback resize setup", (*ts->resizesetup)(ts, ts->steps, ts->ptime, ts->vec_sol, &ts->stepresize, ts->resizectx)); 3986 PetscCall(VecLockReadPop(ts->vec_sol)); 3987 if (ts->stepresize) { 3988 if (ts->resizerollback) { 3989 PetscCall(TSRollBack(ts)); 3990 ts->time_step = ts->time_step0; 3991 } 3992 PetscCall(TSResizeRegisterVec(ts, solname, ts->vec_sol)); 3993 PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_TRUE)); /* specific impls register their own objects */ 3994 } 3995 } 3996 3997 PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin)); 3998 if (nv) { 3999 Vec *vecsout, vecsol; 4000 4001 /* Reset internal objects */ 4002 PetscCall(TSReset(ts)); 4003 4004 /* Transfer needed vectors (users can call SetJacobian, SetDM, etc. here) */ 4005 PetscCall(PetscCalloc1(nv, &vecsout)); 4006 PetscCall(TSResizeTransferVecs(ts, nv, vecsin, vecsout)); 4007 for (PetscInt i = 0; i < nv; i++) { 4008 const char *name; 4009 char *oname; 4010 4011 PetscCall(PetscObjectGetName((PetscObject)vecsin[i], &name)); 4012 PetscCall(PetscStrallocpy(name, &oname)); 4013 PetscCall(TSResizeRegisterVec(ts, names[i], vecsout[i])); 4014 if (vecsout[i]) PetscCall(PetscObjectSetName((PetscObject)vecsout[i], oname)); 4015 PetscCall(PetscFree(oname)); 4016 PetscCall(VecDestroy(&vecsout[i])); 4017 } 4018 PetscCall(PetscFree(vecsout)); 4019 PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_FALSE)); /* specific impls import the transferred objects */ 4020 4021 PetscCall(TSResizeRetrieveVec(ts, solname, &vecsol)); 4022 if (vecsol) PetscCall(TSSetSolution(ts, vecsol)); 4023 PetscAssert(ts->vec_sol, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_NULL, "Missing TS solution"); 4024 } 4025 4026 PetscCall(PetscFree(names)); 4027 PetscCall(PetscFree(vecsin)); 4028 PetscCall(TSResizeReset(ts)); 4029 PetscFunctionReturn(PETSC_SUCCESS); 4030 } 4031 4032 /*@ 4033 TSSolve - Steps the requested number of timesteps. 4034 4035 Collective 4036 4037 Input Parameters: 4038 + ts - the `TS` context obtained from `TSCreate()` 4039 - u - the solution vector (can be null if `TSSetSolution()` was used and `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`) was not used, 4040 otherwise it must contain the initial conditions and will contain the solution at the final requested time 4041 4042 Level: beginner 4043 4044 Notes: 4045 The final time returned by this function may be different from the time of the internally 4046 held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have 4047 stepped over the final time. 4048 4049 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()` 4050 @*/ 4051 PetscErrorCode TSSolve(TS ts, Vec u) 4052 { 4053 Vec solution; 4054 4055 PetscFunctionBegin; 4056 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4057 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 4058 4059 PetscCall(TSSetExactFinalTimeDefault(ts)); 4060 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 */ 4061 if (!ts->vec_sol || u == ts->vec_sol) { 4062 PetscCall(VecDuplicate(u, &solution)); 4063 PetscCall(TSSetSolution(ts, solution)); 4064 PetscCall(VecDestroy(&solution)); /* grant ownership */ 4065 } 4066 PetscCall(VecCopy(u, ts->vec_sol)); 4067 PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE"); 4068 } else if (u) PetscCall(TSSetSolution(ts, u)); 4069 PetscCall(TSSetUp(ts)); 4070 PetscCall(TSTrajectorySetUp(ts->trajectory, ts)); 4071 4072 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>"); 4073 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()"); 4074 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"); 4075 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"); 4076 4077 if (ts->eval_times) { 4078 if (!ts->eval_times->sol_vecs) PetscCall(VecDuplicateVecs(ts->vec_sol, ts->eval_times->num_time_points, &ts->eval_times->sol_vecs)); 4079 for (PetscInt i = 0; i < ts->eval_times->num_time_points; i++) { 4080 PetscBool is_close = PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[i], ts->eval_times->reltol * ts->time_step + ts->eval_times->abstol, 0); 4081 if (ts->ptime <= ts->eval_times->time_points[i] || is_close) { 4082 ts->eval_times->time_point_idx = i; 4083 4084 PetscBool is_ptime_in_sol_times = PETSC_FALSE; // If current solution has already been saved, we should not save it again 4085 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); 4086 if (is_close && !is_ptime_in_sol_times) { 4087 PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_idx])); 4088 ts->eval_times->sol_times[ts->eval_times->sol_idx] = ts->ptime; 4089 ts->eval_times->sol_idx++; 4090 ts->eval_times->time_point_idx++; 4091 } 4092 break; 4093 } 4094 } 4095 } 4096 4097 if (ts->forward_solve) PetscCall(TSForwardSetUp(ts)); 4098 4099 /* reset number of steps only when the step is not restarted. ARKIMEX 4100 restarts the step after an event. Resetting these counters in such case causes 4101 TSTrajectory to incorrectly save the output files 4102 */ 4103 /* reset time step and iteration counters */ 4104 if (!ts->steps) { 4105 ts->ksp_its = 0; 4106 ts->snes_its = 0; 4107 ts->num_snes_failures = 0; 4108 ts->reject = 0; 4109 ts->steprestart = PETSC_TRUE; 4110 ts->steprollback = PETSC_FALSE; 4111 ts->stepresize = PETSC_FALSE; 4112 ts->rhsjacobian.time = PETSC_MIN_REAL; 4113 } 4114 4115 /* make sure initial time step does not overshoot final time or the next point in evaluation times */ 4116 if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 4117 PetscReal maxdt; 4118 PetscReal dt = ts->time_step; 4119 4120 if (ts->eval_times) maxdt = ts->eval_times->time_points[ts->eval_times->time_point_idx] - ts->ptime; 4121 else maxdt = ts->max_time - ts->ptime; 4122 ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt); 4123 } 4124 ts->reason = TS_CONVERGED_ITERATING; 4125 4126 { 4127 PetscViewer viewer; 4128 PetscViewerFormat format; 4129 PetscBool flg; 4130 static PetscBool incall = PETSC_FALSE; 4131 4132 if (!incall) { 4133 /* Estimate the convergence rate of the time discretization */ 4134 PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg)); 4135 if (flg) { 4136 PetscConvEst conv; 4137 DM dm; 4138 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4139 PetscInt Nf; 4140 PetscBool checkTemporal = PETSC_TRUE; 4141 4142 incall = PETSC_TRUE; 4143 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg)); 4144 PetscCall(TSGetDM(ts, &dm)); 4145 PetscCall(DMGetNumFields(dm, &Nf)); 4146 PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha)); 4147 PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv)); 4148 PetscCall(PetscConvEstUseTS(conv, checkTemporal)); 4149 PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts)); 4150 PetscCall(PetscConvEstSetFromOptions(conv)); 4151 PetscCall(PetscConvEstSetUp(conv)); 4152 PetscCall(PetscConvEstGetConvRate(conv, alpha)); 4153 PetscCall(PetscViewerPushFormat(viewer, format)); 4154 PetscCall(PetscConvEstRateView(conv, alpha, viewer)); 4155 PetscCall(PetscViewerPopFormat(viewer)); 4156 PetscCall(PetscViewerDestroy(&viewer)); 4157 PetscCall(PetscConvEstDestroy(&conv)); 4158 PetscCall(PetscFree(alpha)); 4159 incall = PETSC_FALSE; 4160 } 4161 } 4162 } 4163 4164 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre")); 4165 4166 if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */ 4167 PetscUseTypeMethod(ts, solve); 4168 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 4169 ts->solvetime = ts->ptime; 4170 solution = ts->vec_sol; 4171 } else { /* Step the requested number of timesteps. */ 4172 if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 4173 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 4174 4175 if (!ts->steps) { 4176 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 4177 PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol)); 4178 } 4179 4180 ts->start_step = ts->steps; // records starting step 4181 while (!ts->reason) { 4182 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 4183 if (!ts->steprollback || (ts->stepresize && ts->resizerollback)) PetscCall(TSPreStep(ts)); 4184 PetscCall(TSStep(ts)); 4185 if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL)); 4186 if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL)); 4187 if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */ 4188 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 4189 PetscCall(TSForwardCostIntegral(ts)); 4190 if (ts->reason >= 0) ts->steps++; 4191 } 4192 if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */ 4193 if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */ 4194 PetscCall(TSForwardStep(ts)); 4195 if (ts->reason >= 0) ts->steps++; 4196 } 4197 PetscCall(TSPostEvaluate(ts)); 4198 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. */ 4199 if (ts->steprollback) PetscCall(TSPostEvaluate(ts)); 4200 if (!ts->steprollback && ts->resizerollback) PetscCall(TSResize(ts)); 4201 /* check convergence */ 4202 if (!ts->reason) { 4203 if ((ts->steps - ts->start_step) >= ts->run_steps) ts->reason = TS_CONVERGED_ITS; 4204 else if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS; 4205 else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME; 4206 } 4207 if (!ts->steprollback) { 4208 PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol)); 4209 PetscCall(TSPostStep(ts)); 4210 if (!ts->resizerollback) PetscCall(TSResize(ts)); 4211 4212 if (ts->eval_times && ts->eval_times->time_point_idx < ts->eval_times->num_time_points && ts->reason >= 0) { 4213 PetscCheck(ts->eval_times->worktol > 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Unexpected state !(eval_times->worktol > 0) in TSSolve()"); 4214 if (PetscIsCloseAtTol(ts->ptime, ts->eval_times->time_points[ts->eval_times->time_point_idx], ts->eval_times->worktol, 0)) { 4215 ts->eval_times->sol_times[ts->eval_times->sol_idx] = ts->ptime; 4216 PetscCall(VecCopy(ts->vec_sol, ts->eval_times->sol_vecs[ts->eval_times->sol_idx])); 4217 ts->eval_times->sol_idx++; 4218 ts->eval_times->time_point_idx++; 4219 } 4220 } 4221 } 4222 } 4223 PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol)); 4224 4225 if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) { 4226 if (!u) u = ts->vec_sol; 4227 PetscCall(TSInterpolate(ts, ts->max_time, u)); 4228 ts->solvetime = ts->max_time; 4229 solution = u; 4230 PetscCall(TSMonitor(ts, -1, ts->solvetime, solution)); 4231 } else { 4232 if (u) PetscCall(VecCopy(ts->vec_sol, u)); 4233 ts->solvetime = ts->ptime; 4234 solution = ts->vec_sol; 4235 } 4236 } 4237 4238 PetscCall(TSViewFromOptions(ts, NULL, "-ts_view")); 4239 PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution")); 4240 PetscCall(PetscObjectSAWsBlock((PetscObject)ts)); 4241 if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts)); 4242 PetscFunctionReturn(PETSC_SUCCESS); 4243 } 4244 4245 /*@ 4246 TSGetTime - Gets the time of the most recently completed step. 4247 4248 Not Collective 4249 4250 Input Parameter: 4251 . ts - the `TS` context obtained from `TSCreate()` 4252 4253 Output Parameter: 4254 . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`. 4255 4256 Level: beginner 4257 4258 Note: 4259 When called during time step evaluation (e.g. during residual evaluation or via hooks set using `TSSetPreStep()`, 4260 `TSSetPreStage()`, `TSSetPostStage()`, or `TSSetPostStep()`), the time is the time at the start of the step being evaluated. 4261 4262 .seealso: [](ch_ts), `TS`, `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()` 4263 @*/ 4264 PetscErrorCode TSGetTime(TS ts, PetscReal *t) 4265 { 4266 PetscFunctionBegin; 4267 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4268 PetscAssertPointer(t, 2); 4269 *t = ts->ptime; 4270 PetscFunctionReturn(PETSC_SUCCESS); 4271 } 4272 4273 /*@ 4274 TSGetPrevTime - Gets the starting time of the previously completed step. 4275 4276 Not Collective 4277 4278 Input Parameter: 4279 . ts - the `TS` context obtained from `TSCreate()` 4280 4281 Output Parameter: 4282 . t - the previous time 4283 4284 Level: beginner 4285 4286 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()` 4287 @*/ 4288 PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t) 4289 { 4290 PetscFunctionBegin; 4291 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4292 PetscAssertPointer(t, 2); 4293 *t = ts->ptime_prev; 4294 PetscFunctionReturn(PETSC_SUCCESS); 4295 } 4296 4297 /*@ 4298 TSSetTime - Allows one to reset the time. 4299 4300 Logically Collective 4301 4302 Input Parameters: 4303 + ts - the `TS` context obtained from `TSCreate()` 4304 - t - the time 4305 4306 Level: intermediate 4307 4308 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()` 4309 @*/ 4310 PetscErrorCode TSSetTime(TS ts, PetscReal t) 4311 { 4312 PetscFunctionBegin; 4313 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4314 PetscValidLogicalCollectiveReal(ts, t, 2); 4315 ts->ptime = t; 4316 PetscFunctionReturn(PETSC_SUCCESS); 4317 } 4318 4319 /*@ 4320 TSSetOptionsPrefix - Sets the prefix used for searching for all 4321 TS options in the database. 4322 4323 Logically Collective 4324 4325 Input Parameters: 4326 + ts - The `TS` context 4327 - prefix - The prefix to prepend to all option names 4328 4329 Level: advanced 4330 4331 Note: 4332 A hyphen (-) must NOT be given at the beginning of the prefix name. 4333 The first character of all runtime options is AUTOMATICALLY the 4334 hyphen. 4335 4336 .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()` 4337 @*/ 4338 PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[]) 4339 { 4340 SNES snes; 4341 4342 PetscFunctionBegin; 4343 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4344 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix)); 4345 PetscCall(TSGetSNES(ts, &snes)); 4346 PetscCall(SNESSetOptionsPrefix(snes, prefix)); 4347 PetscFunctionReturn(PETSC_SUCCESS); 4348 } 4349 4350 /*@ 4351 TSAppendOptionsPrefix - Appends to the prefix used for searching for all 4352 TS options in the database. 4353 4354 Logically Collective 4355 4356 Input Parameters: 4357 + ts - The `TS` context 4358 - prefix - The prefix to prepend to all option names 4359 4360 Level: advanced 4361 4362 Note: 4363 A hyphen (-) must NOT be given at the beginning of the prefix name. 4364 The first character of all runtime options is AUTOMATICALLY the 4365 hyphen. 4366 4367 .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()` 4368 @*/ 4369 PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[]) 4370 { 4371 SNES snes; 4372 4373 PetscFunctionBegin; 4374 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4375 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix)); 4376 PetscCall(TSGetSNES(ts, &snes)); 4377 PetscCall(SNESAppendOptionsPrefix(snes, prefix)); 4378 PetscFunctionReturn(PETSC_SUCCESS); 4379 } 4380 4381 /*@ 4382 TSGetOptionsPrefix - Sets the prefix used for searching for all 4383 `TS` options in the database. 4384 4385 Not Collective 4386 4387 Input Parameter: 4388 . ts - The `TS` context 4389 4390 Output Parameter: 4391 . prefix - A pointer to the prefix string used 4392 4393 Level: intermediate 4394 4395 .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()` 4396 @*/ 4397 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[]) 4398 { 4399 PetscFunctionBegin; 4400 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4401 PetscAssertPointer(prefix, 2); 4402 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix)); 4403 PetscFunctionReturn(PETSC_SUCCESS); 4404 } 4405 4406 /*@C 4407 TSGetRHSJacobian - Returns the Jacobian J at the present timestep. 4408 4409 Not Collective, but parallel objects are returned if ts is parallel 4410 4411 Input Parameter: 4412 . ts - The `TS` context obtained from `TSCreate()` 4413 4414 Output Parameters: 4415 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or `NULL`) 4416 . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat` (or `NULL`) 4417 . func - Function to compute the Jacobian of the RHS (or `NULL`) 4418 - ctx - User-defined context for Jacobian evaluation routine (or `NULL`) 4419 4420 Level: intermediate 4421 4422 Note: 4423 You can pass in `NULL` for any return argument you do not need. 4424 4425 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4426 4427 @*/ 4428 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, PetscCtxRt ctx) 4429 { 4430 DM dm; 4431 4432 PetscFunctionBegin; 4433 if (Amat || Pmat) { 4434 SNES snes; 4435 PetscCall(TSGetSNES(ts, &snes)); 4436 PetscCall(SNESSetUpMatrices(snes)); 4437 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4438 } 4439 PetscCall(TSGetDM(ts, &dm)); 4440 PetscCall(DMTSGetRHSJacobian(dm, func, ctx)); 4441 PetscFunctionReturn(PETSC_SUCCESS); 4442 } 4443 4444 /*@C 4445 TSGetIJacobian - Returns the implicit Jacobian at the present timestep. 4446 4447 Not Collective, but parallel objects are returned if ts is parallel 4448 4449 Input Parameter: 4450 . ts - The `TS` context obtained from `TSCreate()` 4451 4452 Output Parameters: 4453 + Amat - The (approximate) Jacobian of F(t,U,U_t) 4454 . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat` 4455 . f - The function to compute the matrices 4456 - ctx - User-defined context for Jacobian evaluation routine 4457 4458 Level: advanced 4459 4460 Note: 4461 You can pass in `NULL` for any return argument you do not need. 4462 4463 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()` 4464 @*/ 4465 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, PetscCtxRt ctx) 4466 { 4467 DM dm; 4468 4469 PetscFunctionBegin; 4470 if (Amat || Pmat) { 4471 SNES snes; 4472 PetscCall(TSGetSNES(ts, &snes)); 4473 PetscCall(SNESSetUpMatrices(snes)); 4474 PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL)); 4475 } 4476 PetscCall(TSGetDM(ts, &dm)); 4477 PetscCall(DMTSGetIJacobian(dm, f, ctx)); 4478 PetscFunctionReturn(PETSC_SUCCESS); 4479 } 4480 4481 #include <petsc/private/dmimpl.h> 4482 /*@ 4483 TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS` 4484 4485 Logically Collective 4486 4487 Input Parameters: 4488 + ts - the `TS` integrator object 4489 - dm - the dm, cannot be `NULL` 4490 4491 Level: intermediate 4492 4493 Notes: 4494 A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`, 4495 even when not using interfaces like `DMTSSetIFunction()`. Use `DMClone()` to get a distinct `DM` when solving 4496 different problems using the same function space. 4497 4498 .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()` 4499 @*/ 4500 PetscErrorCode TSSetDM(TS ts, DM dm) 4501 { 4502 SNES snes; 4503 DMTS tsdm; 4504 4505 PetscFunctionBegin; 4506 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4507 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 4508 PetscCall(PetscObjectReference((PetscObject)dm)); 4509 if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */ 4510 if (ts->dm->dmts && !dm->dmts) { 4511 PetscCall(DMCopyDMTS(ts->dm, dm)); 4512 PetscCall(DMGetDMTS(ts->dm, &tsdm)); 4513 /* Grant write privileges to the replacement DM */ 4514 if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm; 4515 } 4516 PetscCall(DMDestroy(&ts->dm)); 4517 } 4518 ts->dm = dm; 4519 4520 PetscCall(TSGetSNES(ts, &snes)); 4521 PetscCall(SNESSetDM(snes, dm)); 4522 PetscFunctionReturn(PETSC_SUCCESS); 4523 } 4524 4525 /*@ 4526 TSGetDM - Gets the `DM` that may be used by some preconditioners 4527 4528 Not Collective 4529 4530 Input Parameter: 4531 . ts - the `TS` 4532 4533 Output Parameter: 4534 . dm - the `DM` 4535 4536 Level: intermediate 4537 4538 .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()` 4539 @*/ 4540 PetscErrorCode TSGetDM(TS ts, DM *dm) 4541 { 4542 PetscFunctionBegin; 4543 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4544 if (!ts->dm) { 4545 PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm)); 4546 if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm)); 4547 } 4548 *dm = ts->dm; 4549 PetscFunctionReturn(PETSC_SUCCESS); 4550 } 4551 4552 /*@ 4553 SNESTSFormFunction - Function to evaluate nonlinear residual defined by an ODE solver algorithm implemented within `TS` 4554 4555 Logically Collective 4556 4557 Input Parameters: 4558 + snes - nonlinear solver 4559 . U - the current state at which to evaluate the residual 4560 - ctx - user context, must be a `TS` 4561 4562 Output Parameter: 4563 . F - the nonlinear residual 4564 4565 Level: developer 4566 4567 Note: 4568 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4569 It is most frequently passed to `MatFDColoringSetFunction()`. 4570 4571 .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()` 4572 @*/ 4573 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, PetscCtx ctx) 4574 { 4575 TS ts = (TS)ctx; 4576 4577 PetscFunctionBegin; 4578 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4579 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4580 PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 4581 PetscValidHeaderSpecific(ts, TS_CLASSID, 4); 4582 PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name); 4583 PetscCall((*ts->ops->snesfunction)(snes, U, F, ts)); 4584 PetscFunctionReturn(PETSC_SUCCESS); 4585 } 4586 4587 /*@ 4588 SNESTSFormJacobian - Function to evaluate the Jacobian defined by an ODE solver algorithm implemented within `TS` 4589 4590 Collective 4591 4592 Input Parameters: 4593 + snes - nonlinear solver 4594 . U - the current state at which to evaluate the residual 4595 - ctx - user context, must be a `TS` 4596 4597 Output Parameters: 4598 + A - the Jacobian 4599 - B - the matrix used to construct the preconditioner (often the same as `A`) 4600 4601 Level: developer 4602 4603 Note: 4604 This function is not normally called by users and is automatically registered with the `SNES` used by `TS`. 4605 4606 .seealso: [](ch_ts), `SNESSetJacobian()` 4607 @*/ 4608 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, PetscCtx ctx) 4609 { 4610 TS ts = (TS)ctx; 4611 4612 PetscFunctionBegin; 4613 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4614 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 4615 PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 4616 PetscValidHeaderSpecific(B, MAT_CLASSID, 4); 4617 PetscValidHeaderSpecific(ts, TS_CLASSID, 5); 4618 PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name); 4619 PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts)); 4620 PetscFunctionReturn(PETSC_SUCCESS); 4621 } 4622 4623 /*@C 4624 TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only 4625 4626 Collective 4627 4628 Input Parameters: 4629 + ts - time stepping context 4630 . t - time at which to evaluate 4631 . U - state at which to evaluate 4632 - ctx - context 4633 4634 Output Parameter: 4635 . F - right-hand side 4636 4637 Level: intermediate 4638 4639 Note: 4640 This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems. 4641 The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`. 4642 4643 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()` 4644 @*/ 4645 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, PetscCtx ctx) 4646 { 4647 Mat Arhs, Brhs; 4648 4649 PetscFunctionBegin; 4650 PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs)); 4651 /* undo the damage caused by shifting */ 4652 PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs)); 4653 PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs)); 4654 PetscCall(MatMult(Arhs, U, F)); 4655 PetscFunctionReturn(PETSC_SUCCESS); 4656 } 4657 4658 /*@C 4659 TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent. 4660 4661 Collective 4662 4663 Input Parameters: 4664 + ts - time stepping context 4665 . t - time at which to evaluate 4666 . U - state at which to evaluate 4667 - ctx - context 4668 4669 Output Parameters: 4670 + A - Jacobian 4671 - B - matrix used to construct the preconditioner, often the same as `A` 4672 4673 Level: intermediate 4674 4675 Note: 4676 This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems. 4677 4678 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()` 4679 @*/ 4680 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, PetscCtx ctx) 4681 { 4682 PetscFunctionBegin; 4683 PetscFunctionReturn(PETSC_SUCCESS); 4684 } 4685 4686 /*@C 4687 TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only 4688 4689 Collective 4690 4691 Input Parameters: 4692 + ts - time stepping context 4693 . t - time at which to evaluate 4694 . U - state at which to evaluate 4695 . Udot - time derivative of state vector 4696 - ctx - context 4697 4698 Output Parameter: 4699 . F - left hand side 4700 4701 Level: intermediate 4702 4703 Notes: 4704 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 4705 user is required to write their own `TSComputeIFunction()`. 4706 This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems. 4707 The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`. 4708 4709 Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U 4710 4711 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()` 4712 @*/ 4713 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, PetscCtx ctx) 4714 { 4715 Mat A, B; 4716 4717 PetscFunctionBegin; 4718 PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL)); 4719 PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE)); 4720 PetscCall(MatMult(A, Udot, F)); 4721 PetscFunctionReturn(PETSC_SUCCESS); 4722 } 4723 4724 /*@C 4725 TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE 4726 4727 Collective 4728 4729 Input Parameters: 4730 + ts - time stepping context 4731 . t - time at which to evaluate 4732 . U - state at which to evaluate 4733 . Udot - time derivative of state vector 4734 . shift - shift to apply 4735 - ctx - context 4736 4737 Output Parameters: 4738 + A - pointer to operator 4739 - B - pointer to matrix from which the preconditioner is built (often `A`) 4740 4741 Level: advanced 4742 4743 Notes: 4744 This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems. 4745 4746 It is only appropriate for problems of the form 4747 4748 $$ 4749 M \dot{U} = F(U,t) 4750 $$ 4751 4752 where M is constant and F is non-stiff. The user must pass M to `TSSetIJacobian()`. The current implementation only 4753 works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing 4754 an implicit operator of the form 4755 4756 $$ 4757 shift*M + J 4758 $$ 4759 4760 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 4761 a copy of M or reassemble it when requested. 4762 4763 .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()` 4764 @*/ 4765 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, PetscCtx ctx) 4766 { 4767 PetscFunctionBegin; 4768 PetscCall(MatScale(A, shift / ts->ijacobian.shift)); 4769 ts->ijacobian.shift = shift; 4770 PetscFunctionReturn(PETSC_SUCCESS); 4771 } 4772 4773 /*@ 4774 TSGetEquationType - Gets the type of the equation that `TS` is solving. 4775 4776 Not Collective 4777 4778 Input Parameter: 4779 . ts - the `TS` context 4780 4781 Output Parameter: 4782 . equation_type - see `TSEquationType` 4783 4784 Level: beginner 4785 4786 .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType` 4787 @*/ 4788 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type) 4789 { 4790 PetscFunctionBegin; 4791 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4792 PetscAssertPointer(equation_type, 2); 4793 *equation_type = ts->equation_type; 4794 PetscFunctionReturn(PETSC_SUCCESS); 4795 } 4796 4797 /*@ 4798 TSSetEquationType - Sets the type of the equation that `TS` is solving. 4799 4800 Not Collective 4801 4802 Input Parameters: 4803 + ts - the `TS` context 4804 - equation_type - see `TSEquationType` 4805 4806 Level: advanced 4807 4808 .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType` 4809 @*/ 4810 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type) 4811 { 4812 PetscFunctionBegin; 4813 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4814 ts->equation_type = equation_type; 4815 PetscFunctionReturn(PETSC_SUCCESS); 4816 } 4817 4818 /*@ 4819 TSGetConvergedReason - Gets the reason the `TS` iteration was stopped. 4820 4821 Not Collective 4822 4823 Input Parameter: 4824 . ts - the `TS` context 4825 4826 Output Parameter: 4827 . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4828 manual pages for the individual convergence tests for complete lists 4829 4830 Level: beginner 4831 4832 Note: 4833 Can only be called after the call to `TSSolve()` is complete. 4834 4835 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4836 @*/ 4837 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason) 4838 { 4839 PetscFunctionBegin; 4840 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4841 PetscAssertPointer(reason, 2); 4842 *reason = ts->reason; 4843 PetscFunctionReturn(PETSC_SUCCESS); 4844 } 4845 4846 /*@ 4847 TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`. 4848 4849 Logically Collective; reason must contain common value 4850 4851 Input Parameters: 4852 + ts - the `TS` context 4853 - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the 4854 manual pages for the individual convergence tests for complete lists 4855 4856 Level: advanced 4857 4858 Note: 4859 Can only be called while `TSSolve()` is active. 4860 4861 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4862 @*/ 4863 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason) 4864 { 4865 PetscFunctionBegin; 4866 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4867 ts->reason = reason; 4868 PetscFunctionReturn(PETSC_SUCCESS); 4869 } 4870 4871 /*@ 4872 TSGetSolveTime - Gets the time after a call to `TSSolve()` 4873 4874 Not Collective 4875 4876 Input Parameter: 4877 . ts - the `TS` context 4878 4879 Output Parameter: 4880 . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()` 4881 4882 Level: beginner 4883 4884 Note: 4885 Can only be called after the call to `TSSolve()` is complete. 4886 4887 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason` 4888 @*/ 4889 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime) 4890 { 4891 PetscFunctionBegin; 4892 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4893 PetscAssertPointer(ftime, 2); 4894 *ftime = ts->solvetime; 4895 PetscFunctionReturn(PETSC_SUCCESS); 4896 } 4897 4898 /*@ 4899 TSGetSNESIterations - Gets the total number of nonlinear iterations 4900 used by the time integrator. 4901 4902 Not Collective 4903 4904 Input Parameter: 4905 . ts - `TS` context 4906 4907 Output Parameter: 4908 . nits - number of nonlinear iterations 4909 4910 Level: intermediate 4911 4912 Note: 4913 This counter is reset to zero for each successive call to `TSSolve()`. 4914 4915 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()` 4916 @*/ 4917 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits) 4918 { 4919 PetscFunctionBegin; 4920 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4921 PetscAssertPointer(nits, 2); 4922 *nits = ts->snes_its; 4923 PetscFunctionReturn(PETSC_SUCCESS); 4924 } 4925 4926 /*@ 4927 TSGetKSPIterations - Gets the total number of linear iterations 4928 used by the time integrator. 4929 4930 Not Collective 4931 4932 Input Parameter: 4933 . ts - `TS` context 4934 4935 Output Parameter: 4936 . lits - number of linear iterations 4937 4938 Level: intermediate 4939 4940 Note: 4941 This counter is reset to zero for each successive call to `TSSolve()`. 4942 4943 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()` 4944 @*/ 4945 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits) 4946 { 4947 PetscFunctionBegin; 4948 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4949 PetscAssertPointer(lits, 2); 4950 *lits = ts->ksp_its; 4951 PetscFunctionReturn(PETSC_SUCCESS); 4952 } 4953 4954 /*@ 4955 TSGetStepRejections - Gets the total number of rejected steps. 4956 4957 Not Collective 4958 4959 Input Parameter: 4960 . ts - `TS` context 4961 4962 Output Parameter: 4963 . rejects - number of steps rejected 4964 4965 Level: intermediate 4966 4967 Note: 4968 This counter is reset to zero for each successive call to `TSSolve()`. 4969 4970 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()` 4971 @*/ 4972 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects) 4973 { 4974 PetscFunctionBegin; 4975 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 4976 PetscAssertPointer(rejects, 2); 4977 *rejects = ts->reject; 4978 PetscFunctionReturn(PETSC_SUCCESS); 4979 } 4980 4981 /*@ 4982 TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS` 4983 4984 Not Collective 4985 4986 Input Parameter: 4987 . ts - `TS` context 4988 4989 Output Parameter: 4990 . fails - number of failed nonlinear solves 4991 4992 Level: intermediate 4993 4994 Note: 4995 This counter is reset to zero for each successive call to `TSSolve()`. 4996 4997 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()` 4998 @*/ 4999 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails) 5000 { 5001 PetscFunctionBegin; 5002 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5003 PetscAssertPointer(fails, 2); 5004 *fails = ts->num_snes_failures; 5005 PetscFunctionReturn(PETSC_SUCCESS); 5006 } 5007 5008 /*@ 5009 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` 5010 5011 Not Collective 5012 5013 Input Parameters: 5014 + ts - `TS` context 5015 - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited 5016 5017 Options Database Key: 5018 . -ts_max_step_rejections - Maximum number of step rejections before a step fails 5019 5020 Level: intermediate 5021 5022 Developer Note: 5023 The options database name is incorrect. 5024 5025 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, 5026 `TSGetConvergedReason()`, `TSSolve()`, `TS_DIVERGED_STEP_REJECTED` 5027 @*/ 5028 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects) 5029 { 5030 PetscFunctionBegin; 5031 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5032 if (rejects == PETSC_UNLIMITED || rejects == -1) { 5033 ts->max_reject = PETSC_UNLIMITED; 5034 } else { 5035 PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections"); 5036 ts->max_reject = rejects; 5037 } 5038 PetscFunctionReturn(PETSC_SUCCESS); 5039 } 5040 5041 /*@ 5042 TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves allowed before `TSSolve()` is ended with a `TSConvergedReason` of `TS_DIVERGED_NONLINEAR_SOLVE` 5043 5044 Not Collective 5045 5046 Input Parameters: 5047 + ts - `TS` context 5048 - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures. 5049 5050 Options Database Key: 5051 . -ts_max_snes_failures - Maximum number of nonlinear solve failures 5052 5053 Level: intermediate 5054 5055 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, 5056 `TSGetConvergedReason()`, `TS_DIVERGED_NONLINEAR_SOLVE`, `TSConvergedReason` 5057 @*/ 5058 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails) 5059 { 5060 PetscFunctionBegin; 5061 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5062 if (fails == PETSC_UNLIMITED || fails == -1) { 5063 ts->max_snes_failures = PETSC_UNLIMITED; 5064 } else { 5065 PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures"); 5066 ts->max_snes_failures = fails; 5067 } 5068 PetscFunctionReturn(PETSC_SUCCESS); 5069 } 5070 5071 /*@ 5072 TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()` 5073 5074 Not Collective 5075 5076 Input Parameters: 5077 + ts - `TS` context 5078 - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure 5079 5080 Options Database Key: 5081 . -ts_error_if_step_fails - Error if no step succeeds 5082 5083 Level: intermediate 5084 5085 .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()` 5086 @*/ 5087 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err) 5088 { 5089 PetscFunctionBegin; 5090 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5091 ts->errorifstepfailed = err; 5092 PetscFunctionReturn(PETSC_SUCCESS); 5093 } 5094 5095 /*@ 5096 TSGetAdapt - Get the adaptive controller context for the current method 5097 5098 Collective if controller has not yet been created 5099 5100 Input Parameter: 5101 . ts - time stepping context 5102 5103 Output Parameter: 5104 . adapt - adaptive controller 5105 5106 Level: intermediate 5107 5108 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()` 5109 @*/ 5110 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt) 5111 { 5112 PetscFunctionBegin; 5113 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5114 PetscAssertPointer(adapt, 2); 5115 if (!ts->adapt) { 5116 PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt)); 5117 PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1)); 5118 } 5119 *adapt = ts->adapt; 5120 PetscFunctionReturn(PETSC_SUCCESS); 5121 } 5122 5123 /*@ 5124 TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller 5125 5126 Logically Collective 5127 5128 Input Parameters: 5129 + ts - time integration context 5130 . atol - scalar absolute tolerances 5131 . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present 5132 . rtol - scalar relative tolerances 5133 - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present 5134 5135 Options Database Keys: 5136 + -ts_rtol <rtol> - relative tolerance for local truncation error 5137 - -ts_atol <atol> - Absolute tolerance for local truncation error 5138 5139 Level: beginner 5140 5141 Notes: 5142 `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value 5143 or the default value from when the object's type was set. 5144 5145 With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error 5146 (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be 5147 computed only for the differential or the algebraic part then this can be done using the vector of 5148 tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the 5149 differential part and infinity for the algebraic part, the LTE calculation will include only the 5150 differential variables. 5151 5152 Fortran Note: 5153 Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`. 5154 5155 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()` 5156 @*/ 5157 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol) 5158 { 5159 PetscFunctionBegin; 5160 if (atol == (PetscReal)PETSC_DETERMINE) { 5161 ts->atol = ts->default_atol; 5162 } else if (atol != (PetscReal)PETSC_CURRENT) { 5163 PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol); 5164 ts->atol = atol; 5165 } 5166 5167 if (vatol) { 5168 PetscCall(PetscObjectReference((PetscObject)vatol)); 5169 PetscCall(VecDestroy(&ts->vatol)); 5170 ts->vatol = vatol; 5171 } 5172 5173 if (rtol == (PetscReal)PETSC_DETERMINE) { 5174 ts->rtol = ts->default_rtol; 5175 } else if (rtol != (PetscReal)PETSC_CURRENT) { 5176 PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol); 5177 ts->rtol = rtol; 5178 } 5179 5180 if (vrtol) { 5181 PetscCall(PetscObjectReference((PetscObject)vrtol)); 5182 PetscCall(VecDestroy(&ts->vrtol)); 5183 ts->vrtol = vrtol; 5184 } 5185 PetscFunctionReturn(PETSC_SUCCESS); 5186 } 5187 5188 /*@ 5189 TSGetTolerances - Get tolerances for local truncation error when using adaptive controller 5190 5191 Logically Collective 5192 5193 Input Parameter: 5194 . ts - time integration context 5195 5196 Output Parameters: 5197 + atol - scalar absolute tolerances, `NULL` to ignore 5198 . vatol - vector of absolute tolerances, `NULL` to ignore 5199 . rtol - scalar relative tolerances, `NULL` to ignore 5200 - vrtol - vector of relative tolerances, `NULL` to ignore 5201 5202 Level: beginner 5203 5204 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()` 5205 @*/ 5206 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol) 5207 { 5208 PetscFunctionBegin; 5209 if (atol) *atol = ts->atol; 5210 if (vatol) *vatol = ts->vatol; 5211 if (rtol) *rtol = ts->rtol; 5212 if (vrtol) *vrtol = ts->vrtol; 5213 PetscFunctionReturn(PETSC_SUCCESS); 5214 } 5215 5216 /*@ 5217 TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances 5218 5219 Collective 5220 5221 Input Parameters: 5222 + ts - time stepping context 5223 . U - state vector, usually ts->vec_sol 5224 . Y - state vector to be compared to U 5225 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5226 5227 Output Parameters: 5228 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5229 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5230 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5231 5232 Options Database Key: 5233 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5234 5235 Level: developer 5236 5237 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()` 5238 @*/ 5239 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5240 { 5241 PetscInt norma_loc, norm_loc, normr_loc; 5242 5243 PetscFunctionBegin; 5244 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5245 PetscValidHeaderSpecific(U, VEC_CLASSID, 2); 5246 PetscValidHeaderSpecific(Y, VEC_CLASSID, 3); 5247 PetscValidLogicalCollectiveEnum(ts, wnormtype, 4); 5248 PetscAssertPointer(norm, 5); 5249 PetscAssertPointer(norma, 6); 5250 PetscAssertPointer(normr, 7); 5251 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)); 5252 if (wnormtype == NORM_2) { 5253 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5254 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5255 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5256 } 5257 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5258 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5259 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5260 PetscFunctionReturn(PETSC_SUCCESS); 5261 } 5262 5263 /*@ 5264 TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances 5265 5266 Collective 5267 5268 Input Parameters: 5269 + ts - time stepping context 5270 . E - error vector 5271 . U - state vector, usually ts->vec_sol 5272 . Y - state vector, previous time step 5273 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY` 5274 5275 Output Parameters: 5276 + norm - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances 5277 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user 5278 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user 5279 5280 Options Database Key: 5281 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY 5282 5283 Level: developer 5284 5285 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()` 5286 @*/ 5287 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) 5288 { 5289 PetscInt norma_loc, norm_loc, normr_loc; 5290 5291 PetscFunctionBegin; 5292 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5293 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)); 5294 if (wnormtype == NORM_2) { 5295 if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc); 5296 if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc); 5297 if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc); 5298 } 5299 PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm"); 5300 PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma"); 5301 PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr"); 5302 PetscFunctionReturn(PETSC_SUCCESS); 5303 } 5304 5305 /*@ 5306 TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler 5307 5308 Logically Collective 5309 5310 Input Parameters: 5311 + ts - time stepping context 5312 - cfltime - maximum stable time step if using forward Euler (value can be different on each process) 5313 5314 Note: 5315 After calling this function, the global CFL time can be obtained by calling TSGetCFLTime() 5316 5317 Level: intermediate 5318 5319 .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL` 5320 @*/ 5321 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime) 5322 { 5323 PetscFunctionBegin; 5324 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5325 ts->cfltime_local = cfltime; 5326 ts->cfltime = -1.; 5327 PetscFunctionReturn(PETSC_SUCCESS); 5328 } 5329 5330 /*@ 5331 TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler 5332 5333 Collective 5334 5335 Input Parameter: 5336 . ts - time stepping context 5337 5338 Output Parameter: 5339 . cfltime - maximum stable time step for forward Euler 5340 5341 Level: advanced 5342 5343 .seealso: [](ch_ts), `TSSetCFLTimeLocal()` 5344 @*/ 5345 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime) 5346 { 5347 PetscFunctionBegin; 5348 if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts))); 5349 *cfltime = ts->cfltime; 5350 PetscFunctionReturn(PETSC_SUCCESS); 5351 } 5352 5353 /*@ 5354 TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu 5355 5356 Input Parameters: 5357 + ts - the `TS` context. 5358 . xl - lower bound. 5359 - xu - upper bound. 5360 5361 Level: advanced 5362 5363 Note: 5364 If this routine is not called then the lower and upper bounds are set to 5365 `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`. 5366 5367 .seealso: [](ch_ts), `TS` 5368 @*/ 5369 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) 5370 { 5371 SNES snes; 5372 5373 PetscFunctionBegin; 5374 PetscCall(TSGetSNES(ts, &snes)); 5375 PetscCall(SNESVISetVariableBounds(snes, xl, xu)); 5376 PetscFunctionReturn(PETSC_SUCCESS); 5377 } 5378 5379 /*@ 5380 TSComputeLinearStability - computes the linear stability function at a point 5381 5382 Collective 5383 5384 Input Parameters: 5385 + ts - the `TS` context 5386 . xr - real part of input argument 5387 - xi - imaginary part of input argument 5388 5389 Output Parameters: 5390 + yr - real part of function value 5391 - yi - imaginary part of function value 5392 5393 Level: developer 5394 5395 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()` 5396 @*/ 5397 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) 5398 { 5399 PetscFunctionBegin; 5400 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5401 PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi); 5402 PetscFunctionReturn(PETSC_SUCCESS); 5403 } 5404 5405 /*@ 5406 TSRestartStep - Flags the solver to restart the next step 5407 5408 Collective 5409 5410 Input Parameter: 5411 . ts - the `TS` context obtained from `TSCreate()` 5412 5413 Level: advanced 5414 5415 Notes: 5416 Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of 5417 discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution 5418 vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For 5419 the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce 5420 discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with 5421 discontinuous source terms). 5422 5423 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()` 5424 @*/ 5425 PetscErrorCode TSRestartStep(TS ts) 5426 { 5427 PetscFunctionBegin; 5428 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5429 ts->steprestart = PETSC_TRUE; 5430 PetscFunctionReturn(PETSC_SUCCESS); 5431 } 5432 5433 /*@ 5434 TSRollBack - Rolls back one time step 5435 5436 Collective 5437 5438 Input Parameter: 5439 . ts - the `TS` context obtained from `TSCreate()` 5440 5441 Level: advanced 5442 5443 .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()` 5444 @*/ 5445 PetscErrorCode TSRollBack(TS ts) 5446 { 5447 PetscFunctionBegin; 5448 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5449 PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called"); 5450 PetscTryTypeMethod(ts, rollback); 5451 PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol)); 5452 ts->time_step = ts->ptime - ts->ptime_prev; 5453 ts->ptime = ts->ptime_prev; 5454 ts->ptime_prev = ts->ptime_prev_rollback; 5455 ts->steps--; 5456 ts->steprollback = PETSC_TRUE; 5457 PetscFunctionReturn(PETSC_SUCCESS); 5458 } 5459 5460 /*@ 5461 TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step 5462 5463 Not collective 5464 5465 Input Parameter: 5466 . ts - the `TS` context obtained from `TSCreate()` 5467 5468 Output Parameter: 5469 . flg - the rollback flag 5470 5471 Level: advanced 5472 5473 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()` 5474 @*/ 5475 PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg) 5476 { 5477 PetscFunctionBegin; 5478 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5479 PetscAssertPointer(flg, 2); 5480 *flg = ts->steprollback; 5481 PetscFunctionReturn(PETSC_SUCCESS); 5482 } 5483 5484 /*@ 5485 TSGetStepResize - Get the internal flag indicating if the current step is after a resize. 5486 5487 Not collective 5488 5489 Input Parameter: 5490 . ts - the `TS` context obtained from `TSCreate()` 5491 5492 Output Parameter: 5493 . flg - the resize flag 5494 5495 Level: advanced 5496 5497 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()` 5498 @*/ 5499 PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg) 5500 { 5501 PetscFunctionBegin; 5502 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5503 PetscAssertPointer(flg, 2); 5504 *flg = ts->stepresize; 5505 PetscFunctionReturn(PETSC_SUCCESS); 5506 } 5507 5508 /*@ 5509 TSGetStages - Get the number of stages and stage values 5510 5511 Input Parameter: 5512 . ts - the `TS` context obtained from `TSCreate()` 5513 5514 Output Parameters: 5515 + ns - the number of stages 5516 - Y - the current stage vectors 5517 5518 Level: advanced 5519 5520 Note: 5521 Both `ns` and `Y` can be `NULL`. 5522 5523 .seealso: [](ch_ts), `TS`, `TSCreate()` 5524 @*/ 5525 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y) 5526 { 5527 PetscFunctionBegin; 5528 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5529 if (ns) PetscAssertPointer(ns, 2); 5530 if (Y) PetscAssertPointer(Y, 3); 5531 if (!ts->ops->getstages) { 5532 if (ns) *ns = 0; 5533 if (Y) *Y = NULL; 5534 } else PetscUseTypeMethod(ts, getstages, ns, Y); 5535 PetscFunctionReturn(PETSC_SUCCESS); 5536 } 5537 5538 /*@C 5539 TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity. 5540 5541 Collective 5542 5543 Input Parameters: 5544 + ts - the `TS` context 5545 . t - current timestep 5546 . U - state vector 5547 . Udot - time derivative of state vector 5548 . shift - shift to apply, see note below 5549 - ctx - an optional user context 5550 5551 Output Parameters: 5552 + J - Jacobian matrix (not altered in this routine) 5553 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`) 5554 5555 Level: intermediate 5556 5557 Notes: 5558 If F(t,U,Udot)=0 is the DAE, the required Jacobian is 5559 5560 dF/dU + shift*dF/dUdot 5561 5562 Most users should not need to explicitly call this routine, as it 5563 is used internally within the nonlinear solvers. 5564 5565 This will first try to get the coloring from the `DM`. If the `DM` type has no coloring 5566 routine, then it will try to get the coloring from the matrix. This requires that the 5567 matrix have nonzero entries precomputed. 5568 5569 .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 5570 @*/ 5571 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, PetscCtx ctx) 5572 { 5573 SNES snes; 5574 MatFDColoring color; 5575 PetscBool hascolor, matcolor = PETSC_FALSE; 5576 5577 PetscFunctionBegin; 5578 PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL)); 5579 PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color)); 5580 if (!color) { 5581 DM dm; 5582 ISColoring iscoloring; 5583 5584 PetscCall(TSGetDM(ts, &dm)); 5585 PetscCall(DMHasColoring(dm, &hascolor)); 5586 if (hascolor && !matcolor) { 5587 PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring)); 5588 PetscCall(MatFDColoringCreate(B, iscoloring, &color)); 5589 PetscCall(MatFDColoringSetFunction(color, (MatFDColoringFn *)SNESTSFormFunction, (void *)ts)); 5590 PetscCall(MatFDColoringSetFromOptions(color)); 5591 PetscCall(MatFDColoringSetUp(B, iscoloring, color)); 5592 PetscCall(ISColoringDestroy(&iscoloring)); 5593 } else { 5594 MatColoring mc; 5595 5596 PetscCall(MatColoringCreate(B, &mc)); 5597 PetscCall(MatColoringSetDistance(mc, 2)); 5598 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 5599 PetscCall(MatColoringSetFromOptions(mc)); 5600 PetscCall(MatColoringApply(mc, &iscoloring)); 5601 PetscCall(MatColoringDestroy(&mc)); 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 } 5608 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color)); 5609 PetscCall(PetscObjectDereference((PetscObject)color)); 5610 } 5611 PetscCall(TSGetSNES(ts, &snes)); 5612 PetscCall(MatFDColoringApply(B, color, U, snes)); 5613 if (J != B) { 5614 PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 5615 PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 5616 } 5617 PetscFunctionReturn(PETSC_SUCCESS); 5618 } 5619 5620 /*@C 5621 TSSetFunctionDomainError - Set a function that tests if the current state vector is valid 5622 5623 Logically collective 5624 5625 Input Parameters: 5626 + ts - the `TS` context 5627 - func - function called within `TSFunctionDomainError()` 5628 5629 Calling sequence of `func`: 5630 + ts - the `TS` context 5631 . time - the current time (of the stage) 5632 . state - the state to check if it is valid 5633 - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable 5634 5635 Level: intermediate 5636 5637 Notes: 5638 `accept` must be collectively specified. 5639 If an implicit ODE solver is being used then, in addition to providing this routine, the 5640 user's code should call `SNESSetFunctionDomainError()` when domain errors occur during 5641 function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`. 5642 Use `TSGetSNES()` to obtain the `SNES` object 5643 5644 Developer Notes: 5645 The naming of this function is inconsistent with the `SNESSetFunctionDomainError()` 5646 since one takes a function pointer and the other does not. 5647 5648 .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()` 5649 @*/ 5650 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept)) 5651 { 5652 PetscFunctionBegin; 5653 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5654 ts->functiondomainerror = func; 5655 PetscFunctionReturn(PETSC_SUCCESS); 5656 } 5657 5658 /*@ 5659 TSFunctionDomainError - Checks if the current state is valid 5660 5661 Collective 5662 5663 Input Parameters: 5664 + ts - the `TS` context 5665 . stagetime - time of the simulation 5666 - Y - state vector to check. 5667 5668 Output Parameter: 5669 . accept - Set to `PETSC_FALSE` if the current state vector is valid. 5670 5671 Level: developer 5672 5673 Note: 5674 This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`) 5675 to check if the current state is valid. 5676 5677 .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()` 5678 @*/ 5679 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept) 5680 { 5681 PetscFunctionBegin; 5682 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5683 PetscValidLogicalCollectiveReal(ts, stagetime, 2); 5684 PetscValidHeaderSpecific(Y, VEC_CLASSID, 3); 5685 PetscAssertPointer(accept, 4); 5686 *accept = PETSC_TRUE; 5687 if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept)); 5688 PetscFunctionReturn(PETSC_SUCCESS); 5689 } 5690 5691 /*@ 5692 TSClone - This function clones a time step `TS` object. 5693 5694 Collective 5695 5696 Input Parameter: 5697 . tsin - The input `TS` 5698 5699 Output Parameter: 5700 . tsout - The output `TS` (cloned) 5701 5702 Level: developer 5703 5704 Notes: 5705 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. 5706 It will likely be replaced in the future with a mechanism of switching methods on the fly. 5707 5708 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 5709 .vb 5710 SNES snes_dup = NULL; 5711 TSGetSNES(ts,&snes_dup); 5712 TSSetSNES(ts,snes_dup); 5713 .ve 5714 5715 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()` 5716 @*/ 5717 PetscErrorCode TSClone(TS tsin, TS *tsout) 5718 { 5719 TS t; 5720 SNES snes_start; 5721 DM dm; 5722 TSType type; 5723 5724 PetscFunctionBegin; 5725 PetscAssertPointer(tsin, 1); 5726 *tsout = NULL; 5727 5728 PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView)); 5729 5730 /* General TS description */ 5731 t->numbermonitors = 0; 5732 t->setupcalled = PETSC_FALSE; 5733 t->ksp_its = 0; 5734 t->snes_its = 0; 5735 t->nwork = 0; 5736 t->rhsjacobian.time = PETSC_MIN_REAL; 5737 t->rhsjacobian.scale = 1.; 5738 t->ijacobian.shift = 1.; 5739 5740 PetscCall(TSGetSNES(tsin, &snes_start)); 5741 PetscCall(TSSetSNES(t, snes_start)); 5742 5743 PetscCall(TSGetDM(tsin, &dm)); 5744 PetscCall(TSSetDM(t, dm)); 5745 5746 t->adapt = tsin->adapt; 5747 PetscCall(PetscObjectReference((PetscObject)t->adapt)); 5748 5749 t->trajectory = tsin->trajectory; 5750 PetscCall(PetscObjectReference((PetscObject)t->trajectory)); 5751 5752 t->event = tsin->event; 5753 if (t->event) t->event->refct++; 5754 5755 t->problem_type = tsin->problem_type; 5756 t->ptime = tsin->ptime; 5757 t->ptime_prev = tsin->ptime_prev; 5758 t->time_step = tsin->time_step; 5759 t->max_time = tsin->max_time; 5760 t->steps = tsin->steps; 5761 t->max_steps = tsin->max_steps; 5762 t->equation_type = tsin->equation_type; 5763 t->atol = tsin->atol; 5764 t->rtol = tsin->rtol; 5765 t->max_snes_failures = tsin->max_snes_failures; 5766 t->max_reject = tsin->max_reject; 5767 t->errorifstepfailed = tsin->errorifstepfailed; 5768 5769 PetscCall(TSGetType(tsin, &type)); 5770 PetscCall(TSSetType(t, type)); 5771 5772 t->vec_sol = NULL; 5773 5774 t->cfltime = tsin->cfltime; 5775 t->cfltime_local = tsin->cfltime_local; 5776 t->exact_final_time = tsin->exact_final_time; 5777 5778 t->ops[0] = tsin->ops[0]; 5779 5780 if (((PetscObject)tsin)->fortran_func_pointers) { 5781 PetscInt i; 5782 PetscCall(PetscMalloc((10) * sizeof(PetscFortranCallbackFn *), &((PetscObject)t)->fortran_func_pointers)); 5783 for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i]; 5784 } 5785 *tsout = t; 5786 PetscFunctionReturn(PETSC_SUCCESS); 5787 } 5788 5789 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(PetscCtx ctx, Vec x, Vec y) 5790 { 5791 TS ts = (TS)ctx; 5792 5793 PetscFunctionBegin; 5794 PetscCall(TSComputeRHSFunction(ts, 0, x, y)); 5795 PetscFunctionReturn(PETSC_SUCCESS); 5796 } 5797 5798 /*@ 5799 TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5800 5801 Logically Collective 5802 5803 Input Parameter: 5804 . ts - the time stepping routine 5805 5806 Output Parameter: 5807 . flg - `PETSC_TRUE` if the multiply is likely correct 5808 5809 Options Database Key: 5810 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator 5811 5812 Level: advanced 5813 5814 Note: 5815 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5816 5817 .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()` 5818 @*/ 5819 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg) 5820 { 5821 Mat J, B; 5822 TSRHSJacobianFn *func; 5823 void *ctx; 5824 5825 PetscFunctionBegin; 5826 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5827 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5828 PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5829 PetscFunctionReturn(PETSC_SUCCESS); 5830 } 5831 5832 /*@ 5833 TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function. 5834 5835 Logically Collective 5836 5837 Input Parameter: 5838 . ts - the time stepping routine 5839 5840 Output Parameter: 5841 . flg - `PETSC_TRUE` if the multiply is likely correct 5842 5843 Options Database Key: 5844 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator 5845 5846 Level: advanced 5847 5848 Notes: 5849 This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian 5850 5851 .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()` 5852 @*/ 5853 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg) 5854 { 5855 Mat J, B; 5856 void *ctx; 5857 TSRHSJacobianFn *func; 5858 5859 PetscFunctionBegin; 5860 PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx)); 5861 PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx)); 5862 PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg)); 5863 PetscFunctionReturn(PETSC_SUCCESS); 5864 } 5865 5866 /*@ 5867 TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used. 5868 5869 Logically Collective 5870 5871 Input Parameters: 5872 + ts - timestepping context 5873 - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5874 5875 Options Database Key: 5876 . -ts_use_splitrhsfunction - <true,false> 5877 5878 Level: intermediate 5879 5880 Note: 5881 This is only for multirate methods 5882 5883 .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()` 5884 @*/ 5885 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) 5886 { 5887 PetscFunctionBegin; 5888 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5889 ts->use_splitrhsfunction = use_splitrhsfunction; 5890 PetscFunctionReturn(PETSC_SUCCESS); 5891 } 5892 5893 /*@ 5894 TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used. 5895 5896 Not Collective 5897 5898 Input Parameter: 5899 . ts - timestepping context 5900 5901 Output Parameter: 5902 . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used 5903 5904 Level: intermediate 5905 5906 .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()` 5907 @*/ 5908 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) 5909 { 5910 PetscFunctionBegin; 5911 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5912 *use_splitrhsfunction = ts->use_splitrhsfunction; 5913 PetscFunctionReturn(PETSC_SUCCESS); 5914 } 5915 5916 /*@ 5917 TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix. 5918 5919 Logically Collective 5920 5921 Input Parameters: 5922 + ts - the time-stepper 5923 - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`) 5924 5925 Level: intermediate 5926 5927 Note: 5928 When the relationship between the nonzero structures is known and supplied the solution process can be much faster 5929 5930 .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure` 5931 @*/ 5932 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str) 5933 { 5934 PetscFunctionBegin; 5935 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5936 ts->axpy_pattern = str; 5937 PetscFunctionReturn(PETSC_SUCCESS); 5938 } 5939 5940 /*@ 5941 TSSetEvaluationTimes - sets the evaluation points. The solution will be computed and stored for each time requested 5942 5943 Collective 5944 5945 Input Parameters: 5946 + ts - the time-stepper 5947 . n - number of the time points 5948 - time_points - array of the time points, must be increasing 5949 5950 Options Database Key: 5951 . -ts_eval_times <t0,...tn> - Sets the evaluation times 5952 5953 Level: intermediate 5954 5955 Notes: 5956 The elements in `time_points` must be all increasing. They correspond to the intermediate points to be saved. 5957 5958 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 5959 5960 The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using evaluation times may 5961 pressure the memory system when using a large number of time points. 5962 5963 .seealso: [](ch_ts), `TS`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`, `TSSetTimeSpan()` 5964 @*/ 5965 PetscErrorCode TSSetEvaluationTimes(TS ts, PetscInt n, PetscReal time_points[]) 5966 { 5967 PetscBool is_sorted; 5968 5969 PetscFunctionBegin; 5970 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 5971 if (ts->eval_times) { // Reset eval_times 5972 ts->eval_times->sol_idx = 0; 5973 ts->eval_times->time_point_idx = 0; 5974 if (n != ts->eval_times->num_time_points) { 5975 PetscCall(PetscFree(ts->eval_times->time_points)); 5976 PetscCall(PetscFree(ts->eval_times->sol_times)); 5977 PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs)); 5978 } else { 5979 PetscCall(PetscArrayzero(ts->eval_times->sol_times, n)); 5980 for (PetscInt i = 0; i < n; i++) PetscCall(VecZeroEntries(ts->eval_times->sol_vecs[i])); 5981 } 5982 } else { // Create/initialize eval_times 5983 TSEvaluationTimes eval_times; 5984 PetscCall(PetscNew(&eval_times)); 5985 PetscCall(PetscMalloc1(n, &eval_times->time_points)); 5986 PetscCall(PetscMalloc1(n, &eval_times->sol_times)); 5987 eval_times->reltol = 1e-6; 5988 eval_times->abstol = 10 * PETSC_MACHINE_EPSILON; 5989 eval_times->worktol = 0; 5990 ts->eval_times = eval_times; 5991 } 5992 ts->eval_times->num_time_points = n; 5993 PetscCall(PetscSortedReal(n, time_points, &is_sorted)); 5994 PetscCheck(is_sorted, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "time_points array must be sorted"); 5995 PetscCall(PetscArraycpy(ts->eval_times->time_points, time_points, n)); 5996 // Note: ts->vec_sol not guaranteed to exist, so ts->eval_times->sol_vecs allocated at TSSolve time 5997 PetscFunctionReturn(PETSC_SUCCESS); 5998 } 5999 6000 /*@C 6001 TSGetEvaluationTimes - gets the evaluation times set with `TSSetEvaluationTimes()` 6002 6003 Not Collective 6004 6005 Input Parameter: 6006 . ts - the time-stepper 6007 6008 Output Parameters: 6009 + n - number of the time points 6010 - time_points - array of the time points 6011 6012 Level: beginner 6013 6014 Note: 6015 The values obtained are valid until the `TS` object is destroyed. 6016 6017 Both `n` and `time_points` can be `NULL`. 6018 6019 Also used to see time points set by `TSSetTimeSpan()`. 6020 6021 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationSolutions()` 6022 @*/ 6023 PetscErrorCode TSGetEvaluationTimes(TS ts, PetscInt *n, const PetscReal *time_points[]) 6024 { 6025 PetscFunctionBegin; 6026 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6027 if (n) PetscAssertPointer(n, 2); 6028 if (time_points) PetscAssertPointer(time_points, 3); 6029 if (!ts->eval_times) { 6030 if (n) *n = 0; 6031 if (time_points) *time_points = NULL; 6032 } else { 6033 if (n) *n = ts->eval_times->num_time_points; 6034 if (time_points) *time_points = ts->eval_times->time_points; 6035 } 6036 PetscFunctionReturn(PETSC_SUCCESS); 6037 } 6038 6039 /*@C 6040 TSGetEvaluationSolutions - Get the number of solutions and the solutions at the evaluation time points specified 6041 6042 Input Parameter: 6043 . ts - the `TS` context obtained from `TSCreate()` 6044 6045 Output Parameters: 6046 + nsol - the number of solutions 6047 . sol_times - array of solution times corresponding to the solution vectors. See note below 6048 - Sols - the solution vectors 6049 6050 Level: intermediate 6051 6052 Notes: 6053 Both `nsol` and `Sols` can be `NULL`. 6054 6055 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()`. 6056 For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain evaluation times. 6057 6058 Also used to see view solutions requested by `TSSetTimeSpan()`. 6059 6060 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()` 6061 @*/ 6062 PetscErrorCode TSGetEvaluationSolutions(TS ts, PetscInt *nsol, const PetscReal *sol_times[], Vec *Sols[]) 6063 { 6064 PetscFunctionBegin; 6065 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6066 if (nsol) PetscAssertPointer(nsol, 2); 6067 if (sol_times) PetscAssertPointer(sol_times, 3); 6068 if (Sols) PetscAssertPointer(Sols, 4); 6069 if (!ts->eval_times) { 6070 if (nsol) *nsol = 0; 6071 if (sol_times) *sol_times = NULL; 6072 if (Sols) *Sols = NULL; 6073 } else { 6074 if (nsol) *nsol = ts->eval_times->sol_idx; 6075 if (sol_times) *sol_times = ts->eval_times->sol_times; 6076 if (Sols) *Sols = ts->eval_times->sol_vecs; 6077 } 6078 PetscFunctionReturn(PETSC_SUCCESS); 6079 } 6080 6081 /*@ 6082 TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span 6083 6084 Collective 6085 6086 Input Parameters: 6087 + ts - the time-stepper 6088 . n - number of the time points (>=2) 6089 - 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. 6090 6091 Options Database Key: 6092 . -ts_time_span <t0,...tf> - Sets the time span 6093 6094 Level: intermediate 6095 6096 Notes: 6097 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. 6098 6099 The elements in `span_times` must be all increasing. They correspond to the intermediate points to be saved. 6100 6101 `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified. 6102 6103 The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using time span may 6104 pressure the memory system when using a large number of span points. 6105 6106 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()` 6107 @*/ 6108 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal span_times[]) 6109 { 6110 PetscFunctionBegin; 6111 PetscValidHeaderSpecific(ts, TS_CLASSID, 1); 6112 PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n); 6113 PetscCall(TSSetEvaluationTimes(ts, n, span_times)); 6114 PetscCall(TSSetTime(ts, span_times[0])); 6115 PetscCall(TSSetMaxTime(ts, span_times[n - 1])); 6116 PetscFunctionReturn(PETSC_SUCCESS); 6117 } 6118 6119 /*@ 6120 TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information. 6121 6122 Collective 6123 6124 Input Parameters: 6125 + ts - the `TS` context 6126 . J - Jacobian matrix (not altered in this routine) 6127 - B - newly computed Jacobian matrix to use with preconditioner 6128 6129 Level: intermediate 6130 6131 Notes: 6132 This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains 6133 many constant zeros entries, which is typically the case when the matrix is generated by a `DM` 6134 and multiple fields are involved. 6135 6136 Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity 6137 structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can 6138 usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian. 6139 `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`. 6140 6141 .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()` 6142 @*/ 6143 PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B) 6144 { 6145 MatColoring mc = NULL; 6146 ISColoring iscoloring = NULL; 6147 MatFDColoring matfdcoloring = NULL; 6148 6149 PetscFunctionBegin; 6150 /* Generate new coloring after eliminating zeros in the matrix */ 6151 PetscCall(MatEliminateZeros(B, PETSC_TRUE)); 6152 PetscCall(MatColoringCreate(B, &mc)); 6153 PetscCall(MatColoringSetDistance(mc, 2)); 6154 PetscCall(MatColoringSetType(mc, MATCOLORINGSL)); 6155 PetscCall(MatColoringSetFromOptions(mc)); 6156 PetscCall(MatColoringApply(mc, &iscoloring)); 6157 PetscCall(MatColoringDestroy(&mc)); 6158 /* Replace the old coloring with the new one */ 6159 PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring)); 6160 PetscCall(MatFDColoringSetFunction(matfdcoloring, (MatFDColoringFn *)SNESTSFormFunction, (void *)ts)); 6161 PetscCall(MatFDColoringSetFromOptions(matfdcoloring)); 6162 PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring)); 6163 PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring)); 6164 PetscCall(PetscObjectDereference((PetscObject)matfdcoloring)); 6165 PetscCall(ISColoringDestroy(&iscoloring)); 6166 PetscFunctionReturn(PETSC_SUCCESS); 6167 } 6168