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