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