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