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