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