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