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