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