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