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