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