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