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