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