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