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