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