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