xref: /petsc/src/ts/interface/ts.c (revision 6e415bd26dfd0d33b8d7233bdee8a51de4844a26)
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, interpolate solution to the exact final time,
2140   or just return at the final time `TS` computed.
2141 
2142   Logically Collective
2143 
2144   Input Parameters:
2145 + ts     - the time-step context
2146 - eftopt - exact final time option
2147 .vb
2148   TS_EXACTFINALTIME_STEPOVER    - Don't do anything if final time is exceeded
2149   TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time
2150   TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to match the final time
2151 .ve
2152 
2153   Options Database Key:
2154 . -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step at runtime
2155 
2156   Level: beginner
2157 
2158   Note:
2159   If you use the option `TS_EXACTFINALTIME_STEPOVER` the solution may be at a very different time
2160   then the final time you selected.
2161 
2162 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSGetExactFinalTime()`
2163 @*/
2164 PetscErrorCode TSSetExactFinalTime(TS ts, TSExactFinalTimeOption eftopt)
2165 {
2166   PetscFunctionBegin;
2167   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2168   PetscValidLogicalCollectiveEnum(ts, eftopt, 2);
2169   ts->exact_final_time = eftopt;
2170   PetscFunctionReturn(PETSC_SUCCESS);
2171 }
2172 
2173 /*@
2174   TSGetExactFinalTime - Gets the exact final time option set with `TSSetExactFinalTime()`
2175 
2176   Not Collective
2177 
2178   Input Parameter:
2179 . ts - the `TS` context
2180 
2181   Output Parameter:
2182 . eftopt - exact final time option
2183 
2184   Level: beginner
2185 
2186 .seealso: [](ch_ts), `TS`, `TSExactFinalTimeOption`, `TSSetExactFinalTime()`
2187 @*/
2188 PetscErrorCode TSGetExactFinalTime(TS ts, TSExactFinalTimeOption *eftopt)
2189 {
2190   PetscFunctionBegin;
2191   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2192   PetscAssertPointer(eftopt, 2);
2193   *eftopt = ts->exact_final_time;
2194   PetscFunctionReturn(PETSC_SUCCESS);
2195 }
2196 
2197 /*@
2198   TSGetTimeStep - Gets the current timestep size.
2199 
2200   Not Collective
2201 
2202   Input Parameter:
2203 . ts - the `TS` context obtained from `TSCreate()`
2204 
2205   Output Parameter:
2206 . dt - the current timestep size
2207 
2208   Level: intermediate
2209 
2210 .seealso: [](ch_ts), `TS`, `TSSetTimeStep()`, `TSGetTime()`
2211 @*/
2212 PetscErrorCode TSGetTimeStep(TS ts, PetscReal *dt)
2213 {
2214   PetscFunctionBegin;
2215   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2216   PetscAssertPointer(dt, 2);
2217   *dt = ts->time_step;
2218   PetscFunctionReturn(PETSC_SUCCESS);
2219 }
2220 
2221 /*@
2222   TSGetSolution - Returns the solution at the present timestep. It
2223   is valid to call this routine inside the function that you are evaluating
2224   in order to move to the new timestep. This vector not changed until
2225   the solution at the next timestep has been calculated.
2226 
2227   Not Collective, but v returned is parallel if ts is parallel
2228 
2229   Input Parameter:
2230 . ts - the `TS` context obtained from `TSCreate()`
2231 
2232   Output Parameter:
2233 . v - the vector containing the solution
2234 
2235   Level: intermediate
2236 
2237   Note:
2238   If you used `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`); this does not return the solution at the requested
2239   final time. It returns the solution at the next timestep.
2240 
2241 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetSolutionComponents()`, `TSSetSolutionFunction()`
2242 @*/
2243 PetscErrorCode TSGetSolution(TS ts, Vec *v)
2244 {
2245   PetscFunctionBegin;
2246   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2247   PetscAssertPointer(v, 2);
2248   *v = ts->vec_sol;
2249   PetscFunctionReturn(PETSC_SUCCESS);
2250 }
2251 
2252 /*@
2253   TSGetSolutionComponents - Returns any solution components at the present
2254   timestep, if available for the time integration method being used.
2255   Solution components are quantities that share the same size and
2256   structure as the solution vector.
2257 
2258   Not Collective, but v returned is parallel if ts is parallel
2259 
2260   Input Parameters:
2261 + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2262 . n  - If v is `NULL`, then the number of solution components is
2263        returned through n, else the n-th solution component is
2264        returned in v.
2265 - v  - the vector containing the n-th solution component
2266        (may be `NULL` to use this function to find out
2267         the number of solutions components).
2268 
2269   Level: advanced
2270 
2271 .seealso: [](ch_ts), `TS`, `TSGetSolution()`
2272 @*/
2273 PetscErrorCode TSGetSolutionComponents(TS ts, PetscInt *n, Vec *v)
2274 {
2275   PetscFunctionBegin;
2276   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2277   if (!ts->ops->getsolutioncomponents) *n = 0;
2278   else PetscUseTypeMethod(ts, getsolutioncomponents, n, v);
2279   PetscFunctionReturn(PETSC_SUCCESS);
2280 }
2281 
2282 /*@
2283   TSGetAuxSolution - Returns an auxiliary solution at the present
2284   timestep, if available for the time integration method being used.
2285 
2286   Not Collective, but v returned is parallel if ts is parallel
2287 
2288   Input Parameters:
2289 + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2290 - v  - the vector containing the auxiliary solution
2291 
2292   Level: intermediate
2293 
2294 .seealso: [](ch_ts), `TS`, `TSGetSolution()`
2295 @*/
2296 PetscErrorCode TSGetAuxSolution(TS ts, Vec *v)
2297 {
2298   PetscFunctionBegin;
2299   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2300   if (ts->ops->getauxsolution) PetscUseTypeMethod(ts, getauxsolution, v);
2301   else PetscCall(VecZeroEntries(*v));
2302   PetscFunctionReturn(PETSC_SUCCESS);
2303 }
2304 
2305 /*@
2306   TSGetTimeError - Returns the estimated error vector, if the chosen
2307   `TSType` has an error estimation functionality and `TSSetTimeError()` was called
2308 
2309   Not Collective, but v returned is parallel if ts is parallel
2310 
2311   Input Parameters:
2312 + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2313 . n  - current estimate (n=0) or previous one (n=-1)
2314 - v  - the vector containing the error (same size as the solution).
2315 
2316   Level: intermediate
2317 
2318   Note:
2319   MUST call after `TSSetUp()`
2320 
2321 .seealso: [](ch_ts), `TSGetSolution()`, `TSSetTimeError()`
2322 @*/
2323 PetscErrorCode TSGetTimeError(TS ts, PetscInt n, Vec *v)
2324 {
2325   PetscFunctionBegin;
2326   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2327   if (ts->ops->gettimeerror) PetscUseTypeMethod(ts, gettimeerror, n, v);
2328   else PetscCall(VecZeroEntries(*v));
2329   PetscFunctionReturn(PETSC_SUCCESS);
2330 }
2331 
2332 /*@
2333   TSSetTimeError - Sets the estimated error vector, if the chosen
2334   `TSType` has an error estimation functionality. This can be used
2335   to restart such a time integrator with a given error vector.
2336 
2337   Not Collective, but v returned is parallel if ts is parallel
2338 
2339   Input Parameters:
2340 + ts - the `TS` context obtained from `TSCreate()` (input parameter).
2341 - v  - the vector containing the error (same size as the solution).
2342 
2343   Level: intermediate
2344 
2345 .seealso: [](ch_ts), `TS`, `TSSetSolution()`, `TSGetTimeError()`
2346 @*/
2347 PetscErrorCode TSSetTimeError(TS ts, Vec v)
2348 {
2349   PetscFunctionBegin;
2350   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2351   PetscCheck(ts->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetUp() first");
2352   PetscTryTypeMethod(ts, settimeerror, v);
2353   PetscFunctionReturn(PETSC_SUCCESS);
2354 }
2355 
2356 /* ----- Routines to initialize and destroy a timestepper ---- */
2357 /*@
2358   TSSetProblemType - Sets the type of problem to be solved.
2359 
2360   Not collective
2361 
2362   Input Parameters:
2363 + ts   - The `TS`
2364 - type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
2365 .vb
2366          U_t - A U = 0      (linear)
2367          U_t - A(t) U = 0   (linear)
2368          F(t,U,U_t) = 0     (nonlinear)
2369 .ve
2370 
2371   Level: beginner
2372 
2373 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
2374 @*/
2375 PetscErrorCode TSSetProblemType(TS ts, TSProblemType type)
2376 {
2377   PetscFunctionBegin;
2378   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2379   ts->problem_type = type;
2380   if (type == TS_LINEAR) {
2381     SNES snes;
2382     PetscCall(TSGetSNES(ts, &snes));
2383     PetscCall(SNESSetType(snes, SNESKSPONLY));
2384   }
2385   PetscFunctionReturn(PETSC_SUCCESS);
2386 }
2387 
2388 /*@
2389   TSGetProblemType - Gets the type of problem to be solved.
2390 
2391   Not collective
2392 
2393   Input Parameter:
2394 . ts - The `TS`
2395 
2396   Output Parameter:
2397 . type - One of `TS_LINEAR`, `TS_NONLINEAR` where these types refer to problems of the forms
2398 .vb
2399          M U_t = A U
2400          M(t) U_t = A(t) U
2401          F(t,U,U_t)
2402 .ve
2403 
2404   Level: beginner
2405 
2406 .seealso: [](ch_ts), `TSSetUp()`, `TSProblemType`, `TS`
2407 @*/
2408 PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type)
2409 {
2410   PetscFunctionBegin;
2411   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2412   PetscAssertPointer(type, 2);
2413   *type = ts->problem_type;
2414   PetscFunctionReturn(PETSC_SUCCESS);
2415 }
2416 
2417 /*
2418     Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp()
2419 */
2420 static PetscErrorCode TSSetExactFinalTimeDefault(TS ts)
2421 {
2422   PetscBool isnone;
2423 
2424   PetscFunctionBegin;
2425   PetscCall(TSGetAdapt(ts, &ts->adapt));
2426   PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
2427 
2428   PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt, TSADAPTNONE, &isnone));
2429   if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP;
2430   else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE;
2431   PetscFunctionReturn(PETSC_SUCCESS);
2432 }
2433 
2434 /*@
2435   TSSetUp - Sets up the internal data structures for the later use of a timestepper.
2436 
2437   Collective
2438 
2439   Input Parameter:
2440 . ts - the `TS` context obtained from `TSCreate()`
2441 
2442   Level: advanced
2443 
2444   Note:
2445   For basic use of the `TS` solvers the user need not explicitly call
2446   `TSSetUp()`, since these actions will automatically occur during
2447   the call to `TSStep()` or `TSSolve()`.  However, if one wishes to control this
2448   phase separately, `TSSetUp()` should be called after `TSCreate()`
2449   and optional routines of the form TSSetXXX(), but before `TSStep()` and `TSSolve()`.
2450 
2451 .seealso: [](ch_ts), `TSCreate()`, `TS`, `TSStep()`, `TSDestroy()`, `TSSolve()`
2452 @*/
2453 PetscErrorCode TSSetUp(TS ts)
2454 {
2455   DM dm;
2456   PetscErrorCode (*func)(SNES, Vec, Vec, void *);
2457   PetscErrorCode (*jac)(SNES, Vec, Mat, Mat, void *);
2458   TSIFunctionFn   *ifun;
2459   TSIJacobianFn   *ijac;
2460   TSI2JacobianFn  *i2jac;
2461   TSRHSJacobianFn *rhsjac;
2462 
2463   PetscFunctionBegin;
2464   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2465   if (ts->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
2466 
2467   if (!((PetscObject)ts)->type_name) {
2468     PetscCall(TSGetIFunction(ts, NULL, &ifun, NULL));
2469     PetscCall(TSSetType(ts, ifun ? TSBEULER : TSEULER));
2470   }
2471 
2472   if (!ts->vec_sol) {
2473     PetscCheck(ts->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call TSSetSolution() first");
2474     PetscCall(DMCreateGlobalVector(ts->dm, &ts->vec_sol));
2475   }
2476 
2477   if (ts->tspan) {
2478     if (!ts->tspan->vecs_sol) PetscCall(VecDuplicateVecs(ts->vec_sol, ts->tspan->num_span_times, &ts->tspan->vecs_sol));
2479   }
2480   if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */
2481     PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs));
2482     ts->Jacp = ts->Jacprhs;
2483   }
2484 
2485   if (ts->quadraturets) {
2486     PetscCall(TSSetUp(ts->quadraturets));
2487     PetscCall(VecDestroy(&ts->vec_costintegrand));
2488     PetscCall(VecDuplicate(ts->quadraturets->vec_sol, &ts->vec_costintegrand));
2489   }
2490 
2491   PetscCall(TSGetRHSJacobian(ts, NULL, NULL, &rhsjac, NULL));
2492   if (rhsjac == TSComputeRHSJacobianConstant) {
2493     Mat  Amat, Pmat;
2494     SNES snes;
2495     PetscCall(TSGetSNES(ts, &snes));
2496     PetscCall(SNESGetJacobian(snes, &Amat, &Pmat, NULL, NULL));
2497     /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
2498      * have displaced the RHS matrix */
2499     if (Amat && Amat == ts->Arhs) {
2500       /* 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 */
2501       PetscCall(MatDuplicate(ts->Arhs, MAT_COPY_VALUES, &Amat));
2502       PetscCall(SNESSetJacobian(snes, Amat, NULL, NULL, NULL));
2503       PetscCall(MatDestroy(&Amat));
2504     }
2505     if (Pmat && Pmat == ts->Brhs) {
2506       PetscCall(MatDuplicate(ts->Brhs, MAT_COPY_VALUES, &Pmat));
2507       PetscCall(SNESSetJacobian(snes, NULL, Pmat, NULL, NULL));
2508       PetscCall(MatDestroy(&Pmat));
2509     }
2510   }
2511 
2512   PetscCall(TSGetAdapt(ts, &ts->adapt));
2513   PetscCall(TSAdaptSetDefaultType(ts->adapt, ts->default_adapt_type));
2514 
2515   PetscTryTypeMethod(ts, setup);
2516 
2517   PetscCall(TSSetExactFinalTimeDefault(ts));
2518 
2519   /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
2520      to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
2521    */
2522   PetscCall(TSGetDM(ts, &dm));
2523   PetscCall(DMSNESGetFunction(dm, &func, NULL));
2524   if (!func) PetscCall(DMSNESSetFunction(dm, SNESTSFormFunction, ts));
2525 
2526   /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
2527      Otherwise, the SNES will use coloring internally to form the Jacobian.
2528    */
2529   PetscCall(DMSNESGetJacobian(dm, &jac, NULL));
2530   PetscCall(DMTSGetIJacobian(dm, &ijac, NULL));
2531   PetscCall(DMTSGetI2Jacobian(dm, &i2jac, NULL));
2532   PetscCall(DMTSGetRHSJacobian(dm, &rhsjac, NULL));
2533   if (!jac && (ijac || i2jac || rhsjac)) PetscCall(DMSNESSetJacobian(dm, SNESTSFormJacobian, ts));
2534 
2535   /* if time integration scheme has a starting method, call it */
2536   PetscTryTypeMethod(ts, startingmethod);
2537 
2538   ts->setupcalled = PETSC_TRUE;
2539   PetscFunctionReturn(PETSC_SUCCESS);
2540 }
2541 
2542 /*@
2543   TSReset - Resets a `TS` context and removes any allocated `Vec`s and `Mat`s.
2544 
2545   Collective
2546 
2547   Input Parameter:
2548 . ts - the `TS` context obtained from `TSCreate()`
2549 
2550   Level: beginner
2551 
2552 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetup()`, `TSDestroy()`
2553 @*/
2554 PetscErrorCode TSReset(TS ts)
2555 {
2556   TS_RHSSplitLink ilink = ts->tsrhssplit, next;
2557 
2558   PetscFunctionBegin;
2559   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2560 
2561   PetscTryTypeMethod(ts, reset);
2562   if (ts->snes) PetscCall(SNESReset(ts->snes));
2563   if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt));
2564 
2565   PetscCall(MatDestroy(&ts->Arhs));
2566   PetscCall(MatDestroy(&ts->Brhs));
2567   PetscCall(VecDestroy(&ts->Frhs));
2568   PetscCall(VecDestroy(&ts->vec_sol));
2569   PetscCall(VecDestroy(&ts->vec_sol0));
2570   PetscCall(VecDestroy(&ts->vec_dot));
2571   PetscCall(VecDestroy(&ts->vatol));
2572   PetscCall(VecDestroy(&ts->vrtol));
2573   PetscCall(VecDestroyVecs(ts->nwork, &ts->work));
2574 
2575   PetscCall(MatDestroy(&ts->Jacprhs));
2576   PetscCall(MatDestroy(&ts->Jacp));
2577   if (ts->forward_solve) PetscCall(TSForwardReset(ts));
2578   if (ts->quadraturets) {
2579     PetscCall(TSReset(ts->quadraturets));
2580     PetscCall(VecDestroy(&ts->vec_costintegrand));
2581   }
2582   while (ilink) {
2583     next = ilink->next;
2584     PetscCall(TSDestroy(&ilink->ts));
2585     PetscCall(PetscFree(ilink->splitname));
2586     PetscCall(ISDestroy(&ilink->is));
2587     PetscCall(PetscFree(ilink));
2588     ilink = next;
2589   }
2590   ts->tsrhssplit     = NULL;
2591   ts->num_rhs_splits = 0;
2592   if (ts->tspan) {
2593     PetscCall(PetscFree(ts->tspan->span_times));
2594     PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol));
2595     PetscCall(PetscFree(ts->tspan));
2596   }
2597   ts->rhsjacobian.time  = PETSC_MIN_REAL;
2598   ts->rhsjacobian.scale = 1.0;
2599   ts->ijacobian.shift   = 1.0;
2600   ts->setupcalled       = PETSC_FALSE;
2601   PetscFunctionReturn(PETSC_SUCCESS);
2602 }
2603 
2604 static PetscErrorCode TSResizeReset(TS);
2605 
2606 /*@
2607   TSDestroy - Destroys the timestepper context that was created
2608   with `TSCreate()`.
2609 
2610   Collective
2611 
2612   Input Parameter:
2613 . ts - the `TS` context obtained from `TSCreate()`
2614 
2615   Level: beginner
2616 
2617 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSSolve()`
2618 @*/
2619 PetscErrorCode TSDestroy(TS *ts)
2620 {
2621   PetscFunctionBegin;
2622   if (!*ts) PetscFunctionReturn(PETSC_SUCCESS);
2623   PetscValidHeaderSpecific(*ts, TS_CLASSID, 1);
2624   if (--((PetscObject)*ts)->refct > 0) {
2625     *ts = NULL;
2626     PetscFunctionReturn(PETSC_SUCCESS);
2627   }
2628 
2629   PetscCall(TSReset(*ts));
2630   PetscCall(TSAdjointReset(*ts));
2631   if ((*ts)->forward_solve) PetscCall(TSForwardReset(*ts));
2632   PetscCall(TSResizeReset(*ts));
2633 
2634   /* if memory was published with SAWs then destroy it */
2635   PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts));
2636   PetscTryTypeMethod(*ts, destroy);
2637 
2638   PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory));
2639 
2640   PetscCall(TSAdaptDestroy(&(*ts)->adapt));
2641   PetscCall(TSEventDestroy(&(*ts)->event));
2642 
2643   PetscCall(SNESDestroy(&(*ts)->snes));
2644   PetscCall(SNESDestroy(&(*ts)->snesrhssplit));
2645   PetscCall(DMDestroy(&(*ts)->dm));
2646   PetscCall(TSMonitorCancel(*ts));
2647   PetscCall(TSAdjointMonitorCancel(*ts));
2648 
2649   PetscCall(TSDestroy(&(*ts)->quadraturets));
2650   PetscCall(PetscHeaderDestroy(ts));
2651   PetscFunctionReturn(PETSC_SUCCESS);
2652 }
2653 
2654 /*@
2655   TSGetSNES - Returns the `SNES` (nonlinear solver) associated with
2656   a `TS` (timestepper) context. Valid only for nonlinear problems.
2657 
2658   Not Collective, but snes is parallel if ts is parallel
2659 
2660   Input Parameter:
2661 . ts - the `TS` context obtained from `TSCreate()`
2662 
2663   Output Parameter:
2664 . snes - the nonlinear solver context
2665 
2666   Level: beginner
2667 
2668   Notes:
2669   The user can then directly manipulate the `SNES` context to set various
2670   options, etc.  Likewise, the user can then extract and manipulate the
2671   `KSP`, and `PC` contexts as well.
2672 
2673   `TSGetSNES()` does not work for integrators that do not use `SNES`; in
2674   this case `TSGetSNES()` returns `NULL` in `snes`.
2675 
2676 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`
2677 @*/
2678 PetscErrorCode TSGetSNES(TS ts, SNES *snes)
2679 {
2680   PetscFunctionBegin;
2681   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2682   PetscAssertPointer(snes, 2);
2683   if (!ts->snes) {
2684     PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts), &ts->snes));
2685     PetscCall(PetscObjectSetOptions((PetscObject)ts->snes, ((PetscObject)ts)->options));
2686     PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
2687     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1));
2688     if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm));
2689     if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
2690   }
2691   *snes = ts->snes;
2692   PetscFunctionReturn(PETSC_SUCCESS);
2693 }
2694 
2695 /*@
2696   TSSetSNES - Set the `SNES` (nonlinear solver) to be used by the timestepping context
2697 
2698   Collective
2699 
2700   Input Parameters:
2701 + ts   - the `TS` context obtained from `TSCreate()`
2702 - snes - the nonlinear solver context
2703 
2704   Level: developer
2705 
2706   Note:
2707   Most users should have the `TS` created by calling `TSGetSNES()`
2708 
2709 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()`
2710 @*/
2711 PetscErrorCode TSSetSNES(TS ts, SNES snes)
2712 {
2713   PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
2714 
2715   PetscFunctionBegin;
2716   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2717   PetscValidHeaderSpecific(snes, SNES_CLASSID, 2);
2718   PetscCall(PetscObjectReference((PetscObject)snes));
2719   PetscCall(SNESDestroy(&ts->snes));
2720 
2721   ts->snes = snes;
2722 
2723   PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
2724   PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL));
2725   if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts));
2726   PetscFunctionReturn(PETSC_SUCCESS);
2727 }
2728 
2729 /*@
2730   TSGetKSP - Returns the `KSP` (linear solver) associated with
2731   a `TS` (timestepper) context.
2732 
2733   Not Collective, but `ksp` is parallel if `ts` is parallel
2734 
2735   Input Parameter:
2736 . ts - the `TS` context obtained from `TSCreate()`
2737 
2738   Output Parameter:
2739 . ksp - the nonlinear solver context
2740 
2741   Level: beginner
2742 
2743   Notes:
2744   The user can then directly manipulate the `KSP` context to set various
2745   options, etc.  Likewise, the user can then extract and manipulate the
2746   `PC` context as well.
2747 
2748   `TSGetKSP()` does not work for integrators that do not use `KSP`;
2749   in this case `TSGetKSP()` returns `NULL` in `ksp`.
2750 
2751 .seealso: [](ch_ts), `TS`, `SNES`, `KSP`, `TSCreate()`, `TSSetUp()`, `TSSolve()`, `TSGetSNES()`
2752 @*/
2753 PetscErrorCode TSGetKSP(TS ts, KSP *ksp)
2754 {
2755   SNES snes;
2756 
2757   PetscFunctionBegin;
2758   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2759   PetscAssertPointer(ksp, 2);
2760   PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first");
2761   PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()");
2762   PetscCall(TSGetSNES(ts, &snes));
2763   PetscCall(SNESGetKSP(snes, ksp));
2764   PetscFunctionReturn(PETSC_SUCCESS);
2765 }
2766 
2767 /* ----------- Routines to set solver parameters ---------- */
2768 
2769 /*@
2770   TSSetMaxSteps - Sets the maximum number of steps to use.
2771 
2772   Logically Collective
2773 
2774   Input Parameters:
2775 + ts       - the `TS` context obtained from `TSCreate()`
2776 - maxsteps - maximum number of steps to use
2777 
2778   Options Database Key:
2779 . -ts_max_steps <maxsteps> - Sets maxsteps
2780 
2781   Level: intermediate
2782 
2783   Note:
2784   Use `PETSC_DETERMINE` to reset the maximum number of steps to the default from when the object's type was set
2785 
2786   The default maximum number of steps is 5,000
2787 
2788   Fortran Note:
2789   Use `PETSC_DETERMINE_INTEGER`
2790 
2791 .seealso: [](ch_ts), `TS`, `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()`
2792 @*/
2793 PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps)
2794 {
2795   PetscFunctionBegin;
2796   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2797   PetscValidLogicalCollectiveInt(ts, maxsteps, 2);
2798   if (maxsteps == PETSC_DETERMINE) {
2799     ts->max_steps = ts->default_max_steps;
2800   } else {
2801     PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative");
2802     ts->max_steps = maxsteps;
2803   }
2804   PetscFunctionReturn(PETSC_SUCCESS);
2805 }
2806 
2807 /*@
2808   TSGetMaxSteps - Gets the maximum number of steps to use.
2809 
2810   Not Collective
2811 
2812   Input Parameter:
2813 . ts - the `TS` context obtained from `TSCreate()`
2814 
2815   Output Parameter:
2816 . maxsteps - maximum number of steps to use
2817 
2818   Level: advanced
2819 
2820 .seealso: [](ch_ts), `TS`, `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()`
2821 @*/
2822 PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps)
2823 {
2824   PetscFunctionBegin;
2825   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2826   PetscAssertPointer(maxsteps, 2);
2827   *maxsteps = ts->max_steps;
2828   PetscFunctionReturn(PETSC_SUCCESS);
2829 }
2830 
2831 /*@
2832   TSSetMaxTime - Sets the maximum (or final) time for timestepping.
2833 
2834   Logically Collective
2835 
2836   Input Parameters:
2837 + ts      - the `TS` context obtained from `TSCreate()`
2838 - maxtime - final time to step to
2839 
2840   Options Database Key:
2841 . -ts_max_time <maxtime> - Sets maxtime
2842 
2843   Level: intermediate
2844 
2845   Notes:
2846   Use `PETSC_DETERMINE` to reset the maximum time to the default from when the object's type was set
2847 
2848   The default maximum time is 5.0
2849 
2850   Fortran Note:
2851   Use `PETSC_DETERMINE_REAL`
2852 
2853 .seealso: [](ch_ts), `TS`, `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()`
2854 @*/
2855 PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime)
2856 {
2857   PetscFunctionBegin;
2858   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2859   PetscValidLogicalCollectiveReal(ts, maxtime, 2);
2860   if (maxtime == PETSC_DETERMINE) {
2861     ts->max_time = ts->default_max_time;
2862   } else {
2863     ts->max_time = maxtime;
2864   }
2865   PetscFunctionReturn(PETSC_SUCCESS);
2866 }
2867 
2868 /*@
2869   TSGetMaxTime - Gets the maximum (or final) time for timestepping.
2870 
2871   Not Collective
2872 
2873   Input Parameter:
2874 . ts - the `TS` context obtained from `TSCreate()`
2875 
2876   Output Parameter:
2877 . maxtime - final time to step to
2878 
2879   Level: advanced
2880 
2881 .seealso: [](ch_ts), `TS`, `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()`
2882 @*/
2883 PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime)
2884 {
2885   PetscFunctionBegin;
2886   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2887   PetscAssertPointer(maxtime, 2);
2888   *maxtime = ts->max_time;
2889   PetscFunctionReturn(PETSC_SUCCESS);
2890 }
2891 
2892 // PetscClangLinter pragma disable: -fdoc-*
2893 /*@
2894   TSSetInitialTimeStep - Deprecated, use `TSSetTime()` and `TSSetTimeStep()`.
2895 
2896   Level: deprecated
2897 
2898 @*/
2899 PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step)
2900 {
2901   PetscFunctionBegin;
2902   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2903   PetscCall(TSSetTime(ts, initial_time));
2904   PetscCall(TSSetTimeStep(ts, time_step));
2905   PetscFunctionReturn(PETSC_SUCCESS);
2906 }
2907 
2908 // PetscClangLinter pragma disable: -fdoc-*
2909 /*@
2910   TSGetDuration - Deprecated, use `TSGetMaxSteps()` and `TSGetMaxTime()`.
2911 
2912   Level: deprecated
2913 
2914 @*/
2915 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
2916 {
2917   PetscFunctionBegin;
2918   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2919   if (maxsteps) {
2920     PetscAssertPointer(maxsteps, 2);
2921     *maxsteps = ts->max_steps;
2922   }
2923   if (maxtime) {
2924     PetscAssertPointer(maxtime, 3);
2925     *maxtime = ts->max_time;
2926   }
2927   PetscFunctionReturn(PETSC_SUCCESS);
2928 }
2929 
2930 // PetscClangLinter pragma disable: -fdoc-*
2931 /*@
2932   TSSetDuration - Deprecated, use `TSSetMaxSteps()` and `TSSetMaxTime()`.
2933 
2934   Level: deprecated
2935 
2936 @*/
2937 PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime)
2938 {
2939   PetscFunctionBegin;
2940   if (maxsteps != (PetscInt)PETSC_CURRENT) PetscCall(TSSetMaxSteps(ts, maxsteps));
2941   if (maxtime != (PetscReal)PETSC_CURRENT) PetscCall(TSSetMaxTime(ts, maxtime));
2942   PetscFunctionReturn(PETSC_SUCCESS);
2943 }
2944 
2945 // PetscClangLinter pragma disable: -fdoc-*
2946 /*@
2947   TSGetTimeStepNumber - Deprecated, use `TSGetStepNumber()`.
2948 
2949   Level: deprecated
2950 
2951 @*/
2952 PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps)
2953 {
2954   return TSGetStepNumber(ts, steps);
2955 }
2956 
2957 // PetscClangLinter pragma disable: -fdoc-*
2958 /*@
2959   TSGetTotalSteps - Deprecated, use `TSGetStepNumber()`.
2960 
2961   Level: deprecated
2962 
2963 @*/
2964 PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps)
2965 {
2966   return TSGetStepNumber(ts, steps);
2967 }
2968 
2969 /*@
2970   TSSetSolution - Sets the initial solution vector
2971   for use by the `TS` routines.
2972 
2973   Logically Collective
2974 
2975   Input Parameters:
2976 + ts - the `TS` context obtained from `TSCreate()`
2977 - u  - the solution vector
2978 
2979   Level: beginner
2980 
2981 .seealso: [](ch_ts), `TS`, `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()`
2982 @*/
2983 PetscErrorCode TSSetSolution(TS ts, Vec u)
2984 {
2985   DM dm;
2986 
2987   PetscFunctionBegin;
2988   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2989   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
2990   PetscCall(PetscObjectReference((PetscObject)u));
2991   PetscCall(VecDestroy(&ts->vec_sol));
2992   ts->vec_sol = u;
2993 
2994   PetscCall(TSGetDM(ts, &dm));
2995   PetscCall(DMShellSetGlobalVector(dm, u));
2996   PetscFunctionReturn(PETSC_SUCCESS);
2997 }
2998 
2999 /*@C
3000   TSSetPreStep - Sets the general-purpose function
3001   called once at the beginning of each time step.
3002 
3003   Logically Collective
3004 
3005   Input Parameters:
3006 + ts   - The `TS` context obtained from `TSCreate()`
3007 - func - The function
3008 
3009   Calling sequence of `func`:
3010 . ts - the `TS` context
3011 
3012   Level: intermediate
3013 
3014 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()`
3015 @*/
3016 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS ts))
3017 {
3018   PetscFunctionBegin;
3019   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3020   ts->prestep = func;
3021   PetscFunctionReturn(PETSC_SUCCESS);
3022 }
3023 
3024 /*@
3025   TSPreStep - Runs the user-defined pre-step function provided with `TSSetPreStep()`
3026 
3027   Collective
3028 
3029   Input Parameter:
3030 . ts - The `TS` context obtained from `TSCreate()`
3031 
3032   Level: developer
3033 
3034   Note:
3035   `TSPreStep()` is typically used within time stepping implementations,
3036   so most users would not generally call this routine themselves.
3037 
3038 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()`
3039 @*/
3040 PetscErrorCode TSPreStep(TS ts)
3041 {
3042   PetscFunctionBegin;
3043   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3044   if (ts->prestep) {
3045     Vec              U;
3046     PetscObjectId    idprev;
3047     PetscBool        sameObject;
3048     PetscObjectState sprev, spost;
3049 
3050     PetscCall(TSGetSolution(ts, &U));
3051     PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3052     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3053     PetscCallBack("TS callback preset", (*ts->prestep)(ts));
3054     PetscCall(TSGetSolution(ts, &U));
3055     PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3056     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3057     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3058   }
3059   PetscFunctionReturn(PETSC_SUCCESS);
3060 }
3061 
3062 /*@C
3063   TSSetPreStage - Sets the general-purpose function
3064   called once at the beginning of each stage.
3065 
3066   Logically Collective
3067 
3068   Input Parameters:
3069 + ts   - The `TS` context obtained from `TSCreate()`
3070 - func - The function
3071 
3072   Calling sequence of `func`:
3073 + ts        - the `TS` context
3074 - stagetime - the stage time
3075 
3076   Level: intermediate
3077 
3078   Note:
3079   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3080   The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being
3081   attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`.
3082 
3083 .seealso: [](ch_ts), `TS`, `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3084 @*/
3085 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime))
3086 {
3087   PetscFunctionBegin;
3088   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3089   ts->prestage = func;
3090   PetscFunctionReturn(PETSC_SUCCESS);
3091 }
3092 
3093 /*@C
3094   TSSetPostStage - Sets the general-purpose function
3095   called once at the end of each stage.
3096 
3097   Logically Collective
3098 
3099   Input Parameters:
3100 + ts   - The `TS` context obtained from `TSCreate()`
3101 - func - The function
3102 
3103   Calling sequence of `func`:
3104 + ts         - the `TS` context
3105 . stagetime  - the stage time
3106 . stageindex - the stage index
3107 - Y          - Array of vectors (of size = total number of stages) with the stage solutions
3108 
3109   Level: intermediate
3110 
3111   Note:
3112   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3113   The time step number being computed can be queried using `TSGetStepNumber()` and the total size of the step being
3114   attempted can be obtained using `TSGetTimeStep()`. The time at the start of the step is available via `TSGetTime()`.
3115 
3116 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3117 @*/
3118 PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y))
3119 {
3120   PetscFunctionBegin;
3121   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3122   ts->poststage = func;
3123   PetscFunctionReturn(PETSC_SUCCESS);
3124 }
3125 
3126 /*@C
3127   TSSetPostEvaluate - Sets the general-purpose function
3128   called at the end of each step evaluation.
3129 
3130   Logically Collective
3131 
3132   Input Parameters:
3133 + ts   - The `TS` context obtained from `TSCreate()`
3134 - func - The function
3135 
3136   Calling sequence of `func`:
3137 . ts - the `TS` context
3138 
3139   Level: intermediate
3140 
3141   Note:
3142   The function set by `TSSetPostEvaluate()` is called after the solution is evaluated, or after the step rollback.
3143   Inside the `func` callback, the solution vector can be obtained with `TSGetSolution()`, and modified, if need be.
3144   The time step can be obtained with `TSGetTimeStep()`, and the time at the start of the step - via `TSGetTime()`.
3145   The potential changes to the solution vector introduced by event handling (`postevent()`) are not relevant for `TSSetPostEvaluate()`,
3146   but are relevant for `TSSetPostStep()`, according to the function call scheme in `TSSolve()`, as shown below
3147 .vb
3148   ...
3149   Step()
3150   PostEvaluate()
3151   EventHandling()
3152   step_rollback ? PostEvaluate() : PostStep()
3153   ...
3154 .ve
3155   where EventHandling() may result in one of the following three outcomes
3156 .vb
3157   (1) | successful step | solution intact
3158   (2) | successful step | solution modified by `postevent()`
3159   (3) | step_rollback   | solution rolled back
3160 .ve
3161 
3162 .seealso: [](ch_ts), `TS`, `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3163 @*/
3164 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS ts))
3165 {
3166   PetscFunctionBegin;
3167   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3168   ts->postevaluate = func;
3169   PetscFunctionReturn(PETSC_SUCCESS);
3170 }
3171 
3172 /*@
3173   TSPreStage - Runs the user-defined pre-stage function set using `TSSetPreStage()`
3174 
3175   Collective
3176 
3177   Input Parameters:
3178 + ts        - The `TS` context obtained from `TSCreate()`
3179 - stagetime - The absolute time of the current stage
3180 
3181   Level: developer
3182 
3183   Note:
3184   `TSPreStage()` is typically used within time stepping implementations,
3185   most users would not generally call this routine themselves.
3186 
3187 .seealso: [](ch_ts), `TS`, `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3188 @*/
3189 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime)
3190 {
3191   PetscFunctionBegin;
3192   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3193   if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime));
3194   PetscFunctionReturn(PETSC_SUCCESS);
3195 }
3196 
3197 /*@
3198   TSPostStage - Runs the user-defined post-stage function set using `TSSetPostStage()`
3199 
3200   Collective
3201 
3202   Input Parameters:
3203 + ts         - The `TS` context obtained from `TSCreate()`
3204 . stagetime  - The absolute time of the current stage
3205 . stageindex - Stage number
3206 - Y          - Array of vectors (of size = total number of stages) with the stage solutions
3207 
3208   Level: developer
3209 
3210   Note:
3211   `TSPostStage()` is typically used within time stepping implementations,
3212   most users would not generally call this routine themselves.
3213 
3214 .seealso: [](ch_ts), `TS`, `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3215 @*/
3216 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
3217 {
3218   PetscFunctionBegin;
3219   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3220   if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y));
3221   PetscFunctionReturn(PETSC_SUCCESS);
3222 }
3223 
3224 /*@
3225   TSPostEvaluate - Runs the user-defined post-evaluate function set using `TSSetPostEvaluate()`
3226 
3227   Collective
3228 
3229   Input Parameter:
3230 . ts - The `TS` context obtained from `TSCreate()`
3231 
3232   Level: developer
3233 
3234   Note:
3235   `TSPostEvaluate()` is typically used within time stepping implementations,
3236   most users would not generally call this routine themselves.
3237 
3238 .seealso: [](ch_ts), `TS`, `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3239 @*/
3240 PetscErrorCode TSPostEvaluate(TS ts)
3241 {
3242   PetscFunctionBegin;
3243   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3244   if (ts->postevaluate) {
3245     Vec              U;
3246     PetscObjectState sprev, spost;
3247 
3248     PetscCall(TSGetSolution(ts, &U));
3249     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3250     PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts));
3251     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3252     if (sprev != spost) PetscCall(TSRestartStep(ts));
3253   }
3254   PetscFunctionReturn(PETSC_SUCCESS);
3255 }
3256 
3257 /*@C
3258   TSSetPostStep - Sets the general-purpose function
3259   called once at the end of each successful time step.
3260 
3261   Logically Collective
3262 
3263   Input Parameters:
3264 + ts   - The `TS` context obtained from `TSCreate()`
3265 - func - The function
3266 
3267   Calling sequence of `func`:
3268 . ts - the `TS` context
3269 
3270   Level: intermediate
3271 
3272   Note:
3273   The function set by `TSSetPostStep()` is called after each successful step. If the event handler locates an event at the
3274   given step, and `postevent()` modifies the solution vector, the solution vector obtained by `TSGetSolution()` inside `func` will
3275   contain the changes. To get the solution without these changes, use `TSSetPostEvaluate()` to set the appropriate callback.
3276   The scheme of the relevant function calls in `TSSolve()` is shown below
3277 .vb
3278   ...
3279   Step()
3280   PostEvaluate()
3281   EventHandling()
3282   step_rollback ? PostEvaluate() : PostStep()
3283   ...
3284 .ve
3285   where EventHandling() may result in one of the following three outcomes
3286 .vb
3287   (1) | successful step | solution intact
3288   (2) | successful step | solution modified by `postevent()`
3289   (3) | step_rollback   | solution rolled back
3290 .ve
3291 
3292 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()`
3293 @*/
3294 PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS ts))
3295 {
3296   PetscFunctionBegin;
3297   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3298   ts->poststep = func;
3299   PetscFunctionReturn(PETSC_SUCCESS);
3300 }
3301 
3302 /*@
3303   TSPostStep - Runs the user-defined post-step function that was set with `TSSetPostStep()`
3304 
3305   Collective
3306 
3307   Input Parameter:
3308 . ts - The `TS` context obtained from `TSCreate()`
3309 
3310   Note:
3311   `TSPostStep()` is typically used within time stepping implementations,
3312   so most users would not generally call this routine themselves.
3313 
3314   Level: developer
3315 
3316 .seealso: [](ch_ts), `TS`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSSetPotsStep()`
3317 @*/
3318 PetscErrorCode TSPostStep(TS ts)
3319 {
3320   PetscFunctionBegin;
3321   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3322   if (ts->poststep) {
3323     Vec              U;
3324     PetscObjectId    idprev;
3325     PetscBool        sameObject;
3326     PetscObjectState sprev, spost;
3327 
3328     PetscCall(TSGetSolution(ts, &U));
3329     PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3330     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3331     PetscCallBack("TS callback poststep", (*ts->poststep)(ts));
3332     PetscCall(TSGetSolution(ts, &U));
3333     PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3334     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3335     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3336   }
3337   PetscFunctionReturn(PETSC_SUCCESS);
3338 }
3339 
3340 /*@
3341   TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
3342 
3343   Collective
3344 
3345   Input Parameters:
3346 + ts - time stepping context
3347 - t  - time to interpolate to
3348 
3349   Output Parameter:
3350 . U - state at given time
3351 
3352   Level: intermediate
3353 
3354   Developer Notes:
3355   `TSInterpolate()` and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
3356 
3357 .seealso: [](ch_ts), `TS`, `TSSetExactFinalTime()`, `TSSolve()`
3358 @*/
3359 PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U)
3360 {
3361   PetscFunctionBegin;
3362   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3363   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
3364   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);
3365   PetscUseTypeMethod(ts, interpolate, t, U);
3366   PetscFunctionReturn(PETSC_SUCCESS);
3367 }
3368 
3369 /*@
3370   TSStep - Steps one time step
3371 
3372   Collective
3373 
3374   Input Parameter:
3375 . ts - the `TS` context obtained from `TSCreate()`
3376 
3377   Level: developer
3378 
3379   Notes:
3380   The public interface for the ODE/DAE solvers is `TSSolve()`, you should almost for sure be using that routine and not this routine.
3381 
3382   The hook set using `TSSetPreStep()` is called before each attempt to take the step. In general, the time step size may
3383   be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3384 
3385   This may over-step the final time provided in `TSSetMaxTime()` depending on the time-step used. `TSSolve()` interpolates to exactly the
3386   time provided in `TSSetMaxTime()`. One can use `TSInterpolate()` to determine an interpolated solution within the final timestep.
3387 
3388 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()`
3389 @*/
3390 PetscErrorCode TSStep(TS ts)
3391 {
3392   static PetscBool cite = PETSC_FALSE;
3393   PetscReal        ptime;
3394 
3395   PetscFunctionBegin;
3396   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3397   PetscCall(PetscCitationsRegister("@article{tspaper,\n"
3398                                    "  title         = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3399                                    "  author        = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n"
3400                                    "  journal       = {arXiv e-preprints},\n"
3401                                    "  eprint        = {1806.01437},\n"
3402                                    "  archivePrefix = {arXiv},\n"
3403                                    "  year          = {2018}\n}\n",
3404                                    &cite));
3405   PetscCall(TSSetUp(ts));
3406   PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
3407   if (ts->tspan)
3408     ts->tspan->worktol = 0; /* In each step of TSSolve() 'tspan->worktol' will be meaningfully defined (later) only once:
3409                                                    in TSAdaptChoose() or TSEvent_dt_cap(), and then reused till the end of the step */
3410 
3411   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>");
3412   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()");
3413   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");
3414 
3415   if (!ts->vec_sol0) PetscCall(VecDuplicate(ts->vec_sol, &ts->vec_sol0));
3416   PetscCall(VecCopy(ts->vec_sol, ts->vec_sol0));
3417   ts->time_step0 = ts->time_step;
3418 
3419   if (!ts->steps) ts->ptime_prev = ts->ptime;
3420   ptime = ts->ptime;
3421 
3422   ts->ptime_prev_rollback = ts->ptime_prev;
3423   ts->reason              = TS_CONVERGED_ITERATING;
3424 
3425   PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0));
3426   PetscUseTypeMethod(ts, step);
3427   PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0));
3428 
3429   if (ts->reason >= 0) {
3430     ts->ptime_prev = ptime;
3431     ts->steps++;
3432     ts->steprollback = PETSC_FALSE;
3433     ts->steprestart  = PETSC_FALSE;
3434     ts->stepresize   = PETSC_FALSE;
3435   }
3436 
3437   if (ts->reason < 0 && ts->errorifstepfailed) {
3438     PetscCall(TSMonitorCancel(ts));
3439     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]);
3440     SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]);
3441   }
3442   PetscFunctionReturn(PETSC_SUCCESS);
3443 }
3444 
3445 /*@
3446   TSEvaluateWLTE - Evaluate the weighted local truncation error norm
3447   at the end of a time step with a given order of accuracy.
3448 
3449   Collective
3450 
3451   Input Parameters:
3452 + ts        - time stepping context
3453 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
3454 
3455   Input/Output Parameter:
3456 . order - optional, desired order for the error evaluation or `PETSC_DECIDE`;
3457            on output, the actual order of the error evaluation
3458 
3459   Output Parameter:
3460 . wlte - the weighted local truncation error norm
3461 
3462   Level: advanced
3463 
3464   Note:
3465   If the timestepper cannot evaluate the error in a particular step
3466   (eg. in the first step or restart steps after event handling),
3467   this routine returns wlte=-1.0 .
3468 
3469 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()`
3470 @*/
3471 PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte)
3472 {
3473   PetscFunctionBegin;
3474   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3475   PetscValidType(ts, 1);
3476   PetscValidLogicalCollectiveEnum(ts, wnormtype, 2);
3477   if (order) PetscAssertPointer(order, 3);
3478   if (order) PetscValidLogicalCollectiveInt(ts, *order, 3);
3479   PetscAssertPointer(wlte, 4);
3480   PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]);
3481   PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte);
3482   PetscFunctionReturn(PETSC_SUCCESS);
3483 }
3484 
3485 /*@
3486   TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
3487 
3488   Collective
3489 
3490   Input Parameters:
3491 + ts    - time stepping context
3492 . order - desired order of accuracy
3493 - done  - whether the step was evaluated at this order (pass `NULL` to generate an error if not available)
3494 
3495   Output Parameter:
3496 . U - state at the end of the current step
3497 
3498   Level: advanced
3499 
3500   Notes:
3501   This function cannot be called until all stages have been evaluated.
3502 
3503   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.
3504 
3505 .seealso: [](ch_ts), `TS`, `TSStep()`, `TSAdapt`
3506 @*/
3507 PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done)
3508 {
3509   PetscFunctionBegin;
3510   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3511   PetscValidType(ts, 1);
3512   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
3513   PetscUseTypeMethod(ts, evaluatestep, order, U, done);
3514   PetscFunctionReturn(PETSC_SUCCESS);
3515 }
3516 
3517 /*@C
3518   TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping.
3519 
3520   Not collective
3521 
3522   Input Parameter:
3523 . ts - time stepping context
3524 
3525   Output Parameter:
3526 . initCondition - The function which computes an initial condition
3527 
3528   Calling sequence of `initCondition`:
3529 + ts - The timestepping context
3530 - u  - The input vector in which the initial condition is stored
3531 
3532   Level: advanced
3533 
3534 .seealso: [](ch_ts), `TS`, `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()`
3535 @*/
3536 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS ts, Vec u))
3537 {
3538   PetscFunctionBegin;
3539   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3540   PetscAssertPointer(initCondition, 2);
3541   *initCondition = ts->ops->initcondition;
3542   PetscFunctionReturn(PETSC_SUCCESS);
3543 }
3544 
3545 /*@C
3546   TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping.
3547 
3548   Logically collective
3549 
3550   Input Parameters:
3551 + ts            - time stepping context
3552 - initCondition - The function which computes an initial condition
3553 
3554   Calling sequence of `initCondition`:
3555 + ts - The timestepping context
3556 - e  - The input vector in which the initial condition is to be stored
3557 
3558   Level: advanced
3559 
3560 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()`
3561 @*/
3562 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS ts, Vec e))
3563 {
3564   PetscFunctionBegin;
3565   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3566   PetscValidFunction(initCondition, 2);
3567   ts->ops->initcondition = initCondition;
3568   PetscFunctionReturn(PETSC_SUCCESS);
3569 }
3570 
3571 /*@
3572   TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set with `TSSetComputeInitialCondition()`
3573 
3574   Collective
3575 
3576   Input Parameters:
3577 + ts - time stepping context
3578 - u  - The `Vec` to store the condition in which will be used in `TSSolve()`
3579 
3580   Level: advanced
3581 
3582 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3583 @*/
3584 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u)
3585 {
3586   PetscFunctionBegin;
3587   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3588   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
3589   PetscTryTypeMethod(ts, initcondition, u);
3590   PetscFunctionReturn(PETSC_SUCCESS);
3591 }
3592 
3593 /*@C
3594   TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping.
3595 
3596   Not collective
3597 
3598   Input Parameter:
3599 . ts - time stepping context
3600 
3601   Output Parameter:
3602 . exactError - The function which computes the solution error
3603 
3604   Calling sequence of `exactError`:
3605 + ts - The timestepping context
3606 . u  - The approximate solution vector
3607 - e  - The vector in which the error is stored
3608 
3609   Level: advanced
3610 
3611 .seealso: [](ch_ts), `TS`, `TSComputeExactError()`
3612 @*/
3613 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS ts, Vec u, Vec e))
3614 {
3615   PetscFunctionBegin;
3616   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3617   PetscAssertPointer(exactError, 2);
3618   *exactError = ts->ops->exacterror;
3619   PetscFunctionReturn(PETSC_SUCCESS);
3620 }
3621 
3622 /*@C
3623   TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping.
3624 
3625   Logically collective
3626 
3627   Input Parameters:
3628 + ts         - time stepping context
3629 - exactError - The function which computes the solution error
3630 
3631   Calling sequence of `exactError`:
3632 + ts - The timestepping context
3633 . u  - The approximate solution vector
3634 - e  - The  vector in which the error is stored
3635 
3636   Level: advanced
3637 
3638 .seealso: [](ch_ts), `TS`, `TSGetComputeExactError()`, `TSComputeExactError()`
3639 @*/
3640 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS ts, Vec u, Vec e))
3641 {
3642   PetscFunctionBegin;
3643   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3644   PetscValidFunction(exactError, 2);
3645   ts->ops->exacterror = exactError;
3646   PetscFunctionReturn(PETSC_SUCCESS);
3647 }
3648 
3649 /*@
3650   TSComputeExactError - Compute the solution error for the timestepping using the function previously set with `TSSetComputeExactError()`
3651 
3652   Collective
3653 
3654   Input Parameters:
3655 + ts - time stepping context
3656 . u  - The approximate solution
3657 - e  - The `Vec` used to store the error
3658 
3659   Level: advanced
3660 
3661 .seealso: [](ch_ts), `TS`, `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3662 @*/
3663 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e)
3664 {
3665   PetscFunctionBegin;
3666   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3667   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
3668   PetscValidHeaderSpecific(e, VEC_CLASSID, 3);
3669   PetscTryTypeMethod(ts, exacterror, u, e);
3670   PetscFunctionReturn(PETSC_SUCCESS);
3671 }
3672 
3673 /*@C
3674   TSSetResize - Sets the resize callbacks.
3675 
3676   Logically Collective
3677 
3678   Input Parameters:
3679 + ts       - The `TS` context obtained from `TSCreate()`
3680 . rollback - Whether a resize will restart the step
3681 . setup    - The setup function
3682 . transfer - The transfer function
3683 - ctx      - [optional] The user-defined context
3684 
3685   Calling sequence of `setup`:
3686 + ts     - the `TS` context
3687 . step   - the current step
3688 . time   - the current time
3689 . state  - the current vector of state
3690 . resize - (output parameter) `PETSC_TRUE` if need resizing, `PETSC_FALSE` otherwise
3691 - ctx    - user defined context
3692 
3693   Calling sequence of `transfer`:
3694 + ts      - the `TS` context
3695 . nv      - the number of vectors to be transferred
3696 . vecsin  - array of vectors to be transferred
3697 . vecsout - array of transferred vectors
3698 - ctx     - user defined context
3699 
3700   Notes:
3701   The `setup` function is called inside `TSSolve()` after `TSEventHandler()` or after `TSPostStep()`
3702   depending on the `rollback` value: if `rollback` is true, then these callbacks behave as error indicators
3703   and will flag the need to remesh and restart the current step. Otherwise, they will simply flag the solver
3704   that the size of the discrete problem has changed.
3705   In both cases, the solver will collect the needed vectors that will be
3706   transferred from the old to the new sizes using the `transfer` callback. These vectors will include the
3707   current solution vector, and other vectors needed by the specific solver used.
3708   For example, `TSBDF` uses previous solutions vectors to solve for the next time step.
3709   Other application specific objects associated with the solver, i.e. Jacobian matrices and `DM`,
3710   will be automatically reset if the sizes are changed and they must be specified again by the user
3711   inside the `transfer` function.
3712   The input and output arrays passed to `transfer` are allocated by PETSc.
3713   Vectors in `vecsout` must be created by the user.
3714   Ownership of vectors in `vecsout` is transferred to PETSc.
3715 
3716   Level: advanced
3717 
3718 .seealso: [](ch_ts), `TS`, `TSSetDM()`, `TSSetIJacobian()`, `TSSetRHSJacobian()`
3719 @*/
3720 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)
3721 {
3722   PetscFunctionBegin;
3723   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3724   ts->resizerollback = rollback;
3725   ts->resizesetup    = setup;
3726   ts->resizetransfer = transfer;
3727   ts->resizectx      = ctx;
3728   PetscFunctionReturn(PETSC_SUCCESS);
3729 }
3730 
3731 /*
3732   TSResizeRegisterOrRetrieve - Register or import vectors transferred with `TSResize()`.
3733 
3734   Collective
3735 
3736   Input Parameters:
3737 + ts   - The `TS` context obtained from `TSCreate()`
3738 - 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.
3739 
3740   Level: developer
3741 
3742   Note:
3743   `TSResizeRegisterOrRetrieve()` is declared PETSC_INTERN since it is
3744    used within time stepping implementations,
3745    so most users would not generally call this routine themselves.
3746 
3747 .seealso: [](ch_ts), `TS`, `TSSetResize()`
3748 @*/
3749 static PetscErrorCode TSResizeRegisterOrRetrieve(TS ts, PetscBool flg)
3750 {
3751   PetscFunctionBegin;
3752   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3753   PetscTryTypeMethod(ts, resizeregister, flg);
3754   /* PetscTryTypeMethod(adapt, resizeregister, flg); */
3755   PetscFunctionReturn(PETSC_SUCCESS);
3756 }
3757 
3758 static PetscErrorCode TSResizeReset(TS ts)
3759 {
3760   PetscFunctionBegin;
3761   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3762   PetscCall(PetscObjectListDestroy(&ts->resizetransferobjs));
3763   PetscFunctionReturn(PETSC_SUCCESS);
3764 }
3765 
3766 static PetscErrorCode TSResizeTransferVecs(TS ts, PetscInt cnt, Vec vecsin[], Vec vecsout[])
3767 {
3768   PetscFunctionBegin;
3769   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3770   PetscValidLogicalCollectiveInt(ts, cnt, 2);
3771   for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPush(vecsin[i]));
3772   if (ts->resizetransfer) {
3773     PetscCall(PetscInfo(ts, "Transferring %" PetscInt_FMT " vectors\n", cnt));
3774     PetscCallBack("TS callback resize transfer", (*ts->resizetransfer)(ts, cnt, vecsin, vecsout, ts->resizectx));
3775   }
3776   for (PetscInt i = 0; i < cnt; i++) PetscCall(VecLockReadPop(vecsin[i]));
3777   PetscFunctionReturn(PETSC_SUCCESS);
3778 }
3779 
3780 /*@C
3781   TSResizeRegisterVec - Register a vector to be transferred with `TSResize()`.
3782 
3783   Collective
3784 
3785   Input Parameters:
3786 + ts   - The `TS` context obtained from `TSCreate()`
3787 . name - A string identifying the vector
3788 - vec  - The vector
3789 
3790   Level: developer
3791 
3792   Note:
3793   `TSResizeRegisterVec()` is typically used within time stepping implementations,
3794   so most users would not generally call this routine themselves.
3795 
3796 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRetrieveVec()`
3797 @*/
3798 PetscErrorCode TSResizeRegisterVec(TS ts, const char name[], Vec vec)
3799 {
3800   PetscFunctionBegin;
3801   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3802   PetscAssertPointer(name, 2);
3803   if (vec) PetscValidHeaderSpecific(vec, VEC_CLASSID, 3);
3804   PetscCall(PetscObjectListAdd(&ts->resizetransferobjs, name, (PetscObject)vec));
3805   PetscFunctionReturn(PETSC_SUCCESS);
3806 }
3807 
3808 /*@C
3809   TSResizeRetrieveVec - Retrieve a vector registered with `TSResizeRegisterVec()`.
3810 
3811   Collective
3812 
3813   Input Parameters:
3814 + ts   - The `TS` context obtained from `TSCreate()`
3815 . name - A string identifying the vector
3816 - vec  - The vector
3817 
3818   Level: developer
3819 
3820   Note:
3821   `TSResizeRetrieveVec()` is typically used within time stepping implementations,
3822   so most users would not generally call this routine themselves.
3823 
3824 .seealso: [](ch_ts), `TS`, `TSSetResize()`, `TSResize()`, `TSResizeRegisterVec()`
3825 @*/
3826 PetscErrorCode TSResizeRetrieveVec(TS ts, const char name[], Vec *vec)
3827 {
3828   PetscFunctionBegin;
3829   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3830   PetscAssertPointer(name, 2);
3831   PetscAssertPointer(vec, 3);
3832   PetscCall(PetscObjectListFind(ts->resizetransferobjs, name, (PetscObject *)vec));
3833   PetscFunctionReturn(PETSC_SUCCESS);
3834 }
3835 
3836 static PetscErrorCode TSResizeGetVecArray(TS ts, PetscInt *nv, const char **names[], Vec *vecs[])
3837 {
3838   PetscInt        cnt;
3839   PetscObjectList tmp;
3840   Vec            *vecsin  = NULL;
3841   const char    **namesin = NULL;
3842 
3843   PetscFunctionBegin;
3844   for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next)
3845     if (tmp->obj && tmp->obj->classid == VEC_CLASSID) cnt++;
3846   if (names) PetscCall(PetscMalloc1(cnt, &namesin));
3847   if (vecs) PetscCall(PetscMalloc1(cnt, &vecsin));
3848   for (tmp = ts->resizetransferobjs, cnt = 0; tmp; tmp = tmp->next) {
3849     if (tmp->obj && tmp->obj->classid == VEC_CLASSID) {
3850       if (vecs) vecsin[cnt] = (Vec)tmp->obj;
3851       if (names) namesin[cnt] = tmp->name;
3852       cnt++;
3853     }
3854   }
3855   if (nv) *nv = cnt;
3856   if (names) *names = namesin;
3857   if (vecs) *vecs = vecsin;
3858   PetscFunctionReturn(PETSC_SUCCESS);
3859 }
3860 
3861 /*@
3862   TSResize - Runs the user-defined transfer functions provided with `TSSetResize()`
3863 
3864   Collective
3865 
3866   Input Parameter:
3867 . ts - The `TS` context obtained from `TSCreate()`
3868 
3869   Level: developer
3870 
3871   Note:
3872   `TSResize()` is typically used within time stepping implementations,
3873   so most users would not generally call this routine themselves.
3874 
3875 .seealso: [](ch_ts), `TS`, `TSSetResize()`
3876 @*/
3877 PetscErrorCode TSResize(TS ts)
3878 {
3879   PetscInt     nv      = 0;
3880   const char **names   = NULL;
3881   Vec         *vecsin  = NULL;
3882   const char  *solname = "ts:vec_sol";
3883 
3884   PetscFunctionBegin;
3885   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3886   if (!ts->resizesetup) PetscFunctionReturn(PETSC_SUCCESS);
3887   if (ts->resizesetup) {
3888     PetscCall(VecLockReadPush(ts->vec_sol));
3889     PetscCallBack("TS callback resize setup", (*ts->resizesetup)(ts, ts->steps, ts->ptime, ts->vec_sol, &ts->stepresize, ts->resizectx));
3890     PetscCall(VecLockReadPop(ts->vec_sol));
3891     if (ts->stepresize) {
3892       if (ts->resizerollback) {
3893         PetscCall(TSRollBack(ts));
3894         ts->time_step = ts->time_step0;
3895       }
3896       PetscCall(TSResizeRegisterVec(ts, solname, ts->vec_sol));
3897       PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_TRUE)); /* specific impls register their own objects */
3898     }
3899   }
3900 
3901   PetscCall(TSResizeGetVecArray(ts, &nv, &names, &vecsin));
3902   if (nv) {
3903     Vec *vecsout, vecsol;
3904 
3905     /* Reset internal objects */
3906     PetscCall(TSReset(ts));
3907 
3908     /* Transfer needed vectors (users can call SetJacobian, SetDM, etc. here) */
3909     PetscCall(PetscCalloc1(nv, &vecsout));
3910     PetscCall(TSResizeTransferVecs(ts, nv, vecsin, vecsout));
3911     for (PetscInt i = 0; i < nv; i++) {
3912       const char *name;
3913       char       *oname;
3914 
3915       PetscCall(PetscObjectGetName((PetscObject)vecsin[i], &name));
3916       PetscCall(PetscStrallocpy(name, &oname));
3917       PetscCall(TSResizeRegisterVec(ts, names[i], vecsout[i]));
3918       if (vecsout[i]) PetscCall(PetscObjectSetName((PetscObject)vecsout[i], oname));
3919       PetscCall(PetscFree(oname));
3920       PetscCall(VecDestroy(&vecsout[i]));
3921     }
3922     PetscCall(PetscFree(vecsout));
3923     PetscCall(TSResizeRegisterOrRetrieve(ts, PETSC_FALSE)); /* specific impls import the transferred objects */
3924 
3925     PetscCall(TSResizeRetrieveVec(ts, solname, &vecsol));
3926     if (vecsol) PetscCall(TSSetSolution(ts, vecsol));
3927     PetscAssert(ts->vec_sol, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_NULL, "Missing TS solution");
3928   }
3929 
3930   PetscCall(PetscFree(names));
3931   PetscCall(PetscFree(vecsin));
3932   PetscCall(TSResizeReset(ts));
3933   PetscFunctionReturn(PETSC_SUCCESS);
3934 }
3935 
3936 /*@
3937   TSSolve - Steps the requested number of timesteps.
3938 
3939   Collective
3940 
3941   Input Parameters:
3942 + ts - the `TS` context obtained from `TSCreate()`
3943 - u  - the solution vector  (can be null if `TSSetSolution()` was used and `TSSetExactFinalTime`(ts,`TS_EXACTFINALTIME_MATCHSTEP`) was not used,
3944                              otherwise must contain the initial conditions and will contain the solution at the final requested time
3945 
3946   Level: beginner
3947 
3948   Notes:
3949   The final time returned by this function may be different from the time of the internally
3950   held state accessible by `TSGetSolution()` and `TSGetTime()` because the method may have
3951   stepped over the final time.
3952 
3953 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()`
3954 @*/
3955 PetscErrorCode TSSolve(TS ts, Vec u)
3956 {
3957   Vec solution;
3958 
3959   PetscFunctionBegin;
3960   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3961   if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
3962 
3963   PetscCall(TSSetExactFinalTimeDefault(ts));
3964   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 */
3965     if (!ts->vec_sol || u == ts->vec_sol) {
3966       PetscCall(VecDuplicate(u, &solution));
3967       PetscCall(TSSetSolution(ts, solution));
3968       PetscCall(VecDestroy(&solution)); /* grant ownership */
3969     }
3970     PetscCall(VecCopy(u, ts->vec_sol));
3971     PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
3972   } else if (u) PetscCall(TSSetSolution(ts, u));
3973   PetscCall(TSSetUp(ts));
3974   PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
3975 
3976   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>");
3977   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()");
3978   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");
3979   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");
3980 
3981   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 */
3982     PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[0]));
3983     ts->tspan->spanctr = 1;
3984   }
3985 
3986   if (ts->forward_solve) PetscCall(TSForwardSetUp(ts));
3987 
3988   /* reset number of steps only when the step is not restarted. ARKIMEX
3989      restarts the step after an event. Resetting these counters in such case causes
3990      TSTrajectory to incorrectly save the output files
3991   */
3992   /* reset time step and iteration counters */
3993   if (!ts->steps) {
3994     ts->ksp_its           = 0;
3995     ts->snes_its          = 0;
3996     ts->num_snes_failures = 0;
3997     ts->reject            = 0;
3998     ts->steprestart       = PETSC_TRUE;
3999     ts->steprollback      = PETSC_FALSE;
4000     ts->stepresize        = PETSC_FALSE;
4001     ts->rhsjacobian.time  = PETSC_MIN_REAL;
4002   }
4003 
4004   /* make sure initial time step does not overshoot final time or the next point in tspan */
4005   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
4006     PetscReal maxdt;
4007     PetscReal dt = ts->time_step;
4008 
4009     if (ts->tspan) maxdt = ts->tspan->span_times[ts->tspan->spanctr] - ts->ptime;
4010     else maxdt = ts->max_time - ts->ptime;
4011     ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt);
4012   }
4013   ts->reason = TS_CONVERGED_ITERATING;
4014 
4015   {
4016     PetscViewer       viewer;
4017     PetscViewerFormat format;
4018     PetscBool         flg;
4019     static PetscBool  incall = PETSC_FALSE;
4020 
4021     if (!incall) {
4022       /* Estimate the convergence rate of the time discretization */
4023       PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg));
4024       if (flg) {
4025         PetscConvEst conv;
4026         DM           dm;
4027         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
4028         PetscInt     Nf;
4029         PetscBool    checkTemporal = PETSC_TRUE;
4030 
4031         incall = PETSC_TRUE;
4032         PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg));
4033         PetscCall(TSGetDM(ts, &dm));
4034         PetscCall(DMGetNumFields(dm, &Nf));
4035         PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha));
4036         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv));
4037         PetscCall(PetscConvEstUseTS(conv, checkTemporal));
4038         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts));
4039         PetscCall(PetscConvEstSetFromOptions(conv));
4040         PetscCall(PetscConvEstSetUp(conv));
4041         PetscCall(PetscConvEstGetConvRate(conv, alpha));
4042         PetscCall(PetscViewerPushFormat(viewer, format));
4043         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
4044         PetscCall(PetscViewerPopFormat(viewer));
4045         PetscCall(PetscViewerDestroy(&viewer));
4046         PetscCall(PetscConvEstDestroy(&conv));
4047         PetscCall(PetscFree(alpha));
4048         incall = PETSC_FALSE;
4049       }
4050     }
4051   }
4052 
4053   PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre"));
4054 
4055   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
4056     PetscUseTypeMethod(ts, solve);
4057     if (u) PetscCall(VecCopy(ts->vec_sol, u));
4058     ts->solvetime = ts->ptime;
4059     solution      = ts->vec_sol;
4060   } else { /* Step the requested number of timesteps. */
4061     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4062     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4063 
4064     if (!ts->steps) {
4065       PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
4066       PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol));
4067     }
4068 
4069     while (!ts->reason) {
4070       PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
4071       if (!ts->steprollback || (ts->stepresize && ts->resizerollback)) PetscCall(TSPreStep(ts));
4072       PetscCall(TSStep(ts));
4073       if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL));
4074       if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL));
4075       if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
4076         if (ts->reason >= 0) ts->steps--;            /* Revert the step number changed by TSStep() */
4077         PetscCall(TSForwardCostIntegral(ts));
4078         if (ts->reason >= 0) ts->steps++;
4079       }
4080       if (ts->forward_solve) {            /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
4081         if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
4082         PetscCall(TSForwardStep(ts));
4083         if (ts->reason >= 0) ts->steps++;
4084       }
4085       PetscCall(TSPostEvaluate(ts));
4086       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. */
4087       if (ts->steprollback) PetscCall(TSPostEvaluate(ts));
4088       if (!ts->steprollback && ts->resizerollback) PetscCall(TSResize(ts));
4089       /* check convergence */
4090       if (!ts->reason) {
4091         if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4092         else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4093       }
4094       if (!ts->steprollback) {
4095         PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
4096         PetscCall(TSPostStep(ts));
4097         if (!ts->resizerollback) PetscCall(TSResize(ts));
4098 
4099         if (ts->tspan && ts->tspan->spanctr < ts->tspan->num_span_times) {
4100           PetscCheck(ts->tspan->worktol > 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_PLIB, "Unexpected state !(tspan->worktol > 0) in TSSolve()");
4101           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++]));
4102         }
4103       }
4104     }
4105     PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
4106 
4107     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
4108       if (!u) u = ts->vec_sol;
4109       PetscCall(TSInterpolate(ts, ts->max_time, u));
4110       ts->solvetime = ts->max_time;
4111       solution      = u;
4112       PetscCall(TSMonitor(ts, -1, ts->solvetime, solution));
4113     } else {
4114       if (u) PetscCall(VecCopy(ts->vec_sol, u));
4115       ts->solvetime = ts->ptime;
4116       solution      = ts->vec_sol;
4117     }
4118   }
4119 
4120   PetscCall(TSViewFromOptions(ts, NULL, "-ts_view"));
4121   PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution"));
4122   PetscCall(PetscObjectSAWsBlock((PetscObject)ts));
4123   if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts));
4124   PetscFunctionReturn(PETSC_SUCCESS);
4125 }
4126 
4127 /*@
4128   TSGetTime - Gets the time of the most recently completed step.
4129 
4130   Not Collective
4131 
4132   Input Parameter:
4133 . ts - the `TS` context obtained from `TSCreate()`
4134 
4135   Output Parameter:
4136 . t - the current time. This time may not corresponds to the final time set with `TSSetMaxTime()`, use `TSGetSolveTime()`.
4137 
4138   Level: beginner
4139 
4140   Note:
4141   When called during time step evaluation (e.g. during residual evaluation or via hooks set using `TSSetPreStep()`,
4142   `TSSetPreStage()`, `TSSetPostStage()`, or `TSSetPostStep()`), the time is the time at the start of the step being evaluated.
4143 
4144 .seealso: [](ch_ts), `TS`, `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()`
4145 @*/
4146 PetscErrorCode TSGetTime(TS ts, PetscReal *t)
4147 {
4148   PetscFunctionBegin;
4149   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4150   PetscAssertPointer(t, 2);
4151   *t = ts->ptime;
4152   PetscFunctionReturn(PETSC_SUCCESS);
4153 }
4154 
4155 /*@
4156   TSGetPrevTime - Gets the starting time of the previously completed step.
4157 
4158   Not Collective
4159 
4160   Input Parameter:
4161 . ts - the `TS` context obtained from `TSCreate()`
4162 
4163   Output Parameter:
4164 . t - the previous time
4165 
4166   Level: beginner
4167 
4168 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()`
4169 @*/
4170 PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t)
4171 {
4172   PetscFunctionBegin;
4173   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4174   PetscAssertPointer(t, 2);
4175   *t = ts->ptime_prev;
4176   PetscFunctionReturn(PETSC_SUCCESS);
4177 }
4178 
4179 /*@
4180   TSSetTime - Allows one to reset the time.
4181 
4182   Logically Collective
4183 
4184   Input Parameters:
4185 + ts - the `TS` context obtained from `TSCreate()`
4186 - t  - the time
4187 
4188   Level: intermediate
4189 
4190 .seealso: [](ch_ts), `TS`, `TSGetTime()`, `TSSetMaxSteps()`
4191 @*/
4192 PetscErrorCode TSSetTime(TS ts, PetscReal t)
4193 {
4194   PetscFunctionBegin;
4195   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4196   PetscValidLogicalCollectiveReal(ts, t, 2);
4197   ts->ptime = t;
4198   PetscFunctionReturn(PETSC_SUCCESS);
4199 }
4200 
4201 /*@
4202   TSSetOptionsPrefix - Sets the prefix used for searching for all
4203   TS options in the database.
4204 
4205   Logically Collective
4206 
4207   Input Parameters:
4208 + ts     - The `TS` context
4209 - prefix - The prefix to prepend to all option names
4210 
4211   Level: advanced
4212 
4213   Note:
4214   A hyphen (-) must NOT be given at the beginning of the prefix name.
4215   The first character of all runtime options is AUTOMATICALLY the
4216   hyphen.
4217 
4218 .seealso: [](ch_ts), `TS`, `TSSetFromOptions()`, `TSAppendOptionsPrefix()`
4219 @*/
4220 PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[])
4221 {
4222   SNES snes;
4223 
4224   PetscFunctionBegin;
4225   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4226   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix));
4227   PetscCall(TSGetSNES(ts, &snes));
4228   PetscCall(SNESSetOptionsPrefix(snes, prefix));
4229   PetscFunctionReturn(PETSC_SUCCESS);
4230 }
4231 
4232 /*@
4233   TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4234   TS options in the database.
4235 
4236   Logically Collective
4237 
4238   Input Parameters:
4239 + ts     - The `TS` context
4240 - prefix - The prefix to prepend to all option names
4241 
4242   Level: advanced
4243 
4244   Note:
4245   A hyphen (-) must NOT be given at the beginning of the prefix name.
4246   The first character of all runtime options is AUTOMATICALLY the
4247   hyphen.
4248 
4249 .seealso: [](ch_ts), `TS`, `TSGetOptionsPrefix()`, `TSSetOptionsPrefix()`, `TSSetFromOptions()`
4250 @*/
4251 PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[])
4252 {
4253   SNES snes;
4254 
4255   PetscFunctionBegin;
4256   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4257   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix));
4258   PetscCall(TSGetSNES(ts, &snes));
4259   PetscCall(SNESAppendOptionsPrefix(snes, prefix));
4260   PetscFunctionReturn(PETSC_SUCCESS);
4261 }
4262 
4263 /*@
4264   TSGetOptionsPrefix - Sets the prefix used for searching for all
4265   `TS` options in the database.
4266 
4267   Not Collective
4268 
4269   Input Parameter:
4270 . ts - The `TS` context
4271 
4272   Output Parameter:
4273 . prefix - A pointer to the prefix string used
4274 
4275   Level: intermediate
4276 
4277   Fortran Notes:
4278   The user should pass in a string 'prefix' of
4279   sufficient length to hold the prefix.
4280 
4281 .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()`
4282 @*/
4283 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[])
4284 {
4285   PetscFunctionBegin;
4286   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4287   PetscAssertPointer(prefix, 2);
4288   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix));
4289   PetscFunctionReturn(PETSC_SUCCESS);
4290 }
4291 
4292 /*@C
4293   TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4294 
4295   Not Collective, but parallel objects are returned if ts is parallel
4296 
4297   Input Parameter:
4298 . ts - The `TS` context obtained from `TSCreate()`
4299 
4300   Output Parameters:
4301 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or `NULL`)
4302 . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat`  (or `NULL`)
4303 . func - Function to compute the Jacobian of the RHS  (or `NULL`)
4304 - ctx  - User-defined context for Jacobian evaluation routine  (or `NULL`)
4305 
4306   Level: intermediate
4307 
4308   Note:
4309   You can pass in `NULL` for any return argument you do not need.
4310 
4311 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4312 
4313 @*/
4314 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, void **ctx)
4315 {
4316   DM dm;
4317 
4318   PetscFunctionBegin;
4319   if (Amat || Pmat) {
4320     SNES snes;
4321     PetscCall(TSGetSNES(ts, &snes));
4322     PetscCall(SNESSetUpMatrices(snes));
4323     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4324   }
4325   PetscCall(TSGetDM(ts, &dm));
4326   PetscCall(DMTSGetRHSJacobian(dm, func, ctx));
4327   PetscFunctionReturn(PETSC_SUCCESS);
4328 }
4329 
4330 /*@C
4331   TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4332 
4333   Not Collective, but parallel objects are returned if ts is parallel
4334 
4335   Input Parameter:
4336 . ts - The `TS` context obtained from `TSCreate()`
4337 
4338   Output Parameters:
4339 + Amat - The (approximate) Jacobian of F(t,U,U_t)
4340 . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat`
4341 . f    - The function to compute the matrices
4342 - ctx  - User-defined context for Jacobian evaluation routine
4343 
4344   Level: advanced
4345 
4346   Note:
4347   You can pass in `NULL` for any return argument you do not need.
4348 
4349 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4350 @*/
4351 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, void **ctx)
4352 {
4353   DM dm;
4354 
4355   PetscFunctionBegin;
4356   if (Amat || Pmat) {
4357     SNES snes;
4358     PetscCall(TSGetSNES(ts, &snes));
4359     PetscCall(SNESSetUpMatrices(snes));
4360     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4361   }
4362   PetscCall(TSGetDM(ts, &dm));
4363   PetscCall(DMTSGetIJacobian(dm, f, ctx));
4364   PetscFunctionReturn(PETSC_SUCCESS);
4365 }
4366 
4367 #include <petsc/private/dmimpl.h>
4368 /*@
4369   TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS`
4370 
4371   Logically Collective
4372 
4373   Input Parameters:
4374 + ts - the `TS` integrator object
4375 - dm - the dm, cannot be `NULL`
4376 
4377   Level: intermediate
4378 
4379   Notes:
4380   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
4381   even when not using interfaces like `DMTSSetIFunction()`.  Use `DMClone()` to get a distinct `DM` when solving
4382   different problems using the same function space.
4383 
4384 .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()`
4385 @*/
4386 PetscErrorCode TSSetDM(TS ts, DM dm)
4387 {
4388   SNES snes;
4389   DMTS tsdm;
4390 
4391   PetscFunctionBegin;
4392   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4393   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
4394   PetscCall(PetscObjectReference((PetscObject)dm));
4395   if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */
4396     if (ts->dm->dmts && !dm->dmts) {
4397       PetscCall(DMCopyDMTS(ts->dm, dm));
4398       PetscCall(DMGetDMTS(ts->dm, &tsdm));
4399       /* Grant write privileges to the replacement DM */
4400       if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm;
4401     }
4402     PetscCall(DMDestroy(&ts->dm));
4403   }
4404   ts->dm = dm;
4405 
4406   PetscCall(TSGetSNES(ts, &snes));
4407   PetscCall(SNESSetDM(snes, dm));
4408   PetscFunctionReturn(PETSC_SUCCESS);
4409 }
4410 
4411 /*@
4412   TSGetDM - Gets the `DM` that may be used by some preconditioners
4413 
4414   Not Collective
4415 
4416   Input Parameter:
4417 . ts - the `TS`
4418 
4419   Output Parameter:
4420 . dm - the `DM`
4421 
4422   Level: intermediate
4423 
4424 .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()`
4425 @*/
4426 PetscErrorCode TSGetDM(TS ts, DM *dm)
4427 {
4428   PetscFunctionBegin;
4429   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4430   if (!ts->dm) {
4431     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm));
4432     if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm));
4433   }
4434   *dm = ts->dm;
4435   PetscFunctionReturn(PETSC_SUCCESS);
4436 }
4437 
4438 /*@
4439   SNESTSFormFunction - Function to evaluate nonlinear residual
4440 
4441   Logically Collective
4442 
4443   Input Parameters:
4444 + snes - nonlinear solver
4445 . U    - the current state at which to evaluate the residual
4446 - ctx  - user context, must be a TS
4447 
4448   Output Parameter:
4449 . F - the nonlinear residual
4450 
4451   Level: advanced
4452 
4453   Note:
4454   This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.
4455   It is most frequently passed to `MatFDColoringSetFunction()`.
4456 
4457 .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()`
4458 @*/
4459 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx)
4460 {
4461   TS ts = (TS)ctx;
4462 
4463   PetscFunctionBegin;
4464   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4465   PetscValidHeaderSpecific(U, VEC_CLASSID, 2);
4466   PetscValidHeaderSpecific(F, VEC_CLASSID, 3);
4467   PetscValidHeaderSpecific(ts, TS_CLASSID, 4);
4468   PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name);
4469   PetscCall((*ts->ops->snesfunction)(snes, U, F, ts));
4470   PetscFunctionReturn(PETSC_SUCCESS);
4471 }
4472 
4473 /*@
4474   SNESTSFormJacobian - Function to evaluate the Jacobian
4475 
4476   Collective
4477 
4478   Input Parameters:
4479 + snes - nonlinear solver
4480 . U    - the current state at which to evaluate the residual
4481 - ctx  - user context, must be a `TS`
4482 
4483   Output Parameters:
4484 + A - the Jacobian
4485 - B - the preconditioning matrix (may be the same as A)
4486 
4487   Level: developer
4488 
4489   Note:
4490   This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.
4491 
4492 .seealso: [](ch_ts), `SNESSetJacobian()`
4493 @*/
4494 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx)
4495 {
4496   TS ts = (TS)ctx;
4497 
4498   PetscFunctionBegin;
4499   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4500   PetscValidHeaderSpecific(U, VEC_CLASSID, 2);
4501   PetscValidHeaderSpecific(A, MAT_CLASSID, 3);
4502   PetscValidHeaderSpecific(B, MAT_CLASSID, 4);
4503   PetscValidHeaderSpecific(ts, TS_CLASSID, 5);
4504   PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name);
4505   PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts));
4506   PetscFunctionReturn(PETSC_SUCCESS);
4507 }
4508 
4509 /*@C
4510   TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only
4511 
4512   Collective
4513 
4514   Input Parameters:
4515 + ts  - time stepping context
4516 . t   - time at which to evaluate
4517 . U   - state at which to evaluate
4518 - ctx - context
4519 
4520   Output Parameter:
4521 . F - right-hand side
4522 
4523   Level: intermediate
4524 
4525   Note:
4526   This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems.
4527   The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`.
4528 
4529 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
4530 @*/
4531 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx)
4532 {
4533   Mat Arhs, Brhs;
4534 
4535   PetscFunctionBegin;
4536   PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
4537   /* undo the damage caused by shifting */
4538   PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs));
4539   PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
4540   PetscCall(MatMult(Arhs, U, F));
4541   PetscFunctionReturn(PETSC_SUCCESS);
4542 }
4543 
4544 /*@C
4545   TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
4546 
4547   Collective
4548 
4549   Input Parameters:
4550 + ts  - time stepping context
4551 . t   - time at which to evaluate
4552 . U   - state at which to evaluate
4553 - ctx - context
4554 
4555   Output Parameters:
4556 + A - pointer to operator
4557 - B - pointer to preconditioning matrix
4558 
4559   Level: intermediate
4560 
4561   Note:
4562   This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems.
4563 
4564 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()`
4565 @*/
4566 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx)
4567 {
4568   PetscFunctionBegin;
4569   PetscFunctionReturn(PETSC_SUCCESS);
4570 }
4571 
4572 /*@C
4573   TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
4574 
4575   Collective
4576 
4577   Input Parameters:
4578 + ts   - time stepping context
4579 . t    - time at which to evaluate
4580 . U    - state at which to evaluate
4581 . Udot - time derivative of state vector
4582 - ctx  - context
4583 
4584   Output Parameter:
4585 . F - left hand side
4586 
4587   Level: intermediate
4588 
4589   Notes:
4590   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
4591   user is required to write their own `TSComputeIFunction()`.
4592   This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems.
4593   The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`.
4594 
4595   Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U
4596 
4597 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()`
4598 @*/
4599 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx)
4600 {
4601   Mat A, B;
4602 
4603   PetscFunctionBegin;
4604   PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL));
4605   PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE));
4606   PetscCall(MatMult(A, Udot, F));
4607   PetscFunctionReturn(PETSC_SUCCESS);
4608 }
4609 
4610 /*@C
4611   TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE
4612 
4613   Collective
4614 
4615   Input Parameters:
4616 + ts    - time stepping context
4617 . t     - time at which to evaluate
4618 . U     - state at which to evaluate
4619 . Udot  - time derivative of state vector
4620 . shift - shift to apply
4621 - ctx   - context
4622 
4623   Output Parameters:
4624 + A - pointer to operator
4625 - B - pointer to matrix from which the preconditioner is built (often `A`)
4626 
4627   Level: advanced
4628 
4629   Notes:
4630   This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems.
4631 
4632   It is only appropriate for problems of the form
4633 
4634   $$
4635   M \dot{U} = F(U,t)
4636   $$
4637 
4638   where M is constant and F is non-stiff.  The user must pass M to `TSSetIJacobian()`.  The current implementation only
4639   works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing
4640   an implicit operator of the form
4641 
4642   $$
4643   shift*M + J
4644   $$
4645 
4646   where J is the Jacobian of -F(U).  Support may be added in a future version of PETSc, but for now, the user must store
4647   a copy of M or reassemble it when requested.
4648 
4649 .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()`
4650 @*/
4651 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx)
4652 {
4653   PetscFunctionBegin;
4654   PetscCall(MatScale(A, shift / ts->ijacobian.shift));
4655   ts->ijacobian.shift = shift;
4656   PetscFunctionReturn(PETSC_SUCCESS);
4657 }
4658 
4659 /*@
4660   TSGetEquationType - Gets the type of the equation that `TS` is solving.
4661 
4662   Not Collective
4663 
4664   Input Parameter:
4665 . ts - the `TS` context
4666 
4667   Output Parameter:
4668 . equation_type - see `TSEquationType`
4669 
4670   Level: beginner
4671 
4672 .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType`
4673 @*/
4674 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type)
4675 {
4676   PetscFunctionBegin;
4677   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4678   PetscAssertPointer(equation_type, 2);
4679   *equation_type = ts->equation_type;
4680   PetscFunctionReturn(PETSC_SUCCESS);
4681 }
4682 
4683 /*@
4684   TSSetEquationType - Sets the type of the equation that `TS` is solving.
4685 
4686   Not Collective
4687 
4688   Input Parameters:
4689 + ts            - the `TS` context
4690 - equation_type - see `TSEquationType`
4691 
4692   Level: advanced
4693 
4694 .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType`
4695 @*/
4696 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type)
4697 {
4698   PetscFunctionBegin;
4699   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4700   ts->equation_type = equation_type;
4701   PetscFunctionReturn(PETSC_SUCCESS);
4702 }
4703 
4704 /*@
4705   TSGetConvergedReason - Gets the reason the `TS` iteration was stopped.
4706 
4707   Not Collective
4708 
4709   Input Parameter:
4710 . ts - the `TS` context
4711 
4712   Output Parameter:
4713 . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4714             manual pages for the individual convergence tests for complete lists
4715 
4716   Level: beginner
4717 
4718   Note:
4719   Can only be called after the call to `TSSolve()` is complete.
4720 
4721 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4722 @*/
4723 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason)
4724 {
4725   PetscFunctionBegin;
4726   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4727   PetscAssertPointer(reason, 2);
4728   *reason = ts->reason;
4729   PetscFunctionReturn(PETSC_SUCCESS);
4730 }
4731 
4732 /*@
4733   TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`.
4734 
4735   Logically Collective; reason must contain common value
4736 
4737   Input Parameters:
4738 + ts     - the `TS` context
4739 - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4740             manual pages for the individual convergence tests for complete lists
4741 
4742   Level: advanced
4743 
4744   Note:
4745   Can only be called while `TSSolve()` is active.
4746 
4747 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4748 @*/
4749 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason)
4750 {
4751   PetscFunctionBegin;
4752   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4753   ts->reason = reason;
4754   PetscFunctionReturn(PETSC_SUCCESS);
4755 }
4756 
4757 /*@
4758   TSGetSolveTime - Gets the time after a call to `TSSolve()`
4759 
4760   Not Collective
4761 
4762   Input Parameter:
4763 . ts - the `TS` context
4764 
4765   Output Parameter:
4766 . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()`
4767 
4768   Level: beginner
4769 
4770   Note:
4771   Can only be called after the call to `TSSolve()` is complete.
4772 
4773 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4774 @*/
4775 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime)
4776 {
4777   PetscFunctionBegin;
4778   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4779   PetscAssertPointer(ftime, 2);
4780   *ftime = ts->solvetime;
4781   PetscFunctionReturn(PETSC_SUCCESS);
4782 }
4783 
4784 /*@
4785   TSGetSNESIterations - Gets the total number of nonlinear iterations
4786   used by the time integrator.
4787 
4788   Not Collective
4789 
4790   Input Parameter:
4791 . ts - `TS` context
4792 
4793   Output Parameter:
4794 . nits - number of nonlinear iterations
4795 
4796   Level: intermediate
4797 
4798   Note:
4799   This counter is reset to zero for each successive call to `TSSolve()`.
4800 
4801 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()`
4802 @*/
4803 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits)
4804 {
4805   PetscFunctionBegin;
4806   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4807   PetscAssertPointer(nits, 2);
4808   *nits = ts->snes_its;
4809   PetscFunctionReturn(PETSC_SUCCESS);
4810 }
4811 
4812 /*@
4813   TSGetKSPIterations - Gets the total number of linear iterations
4814   used by the time integrator.
4815 
4816   Not Collective
4817 
4818   Input Parameter:
4819 . ts - `TS` context
4820 
4821   Output Parameter:
4822 . lits - number of linear iterations
4823 
4824   Level: intermediate
4825 
4826   Note:
4827   This counter is reset to zero for each successive call to `TSSolve()`.
4828 
4829 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `SNESGetKSPIterations()`
4830 @*/
4831 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits)
4832 {
4833   PetscFunctionBegin;
4834   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4835   PetscAssertPointer(lits, 2);
4836   *lits = ts->ksp_its;
4837   PetscFunctionReturn(PETSC_SUCCESS);
4838 }
4839 
4840 /*@
4841   TSGetStepRejections - Gets the total number of rejected steps.
4842 
4843   Not Collective
4844 
4845   Input Parameter:
4846 . ts - `TS` context
4847 
4848   Output Parameter:
4849 . rejects - number of steps rejected
4850 
4851   Level: intermediate
4852 
4853   Note:
4854   This counter is reset to zero for each successive call to `TSSolve()`.
4855 
4856 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()`
4857 @*/
4858 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects)
4859 {
4860   PetscFunctionBegin;
4861   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4862   PetscAssertPointer(rejects, 2);
4863   *rejects = ts->reject;
4864   PetscFunctionReturn(PETSC_SUCCESS);
4865 }
4866 
4867 /*@
4868   TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS`
4869 
4870   Not Collective
4871 
4872   Input Parameter:
4873 . ts - `TS` context
4874 
4875   Output Parameter:
4876 . fails - number of failed nonlinear solves
4877 
4878   Level: intermediate
4879 
4880   Note:
4881   This counter is reset to zero for each successive call to `TSSolve()`.
4882 
4883 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()`
4884 @*/
4885 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails)
4886 {
4887   PetscFunctionBegin;
4888   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4889   PetscAssertPointer(fails, 2);
4890   *fails = ts->num_snes_failures;
4891   PetscFunctionReturn(PETSC_SUCCESS);
4892 }
4893 
4894 /*@
4895   TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails
4896 
4897   Not Collective
4898 
4899   Input Parameters:
4900 + ts      - `TS` context
4901 - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited
4902 
4903   Options Database Key:
4904 . -ts_max_reject - Maximum number of step rejections before a step fails
4905 
4906   Level: intermediate
4907 
4908   Developer Note:
4909   The options database name is incorrect.
4910 
4911 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()`
4912 @*/
4913 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects)
4914 {
4915   PetscFunctionBegin;
4916   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4917   if (rejects == PETSC_UNLIMITED || rejects == -1) {
4918     ts->max_reject = PETSC_UNLIMITED;
4919   } else {
4920     PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections");
4921     ts->max_reject = rejects;
4922   }
4923   PetscFunctionReturn(PETSC_SUCCESS);
4924 }
4925 
4926 /*@
4927   TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves
4928 
4929   Not Collective
4930 
4931   Input Parameters:
4932 + ts    - `TS` context
4933 - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures.
4934 
4935   Options Database Key:
4936 . -ts_max_snes_failures - Maximum number of nonlinear solve failures
4937 
4938   Level: intermediate
4939 
4940 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()`
4941 @*/
4942 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails)
4943 {
4944   PetscFunctionBegin;
4945   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4946   if (fails == PETSC_UNLIMITED || fails == -1) {
4947     ts->max_snes_failures = PETSC_UNLIMITED;
4948   } else {
4949     PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
4950     ts->max_snes_failures = fails;
4951   }
4952   PetscFunctionReturn(PETSC_SUCCESS);
4953 }
4954 
4955 /*@
4956   TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()`
4957 
4958   Not Collective
4959 
4960   Input Parameters:
4961 + ts  - `TS` context
4962 - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure
4963 
4964   Options Database Key:
4965 . -ts_error_if_step_fails - Error if no step succeeds
4966 
4967   Level: intermediate
4968 
4969 .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()`
4970 @*/
4971 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err)
4972 {
4973   PetscFunctionBegin;
4974   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4975   ts->errorifstepfailed = err;
4976   PetscFunctionReturn(PETSC_SUCCESS);
4977 }
4978 
4979 /*@
4980   TSGetAdapt - Get the adaptive controller context for the current method
4981 
4982   Collective if controller has not yet been created
4983 
4984   Input Parameter:
4985 . ts - time stepping context
4986 
4987   Output Parameter:
4988 . adapt - adaptive controller
4989 
4990   Level: intermediate
4991 
4992 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()`
4993 @*/
4994 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt)
4995 {
4996   PetscFunctionBegin;
4997   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4998   PetscAssertPointer(adapt, 2);
4999   if (!ts->adapt) {
5000     PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt));
5001     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1));
5002   }
5003   *adapt = ts->adapt;
5004   PetscFunctionReturn(PETSC_SUCCESS);
5005 }
5006 
5007 /*@
5008   TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller
5009 
5010   Logically Collective
5011 
5012   Input Parameters:
5013 + ts    - time integration context
5014 . atol  - scalar absolute tolerances
5015 . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present
5016 . rtol  - scalar relative tolerances
5017 - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present
5018 
5019   Options Database Keys:
5020 + -ts_rtol <rtol> - relative tolerance for local truncation error
5021 - -ts_atol <atol> - Absolute tolerance for local truncation error
5022 
5023   Level: beginner
5024 
5025   Notes:
5026   `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value
5027   or the default value from when the object's type was set.
5028 
5029   With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5030   (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5031   computed only for the differential or the algebraic part then this can be done using the vector of
5032   tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5033   differential part and infinity for the algebraic part, the LTE calculation will include only the
5034   differential variables.
5035 
5036   Fortran Note:
5037   Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`.
5038 
5039 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()`
5040 @*/
5041 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol)
5042 {
5043   PetscFunctionBegin;
5044   if (atol == (PetscReal)PETSC_DETERMINE) {
5045     ts->atol = ts->default_atol;
5046   } else if (atol != (PetscReal)PETSC_CURRENT) {
5047     PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol);
5048     ts->atol = atol;
5049   }
5050 
5051   if (vatol) {
5052     PetscCall(PetscObjectReference((PetscObject)vatol));
5053     PetscCall(VecDestroy(&ts->vatol));
5054     ts->vatol = vatol;
5055   }
5056 
5057   if (rtol == (PetscReal)PETSC_DETERMINE) {
5058     ts->rtol = ts->default_rtol;
5059   } else if (rtol != (PetscReal)PETSC_CURRENT) {
5060     PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol);
5061     ts->rtol = rtol;
5062   }
5063 
5064   if (vrtol) {
5065     PetscCall(PetscObjectReference((PetscObject)vrtol));
5066     PetscCall(VecDestroy(&ts->vrtol));
5067     ts->vrtol = vrtol;
5068   }
5069   PetscFunctionReturn(PETSC_SUCCESS);
5070 }
5071 
5072 /*@
5073   TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
5074 
5075   Logically Collective
5076 
5077   Input Parameter:
5078 . ts - time integration context
5079 
5080   Output Parameters:
5081 + atol  - scalar absolute tolerances, `NULL` to ignore
5082 . vatol - vector of absolute tolerances, `NULL` to ignore
5083 . rtol  - scalar relative tolerances, `NULL` to ignore
5084 - vrtol - vector of relative tolerances, `NULL` to ignore
5085 
5086   Level: beginner
5087 
5088 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()`
5089 @*/
5090 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol)
5091 {
5092   PetscFunctionBegin;
5093   if (atol) *atol = ts->atol;
5094   if (vatol) *vatol = ts->vatol;
5095   if (rtol) *rtol = ts->rtol;
5096   if (vrtol) *vrtol = ts->vrtol;
5097   PetscFunctionReturn(PETSC_SUCCESS);
5098 }
5099 
5100 /*@
5101   TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
5102 
5103   Collective
5104 
5105   Input Parameters:
5106 + ts        - time stepping context
5107 . U         - state vector, usually ts->vec_sol
5108 . Y         - state vector to be compared to U
5109 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
5110 
5111   Output Parameters:
5112 + norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5113 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5114 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5115 
5116   Options Database Key:
5117 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5118 
5119   Level: developer
5120 
5121 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()`
5122 @*/
5123 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5124 {
5125   PetscInt norma_loc, norm_loc, normr_loc;
5126 
5127   PetscFunctionBegin;
5128   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5129   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));
5130   if (wnormtype == NORM_2) {
5131     if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5132     if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5133     if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5134   }
5135   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5136   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5137   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5138   PetscFunctionReturn(PETSC_SUCCESS);
5139 }
5140 
5141 /*@
5142   TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
5143 
5144   Collective
5145 
5146   Input Parameters:
5147 + ts        - time stepping context
5148 . E         - error vector
5149 . U         - state vector, usually ts->vec_sol
5150 . Y         - state vector, previous time step
5151 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
5152 
5153   Output Parameters:
5154 + norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5155 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5156 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5157 
5158   Options Database Key:
5159 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5160 
5161   Level: developer
5162 
5163 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()`
5164 @*/
5165 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5166 {
5167   PetscInt norma_loc, norm_loc, normr_loc;
5168 
5169   PetscFunctionBegin;
5170   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5171   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));
5172   if (wnormtype == NORM_2) {
5173     if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5174     if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5175     if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5176   }
5177   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5178   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5179   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5180   PetscFunctionReturn(PETSC_SUCCESS);
5181 }
5182 
5183 /*@
5184   TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
5185 
5186   Logically Collective
5187 
5188   Input Parameters:
5189 + ts      - time stepping context
5190 - cfltime - maximum stable time step if using forward Euler (value can be different on each process)
5191 
5192   Note:
5193   After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
5194 
5195   Level: intermediate
5196 
5197 .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL`
5198 @*/
5199 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime)
5200 {
5201   PetscFunctionBegin;
5202   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5203   ts->cfltime_local = cfltime;
5204   ts->cfltime       = -1.;
5205   PetscFunctionReturn(PETSC_SUCCESS);
5206 }
5207 
5208 /*@
5209   TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
5210 
5211   Collective
5212 
5213   Input Parameter:
5214 . ts - time stepping context
5215 
5216   Output Parameter:
5217 . cfltime - maximum stable time step for forward Euler
5218 
5219   Level: advanced
5220 
5221 .seealso: [](ch_ts), `TSSetCFLTimeLocal()`
5222 @*/
5223 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime)
5224 {
5225   PetscFunctionBegin;
5226   if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts)));
5227   *cfltime = ts->cfltime;
5228   PetscFunctionReturn(PETSC_SUCCESS);
5229 }
5230 
5231 /*@
5232   TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
5233 
5234   Input Parameters:
5235 + ts - the `TS` context.
5236 . xl - lower bound.
5237 - xu - upper bound.
5238 
5239   Level: advanced
5240 
5241   Note:
5242   If this routine is not called then the lower and upper bounds are set to
5243   `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`.
5244 
5245 .seealso: [](ch_ts), `TS`
5246 @*/
5247 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
5248 {
5249   SNES snes;
5250 
5251   PetscFunctionBegin;
5252   PetscCall(TSGetSNES(ts, &snes));
5253   PetscCall(SNESVISetVariableBounds(snes, xl, xu));
5254   PetscFunctionReturn(PETSC_SUCCESS);
5255 }
5256 
5257 /*@
5258   TSComputeLinearStability - computes the linear stability function at a point
5259 
5260   Collective
5261 
5262   Input Parameters:
5263 + ts - the `TS` context
5264 . xr - real part of input argument
5265 - xi - imaginary part of input argument
5266 
5267   Output Parameters:
5268 + yr - real part of function value
5269 - yi - imaginary part of function value
5270 
5271   Level: developer
5272 
5273 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
5274 @*/
5275 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi)
5276 {
5277   PetscFunctionBegin;
5278   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5279   PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi);
5280   PetscFunctionReturn(PETSC_SUCCESS);
5281 }
5282 
5283 /*@
5284   TSRestartStep - Flags the solver to restart the next step
5285 
5286   Collective
5287 
5288   Input Parameter:
5289 . ts - the `TS` context obtained from `TSCreate()`
5290 
5291   Level: advanced
5292 
5293   Notes:
5294   Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of
5295   discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
5296   vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
5297   the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce
5298   discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
5299   discontinuous source terms).
5300 
5301 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()`
5302 @*/
5303 PetscErrorCode TSRestartStep(TS ts)
5304 {
5305   PetscFunctionBegin;
5306   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5307   ts->steprestart = PETSC_TRUE;
5308   PetscFunctionReturn(PETSC_SUCCESS);
5309 }
5310 
5311 /*@
5312   TSRollBack - Rolls back one time step
5313 
5314   Collective
5315 
5316   Input Parameter:
5317 . ts - the `TS` context obtained from `TSCreate()`
5318 
5319   Level: advanced
5320 
5321 .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()`
5322 @*/
5323 PetscErrorCode TSRollBack(TS ts)
5324 {
5325   PetscFunctionBegin;
5326   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5327   PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called");
5328   PetscTryTypeMethod(ts, rollback);
5329   PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol));
5330   ts->time_step  = ts->ptime - ts->ptime_prev;
5331   ts->ptime      = ts->ptime_prev;
5332   ts->ptime_prev = ts->ptime_prev_rollback;
5333   ts->steps--;
5334   ts->steprollback = PETSC_TRUE;
5335   PetscFunctionReturn(PETSC_SUCCESS);
5336 }
5337 
5338 /*@
5339   TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step
5340 
5341   Not collective
5342 
5343   Input Parameter:
5344 . ts - the `TS` context obtained from `TSCreate()`
5345 
5346   Output Parameter:
5347 . flg - the rollback flag
5348 
5349   Level: advanced
5350 
5351 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()`
5352 @*/
5353 PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg)
5354 {
5355   PetscFunctionBegin;
5356   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5357   PetscAssertPointer(flg, 2);
5358   *flg = ts->steprollback;
5359   PetscFunctionReturn(PETSC_SUCCESS);
5360 }
5361 
5362 /*@
5363   TSGetStepResize - Get the internal flag indicating if the current step is after a resize.
5364 
5365   Not collective
5366 
5367   Input Parameter:
5368 . ts - the `TS` context obtained from `TSCreate()`
5369 
5370   Output Parameter:
5371 . flg - the resize flag
5372 
5373   Level: advanced
5374 
5375 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()`
5376 @*/
5377 PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg)
5378 {
5379   PetscFunctionBegin;
5380   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5381   PetscAssertPointer(flg, 2);
5382   *flg = ts->stepresize;
5383   PetscFunctionReturn(PETSC_SUCCESS);
5384 }
5385 
5386 /*@
5387   TSGetStages - Get the number of stages and stage values
5388 
5389   Input Parameter:
5390 . ts - the `TS` context obtained from `TSCreate()`
5391 
5392   Output Parameters:
5393 + ns - the number of stages
5394 - Y  - the current stage vectors
5395 
5396   Level: advanced
5397 
5398   Note:
5399   Both `ns` and `Y` can be `NULL`.
5400 
5401 .seealso: [](ch_ts), `TS`, `TSCreate()`
5402 @*/
5403 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y)
5404 {
5405   PetscFunctionBegin;
5406   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5407   if (ns) PetscAssertPointer(ns, 2);
5408   if (Y) PetscAssertPointer(Y, 3);
5409   if (!ts->ops->getstages) {
5410     if (ns) *ns = 0;
5411     if (Y) *Y = NULL;
5412   } else PetscUseTypeMethod(ts, getstages, ns, Y);
5413   PetscFunctionReturn(PETSC_SUCCESS);
5414 }
5415 
5416 /*@C
5417   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
5418 
5419   Collective
5420 
5421   Input Parameters:
5422 + ts    - the `TS` context
5423 . t     - current timestep
5424 . U     - state vector
5425 . Udot  - time derivative of state vector
5426 . shift - shift to apply, see note below
5427 - ctx   - an optional user context
5428 
5429   Output Parameters:
5430 + J - Jacobian matrix (not altered in this routine)
5431 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`)
5432 
5433   Level: intermediate
5434 
5435   Notes:
5436   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
5437 
5438   dF/dU + shift*dF/dUdot
5439 
5440   Most users should not need to explicitly call this routine, as it
5441   is used internally within the nonlinear solvers.
5442 
5443   This will first try to get the coloring from the `DM`.  If the `DM` type has no coloring
5444   routine, then it will try to get the coloring from the matrix.  This requires that the
5445   matrix have nonzero entries precomputed.
5446 
5447 .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
5448 @*/
5449 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx)
5450 {
5451   SNES          snes;
5452   MatFDColoring color;
5453   PetscBool     hascolor, matcolor = PETSC_FALSE;
5454 
5455   PetscFunctionBegin;
5456   PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL));
5457   PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color));
5458   if (!color) {
5459     DM         dm;
5460     ISColoring iscoloring;
5461 
5462     PetscCall(TSGetDM(ts, &dm));
5463     PetscCall(DMHasColoring(dm, &hascolor));
5464     if (hascolor && !matcolor) {
5465       PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring));
5466       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5467       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
5468       PetscCall(MatFDColoringSetFromOptions(color));
5469       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5470       PetscCall(ISColoringDestroy(&iscoloring));
5471     } else {
5472       MatColoring mc;
5473 
5474       PetscCall(MatColoringCreate(B, &mc));
5475       PetscCall(MatColoringSetDistance(mc, 2));
5476       PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
5477       PetscCall(MatColoringSetFromOptions(mc));
5478       PetscCall(MatColoringApply(mc, &iscoloring));
5479       PetscCall(MatColoringDestroy(&mc));
5480       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5481       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
5482       PetscCall(MatFDColoringSetFromOptions(color));
5483       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5484       PetscCall(ISColoringDestroy(&iscoloring));
5485     }
5486     PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color));
5487     PetscCall(PetscObjectDereference((PetscObject)color));
5488   }
5489   PetscCall(TSGetSNES(ts, &snes));
5490   PetscCall(MatFDColoringApply(B, color, U, snes));
5491   if (J != B) {
5492     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
5493     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
5494   }
5495   PetscFunctionReturn(PETSC_SUCCESS);
5496 }
5497 
5498 /*@C
5499   TSSetFunctionDomainError - Set a function that tests if the current state vector is valid
5500 
5501   Input Parameters:
5502 + ts   - the `TS` context
5503 - func - function called within `TSFunctionDomainError()`
5504 
5505   Calling sequence of `func`:
5506 + ts     - the `TS` context
5507 . time   - the current time (of the stage)
5508 . state  - the state to check if it is valid
5509 - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable
5510 
5511   Level: intermediate
5512 
5513   Notes:
5514   If an implicit ODE solver is being used then, in addition to providing this routine, the
5515   user's code should call `SNESSetFunctionDomainError()` when domain errors occur during
5516   function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`.
5517   Use `TSGetSNES()` to obtain the `SNES` object
5518 
5519   Developer Notes:
5520   The naming of this function is inconsistent with the `SNESSetFunctionDomainError()`
5521   since one takes a function pointer and the other does not.
5522 
5523 .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()`
5524 @*/
5525 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept))
5526 {
5527   PetscFunctionBegin;
5528   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5529   ts->functiondomainerror = func;
5530   PetscFunctionReturn(PETSC_SUCCESS);
5531 }
5532 
5533 /*@
5534   TSFunctionDomainError - Checks if the current state is valid
5535 
5536   Input Parameters:
5537 + ts        - the `TS` context
5538 . stagetime - time of the simulation
5539 - Y         - state vector to check.
5540 
5541   Output Parameter:
5542 . accept - Set to `PETSC_FALSE` if the current state vector is valid.
5543 
5544   Level: developer
5545 
5546   Note:
5547   This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`)
5548   to check if the current state is valid.
5549 
5550 .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()`
5551 @*/
5552 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept)
5553 {
5554   PetscFunctionBegin;
5555   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5556   *accept = PETSC_TRUE;
5557   if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept));
5558   PetscFunctionReturn(PETSC_SUCCESS);
5559 }
5560 
5561 /*@
5562   TSClone - This function clones a time step `TS` object.
5563 
5564   Collective
5565 
5566   Input Parameter:
5567 . tsin - The input `TS`
5568 
5569   Output Parameter:
5570 . tsout - The output `TS` (cloned)
5571 
5572   Level: developer
5573 
5574   Notes:
5575   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.
5576   It will likely be replaced in the future with a mechanism of switching methods on the fly.
5577 
5578   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
5579 .vb
5580  SNES snes_dup = NULL;
5581  TSGetSNES(ts,&snes_dup);
5582  TSSetSNES(ts,snes_dup);
5583 .ve
5584 
5585 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()`
5586 @*/
5587 PetscErrorCode TSClone(TS tsin, TS *tsout)
5588 {
5589   TS     t;
5590   SNES   snes_start;
5591   DM     dm;
5592   TSType type;
5593 
5594   PetscFunctionBegin;
5595   PetscAssertPointer(tsin, 1);
5596   *tsout = NULL;
5597 
5598   PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView));
5599 
5600   /* General TS description */
5601   t->numbermonitors    = 0;
5602   t->monitorFrequency  = 1;
5603   t->setupcalled       = 0;
5604   t->ksp_its           = 0;
5605   t->snes_its          = 0;
5606   t->nwork             = 0;
5607   t->rhsjacobian.time  = PETSC_MIN_REAL;
5608   t->rhsjacobian.scale = 1.;
5609   t->ijacobian.shift   = 1.;
5610 
5611   PetscCall(TSGetSNES(tsin, &snes_start));
5612   PetscCall(TSSetSNES(t, snes_start));
5613 
5614   PetscCall(TSGetDM(tsin, &dm));
5615   PetscCall(TSSetDM(t, dm));
5616 
5617   t->adapt = tsin->adapt;
5618   PetscCall(PetscObjectReference((PetscObject)t->adapt));
5619 
5620   t->trajectory = tsin->trajectory;
5621   PetscCall(PetscObjectReference((PetscObject)t->trajectory));
5622 
5623   t->event = tsin->event;
5624   if (t->event) t->event->refct++;
5625 
5626   t->problem_type      = tsin->problem_type;
5627   t->ptime             = tsin->ptime;
5628   t->ptime_prev        = tsin->ptime_prev;
5629   t->time_step         = tsin->time_step;
5630   t->max_time          = tsin->max_time;
5631   t->steps             = tsin->steps;
5632   t->max_steps         = tsin->max_steps;
5633   t->equation_type     = tsin->equation_type;
5634   t->atol              = tsin->atol;
5635   t->rtol              = tsin->rtol;
5636   t->max_snes_failures = tsin->max_snes_failures;
5637   t->max_reject        = tsin->max_reject;
5638   t->errorifstepfailed = tsin->errorifstepfailed;
5639 
5640   PetscCall(TSGetType(tsin, &type));
5641   PetscCall(TSSetType(t, type));
5642 
5643   t->vec_sol = NULL;
5644 
5645   t->cfltime          = tsin->cfltime;
5646   t->cfltime_local    = tsin->cfltime_local;
5647   t->exact_final_time = tsin->exact_final_time;
5648 
5649   t->ops[0] = tsin->ops[0];
5650 
5651   if (((PetscObject)tsin)->fortran_func_pointers) {
5652     PetscInt i;
5653     PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers));
5654     for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
5655   }
5656   *tsout = t;
5657   PetscFunctionReturn(PETSC_SUCCESS);
5658 }
5659 
5660 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y)
5661 {
5662   TS ts = (TS)ctx;
5663 
5664   PetscFunctionBegin;
5665   PetscCall(TSComputeRHSFunction(ts, 0, x, y));
5666   PetscFunctionReturn(PETSC_SUCCESS);
5667 }
5668 
5669 /*@
5670   TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.
5671 
5672   Logically Collective
5673 
5674   Input Parameter:
5675 . ts - the time stepping routine
5676 
5677   Output Parameter:
5678 . flg - `PETSC_TRUE` if the multiply is likely correct
5679 
5680   Options Database Key:
5681 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
5682 
5683   Level: advanced
5684 
5685   Note:
5686   This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian
5687 
5688 .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()`
5689 @*/
5690 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg)
5691 {
5692   Mat              J, B;
5693   TSRHSJacobianFn *func;
5694   void            *ctx;
5695 
5696   PetscFunctionBegin;
5697   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5698   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5699   PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5700   PetscFunctionReturn(PETSC_SUCCESS);
5701 }
5702 
5703 /*@
5704   TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.
5705 
5706   Logically Collective
5707 
5708   Input Parameter:
5709 . ts - the time stepping routine
5710 
5711   Output Parameter:
5712 . flg - `PETSC_TRUE` if the multiply is likely correct
5713 
5714   Options Database Key:
5715 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
5716 
5717   Level: advanced
5718 
5719   Notes:
5720   This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian
5721 
5722 .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()`
5723 @*/
5724 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg)
5725 {
5726   Mat              J, B;
5727   void            *ctx;
5728   TSRHSJacobianFn *func;
5729 
5730   PetscFunctionBegin;
5731   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5732   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5733   PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5734   PetscFunctionReturn(PETSC_SUCCESS);
5735 }
5736 
5737 /*@
5738   TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used.
5739 
5740   Logically Collective
5741 
5742   Input Parameters:
5743 + ts                   - timestepping context
5744 - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used
5745 
5746   Options Database Key:
5747 . -ts_use_splitrhsfunction - <true,false>
5748 
5749   Level: intermediate
5750 
5751   Note:
5752   This is only for multirate methods
5753 
5754 .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()`
5755 @*/
5756 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction)
5757 {
5758   PetscFunctionBegin;
5759   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5760   ts->use_splitrhsfunction = use_splitrhsfunction;
5761   PetscFunctionReturn(PETSC_SUCCESS);
5762 }
5763 
5764 /*@
5765   TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used.
5766 
5767   Not Collective
5768 
5769   Input Parameter:
5770 . ts - timestepping context
5771 
5772   Output Parameter:
5773 . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used
5774 
5775   Level: intermediate
5776 
5777 .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()`
5778 @*/
5779 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction)
5780 {
5781   PetscFunctionBegin;
5782   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5783   *use_splitrhsfunction = ts->use_splitrhsfunction;
5784   PetscFunctionReturn(PETSC_SUCCESS);
5785 }
5786 
5787 /*@
5788   TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix.
5789 
5790   Logically  Collective
5791 
5792   Input Parameters:
5793 + ts  - the time-stepper
5794 - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`)
5795 
5796   Level: intermediate
5797 
5798   Note:
5799   When the relationship between the nonzero structures is known and supplied the solution process can be much faster
5800 
5801 .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure`
5802  @*/
5803 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str)
5804 {
5805   PetscFunctionBegin;
5806   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5807   ts->axpy_pattern = str;
5808   PetscFunctionReturn(PETSC_SUCCESS);
5809 }
5810 
5811 /*@
5812   TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span
5813 
5814   Collective
5815 
5816   Input Parameters:
5817 + ts         - the time-stepper
5818 . n          - number of the time points (>=2)
5819 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively.
5820 
5821   Options Database Key:
5822 . -ts_time_span <t0,...tf> - Sets the time span
5823 
5824   Level: intermediate
5825 
5826   Notes:
5827   The elements in tspan must be all increasing. They correspond to the intermediate points for time integration.
5828   `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.
5829   The intermediate solutions are saved in a vector array that can be accessed with `TSGetTimeSpanSolutions()`. Thus using time span may
5830   pressure the memory system when using a large number of span points.
5831 
5832 .seealso: [](ch_ts), `TS`, `TSGetTimeSpan()`, `TSGetTimeSpanSolutions()`
5833  @*/
5834 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times)
5835 {
5836   PetscFunctionBegin;
5837   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5838   PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n);
5839   if (ts->tspan && n != ts->tspan->num_span_times) {
5840     PetscCall(PetscFree(ts->tspan->span_times));
5841     PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol));
5842     PetscCall(PetscMalloc1(n, &ts->tspan->span_times));
5843   }
5844   if (!ts->tspan) {
5845     TSTimeSpan tspan;
5846     PetscCall(PetscNew(&tspan));
5847     PetscCall(PetscMalloc1(n, &tspan->span_times));
5848     tspan->reltol  = 1e-6;
5849     tspan->abstol  = 10 * PETSC_MACHINE_EPSILON;
5850     tspan->worktol = 0;
5851     ts->tspan      = tspan;
5852   }
5853   ts->tspan->num_span_times = n;
5854   PetscCall(PetscArraycpy(ts->tspan->span_times, span_times, n));
5855   PetscCall(TSSetTime(ts, ts->tspan->span_times[0]));
5856   PetscCall(TSSetMaxTime(ts, ts->tspan->span_times[n - 1]));
5857   PetscFunctionReturn(PETSC_SUCCESS);
5858 }
5859 
5860 /*@C
5861   TSGetTimeSpan - gets the time span set with `TSSetTimeSpan()`
5862 
5863   Not Collective
5864 
5865   Input Parameter:
5866 . ts - the time-stepper
5867 
5868   Output Parameters:
5869 + n          - number of the time points (>=2)
5870 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively.
5871 
5872   Level: beginner
5873 
5874   Note:
5875   The values obtained are valid until the `TS` object is destroyed.
5876 
5877   Both `n` and `span_times` can be `NULL`.
5878 
5879 .seealso: [](ch_ts), `TS`, `TSSetTimeSpan()`, `TSGetTimeSpanSolutions()`
5880  @*/
5881 PetscErrorCode TSGetTimeSpan(TS ts, PetscInt *n, const PetscReal *span_times[])
5882 {
5883   PetscFunctionBegin;
5884   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5885   if (n) PetscAssertPointer(n, 2);
5886   if (span_times) PetscAssertPointer(span_times, 3);
5887   if (!ts->tspan) {
5888     if (n) *n = 0;
5889     if (span_times) *span_times = NULL;
5890   } else {
5891     if (n) *n = ts->tspan->num_span_times;
5892     if (span_times) *span_times = ts->tspan->span_times;
5893   }
5894   PetscFunctionReturn(PETSC_SUCCESS);
5895 }
5896 
5897 /*@
5898   TSGetTimeSpanSolutions - Get the number of solutions and the solutions at the time points specified by the time span.
5899 
5900   Input Parameter:
5901 . ts - the `TS` context obtained from `TSCreate()`
5902 
5903   Output Parameters:
5904 + nsol - the number of solutions
5905 - Sols - the solution vectors
5906 
5907   Level: intermediate
5908 
5909   Notes:
5910   Both `nsol` and `Sols` can be `NULL`.
5911 
5912   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()`.
5913   For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain points in the span.
5914 
5915 .seealso: [](ch_ts), `TS`, `TSSetTimeSpan()`
5916 @*/
5917 PetscErrorCode TSGetTimeSpanSolutions(TS ts, PetscInt *nsol, Vec **Sols)
5918 {
5919   PetscFunctionBegin;
5920   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5921   if (nsol) PetscAssertPointer(nsol, 2);
5922   if (Sols) PetscAssertPointer(Sols, 3);
5923   if (!ts->tspan) {
5924     if (nsol) *nsol = 0;
5925     if (Sols) *Sols = NULL;
5926   } else {
5927     if (nsol) *nsol = ts->tspan->spanctr;
5928     if (Sols) *Sols = ts->tspan->vecs_sol;
5929   }
5930   PetscFunctionReturn(PETSC_SUCCESS);
5931 }
5932 
5933 /*@
5934   TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information.
5935 
5936   Collective
5937 
5938   Input Parameters:
5939 + ts - the `TS` context
5940 . J  - Jacobian matrix (not altered in this routine)
5941 - B  - newly computed Jacobian matrix to use with preconditioner
5942 
5943   Level: intermediate
5944 
5945   Notes:
5946   This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains
5947   many constant zeros entries, which is typically the case when the matrix is generated by a `DM`
5948   and multiple fields are involved.
5949 
5950   Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity
5951   structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can
5952   usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian.
5953   `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`.
5954 
5955 .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
5956 @*/
5957 PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B)
5958 {
5959   MatColoring   mc            = NULL;
5960   ISColoring    iscoloring    = NULL;
5961   MatFDColoring matfdcoloring = NULL;
5962 
5963   PetscFunctionBegin;
5964   /* Generate new coloring after eliminating zeros in the matrix */
5965   PetscCall(MatEliminateZeros(B, PETSC_TRUE));
5966   PetscCall(MatColoringCreate(B, &mc));
5967   PetscCall(MatColoringSetDistance(mc, 2));
5968   PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
5969   PetscCall(MatColoringSetFromOptions(mc));
5970   PetscCall(MatColoringApply(mc, &iscoloring));
5971   PetscCall(MatColoringDestroy(&mc));
5972   /* Replace the old coloring with the new one */
5973   PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring));
5974   PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
5975   PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
5976   PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring));
5977   PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring));
5978   PetscCall(PetscObjectDereference((PetscObject)matfdcoloring));
5979   PetscCall(ISColoringDestroy(&iscoloring));
5980   PetscFunctionReturn(PETSC_SUCCESS);
5981 }
5982