xref: /petsc/src/ts/interface/ts.c (revision 750b007cd8d816cecd9de99077bb0a703b4cf61a)
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(PetscObjectIncrementTabLevel((PetscObject)ts->snes, (PetscObject)ts, 1));
2704     if (ts->dm) PetscCall(SNESSetDM(ts->snes, ts->dm));
2705     if (ts->problem_type == TS_LINEAR) PetscCall(SNESSetType(ts->snes, SNESKSPONLY));
2706   }
2707   *snes = ts->snes;
2708   PetscFunctionReturn(0);
2709 }
2710 
2711 /*@
2712    TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
2713 
2714    Collective
2715 
2716    Input Parameters:
2717 +  ts - the TS context obtained from TSCreate()
2718 -  snes - the nonlinear solver context
2719 
2720    Notes:
2721    Most users should have the TS created by calling TSGetSNES()
2722 
2723    Level: developer
2724 
2725 @*/
2726 PetscErrorCode TSSetSNES(TS ts, SNES snes) {
2727   PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
2728 
2729   PetscFunctionBegin;
2730   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2731   PetscValidHeaderSpecific(snes, SNES_CLASSID, 2);
2732   PetscCall(PetscObjectReference((PetscObject)snes));
2733   PetscCall(SNESDestroy(&ts->snes));
2734 
2735   ts->snes = snes;
2736 
2737   PetscCall(SNESSetFunction(ts->snes, NULL, SNESTSFormFunction, ts));
2738   PetscCall(SNESGetJacobian(ts->snes, NULL, NULL, &func, NULL));
2739   if (func == SNESTSFormJacobian) PetscCall(SNESSetJacobian(ts->snes, NULL, NULL, SNESTSFormJacobian, ts));
2740   PetscFunctionReturn(0);
2741 }
2742 
2743 /*@
2744    TSGetKSP - Returns the KSP (linear solver) associated with
2745    a TS (timestepper) context.
2746 
2747    Not Collective, but KSP is parallel if TS is parallel
2748 
2749    Input Parameter:
2750 .  ts - the TS context obtained from TSCreate()
2751 
2752    Output Parameter:
2753 .  ksp - the nonlinear solver context
2754 
2755    Notes:
2756    The user can then directly manipulate the KSP context to set various
2757    options, etc.  Likewise, the user can then extract and manipulate the
2758    KSP and PC contexts as well.
2759 
2760    TSGetKSP() does not work for integrators that do not use KSP;
2761    in this case TSGetKSP() returns NULL in ksp.
2762 
2763    Level: beginner
2764 
2765 @*/
2766 PetscErrorCode TSGetKSP(TS ts, KSP *ksp) {
2767   SNES snes;
2768 
2769   PetscFunctionBegin;
2770   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2771   PetscValidPointer(ksp, 2);
2772   PetscCheck(((PetscObject)ts)->type_name, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "KSP is not created yet. Call TSSetType() first");
2773   PetscCheck(ts->problem_type == TS_LINEAR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Linear only; use TSGetSNES()");
2774   PetscCall(TSGetSNES(ts, &snes));
2775   PetscCall(SNESGetKSP(snes, ksp));
2776   PetscFunctionReturn(0);
2777 }
2778 
2779 /* ----------- Routines to set solver parameters ---------- */
2780 
2781 /*@
2782    TSSetMaxSteps - Sets the maximum number of steps to use.
2783 
2784    Logically Collective on TS
2785 
2786    Input Parameters:
2787 +  ts - the TS context obtained from TSCreate()
2788 -  maxsteps - maximum number of steps to use
2789 
2790    Options Database Keys:
2791 .  -ts_max_steps <maxsteps> - Sets maxsteps
2792 
2793    Notes:
2794    The default maximum number of steps is 5000
2795 
2796    Level: intermediate
2797 
2798 .seealso: `TSGetMaxSteps()`, `TSSetMaxTime()`, `TSSetExactFinalTime()`
2799 @*/
2800 PetscErrorCode TSSetMaxSteps(TS ts, PetscInt maxsteps) {
2801   PetscFunctionBegin;
2802   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2803   PetscValidLogicalCollectiveInt(ts, maxsteps, 2);
2804   PetscCheck(maxsteps >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Maximum number of steps must be non-negative");
2805   ts->max_steps = maxsteps;
2806   PetscFunctionReturn(0);
2807 }
2808 
2809 /*@
2810    TSGetMaxSteps - Gets the maximum number of steps to use.
2811 
2812    Not Collective
2813 
2814    Input Parameters:
2815 .  ts - the TS context obtained from TSCreate()
2816 
2817    Output Parameter:
2818 .  maxsteps - maximum number of steps to use
2819 
2820    Level: advanced
2821 
2822 .seealso: `TSSetMaxSteps()`, `TSGetMaxTime()`, `TSSetMaxTime()`
2823 @*/
2824 PetscErrorCode TSGetMaxSteps(TS ts, PetscInt *maxsteps) {
2825   PetscFunctionBegin;
2826   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2827   PetscValidIntPointer(maxsteps, 2);
2828   *maxsteps = ts->max_steps;
2829   PetscFunctionReturn(0);
2830 }
2831 
2832 /*@
2833    TSSetMaxTime - Sets the maximum (or final) time for timestepping.
2834 
2835    Logically Collective on TS
2836 
2837    Input Parameters:
2838 +  ts - the TS context obtained from TSCreate()
2839 -  maxtime - final time to step to
2840 
2841    Options Database Keys:
2842 .  -ts_max_time <maxtime> - Sets maxtime
2843 
2844    Notes:
2845    The default maximum time is 5.0
2846 
2847    Level: intermediate
2848 
2849 .seealso: `TSGetMaxTime()`, `TSSetMaxSteps()`, `TSSetExactFinalTime()`
2850 @*/
2851 PetscErrorCode TSSetMaxTime(TS ts, PetscReal maxtime) {
2852   PetscFunctionBegin;
2853   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2854   PetscValidLogicalCollectiveReal(ts, maxtime, 2);
2855   ts->max_time = maxtime;
2856   PetscFunctionReturn(0);
2857 }
2858 
2859 /*@
2860    TSGetMaxTime - Gets the maximum (or final) time for timestepping.
2861 
2862    Not Collective
2863 
2864    Input Parameters:
2865 .  ts - the TS context obtained from TSCreate()
2866 
2867    Output Parameter:
2868 .  maxtime - final time to step to
2869 
2870    Level: advanced
2871 
2872 .seealso: `TSSetMaxTime()`, `TSGetMaxSteps()`, `TSSetMaxSteps()`
2873 @*/
2874 PetscErrorCode TSGetMaxTime(TS ts, PetscReal *maxtime) {
2875   PetscFunctionBegin;
2876   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2877   PetscValidRealPointer(maxtime, 2);
2878   *maxtime = ts->max_time;
2879   PetscFunctionReturn(0);
2880 }
2881 
2882 /*@
2883    TSSetInitialTimeStep - Deprecated, use TSSetTime() and TSSetTimeStep().
2884 
2885    Level: deprecated
2886 
2887 @*/
2888 PetscErrorCode TSSetInitialTimeStep(TS ts, PetscReal initial_time, PetscReal time_step) {
2889   PetscFunctionBegin;
2890   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2891   PetscCall(TSSetTime(ts, initial_time));
2892   PetscCall(TSSetTimeStep(ts, time_step));
2893   PetscFunctionReturn(0);
2894 }
2895 
2896 /*@
2897    TSGetDuration - Deprecated, use TSGetMaxSteps() and TSGetMaxTime().
2898 
2899    Level: deprecated
2900 
2901 @*/
2902 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime) {
2903   PetscFunctionBegin;
2904   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2905   if (maxsteps) {
2906     PetscValidIntPointer(maxsteps, 2);
2907     *maxsteps = ts->max_steps;
2908   }
2909   if (maxtime) {
2910     PetscValidRealPointer(maxtime, 3);
2911     *maxtime = ts->max_time;
2912   }
2913   PetscFunctionReturn(0);
2914 }
2915 
2916 /*@
2917    TSSetDuration - Deprecated, use TSSetMaxSteps() and TSSetMaxTime().
2918 
2919    Level: deprecated
2920 
2921 @*/
2922 PetscErrorCode TSSetDuration(TS ts, PetscInt maxsteps, PetscReal maxtime) {
2923   PetscFunctionBegin;
2924   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2925   PetscValidLogicalCollectiveInt(ts, maxsteps, 2);
2926   PetscValidLogicalCollectiveReal(ts, maxtime, 3);
2927   if (maxsteps >= 0) ts->max_steps = maxsteps;
2928   if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
2929   PetscFunctionReturn(0);
2930 }
2931 
2932 /*@
2933    TSGetTimeStepNumber - Deprecated, use TSGetStepNumber().
2934 
2935    Level: deprecated
2936 
2937 @*/
2938 PetscErrorCode TSGetTimeStepNumber(TS ts, PetscInt *steps) {
2939   return TSGetStepNumber(ts, steps);
2940 }
2941 
2942 /*@
2943    TSGetTotalSteps - Deprecated, use TSGetStepNumber().
2944 
2945    Level: deprecated
2946 
2947 @*/
2948 PetscErrorCode TSGetTotalSteps(TS ts, PetscInt *steps) {
2949   return TSGetStepNumber(ts, steps);
2950 }
2951 
2952 /*@
2953    TSSetSolution - Sets the initial solution vector
2954    for use by the TS routines.
2955 
2956    Logically Collective on TS
2957 
2958    Input Parameters:
2959 +  ts - the TS context obtained from TSCreate()
2960 -  u - the solution vector
2961 
2962    Level: beginner
2963 
2964 .seealso: `TSSetSolutionFunction()`, `TSGetSolution()`, `TSCreate()`
2965 @*/
2966 PetscErrorCode TSSetSolution(TS ts, Vec u) {
2967   DM dm;
2968 
2969   PetscFunctionBegin;
2970   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
2971   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
2972   PetscCall(PetscObjectReference((PetscObject)u));
2973   PetscCall(VecDestroy(&ts->vec_sol));
2974   ts->vec_sol = u;
2975 
2976   PetscCall(TSGetDM(ts, &dm));
2977   PetscCall(DMShellSetGlobalVector(dm, u));
2978   PetscFunctionReturn(0);
2979 }
2980 
2981 /*@C
2982   TSSetPreStep - Sets the general-purpose function
2983   called once at the beginning of each time step.
2984 
2985   Logically Collective on TS
2986 
2987   Input Parameters:
2988 + ts   - The TS context obtained from TSCreate()
2989 - func - The function
2990 
2991   Calling sequence of func:
2992 .vb
2993   PetscErrorCode func (TS ts);
2994 .ve
2995 
2996   Level: intermediate
2997 
2998 .seealso: `TSSetPreStage()`, `TSSetPostStage()`, `TSSetPostStep()`, `TSStep()`, `TSRestartStep()`
2999 @*/
3000 PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS)) {
3001   PetscFunctionBegin;
3002   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3003   ts->prestep = func;
3004   PetscFunctionReturn(0);
3005 }
3006 
3007 /*@
3008   TSPreStep - Runs the user-defined pre-step function.
3009 
3010   Collective on TS
3011 
3012   Input Parameters:
3013 . ts   - The TS context obtained from TSCreate()
3014 
3015   Notes:
3016   TSPreStep() is typically used within time stepping implementations,
3017   so most users would not generally call this routine themselves.
3018 
3019   Level: developer
3020 
3021 .seealso: `TSSetPreStep()`, `TSPreStage()`, `TSPostStage()`, `TSPostStep()`
3022 @*/
3023 PetscErrorCode TSPreStep(TS ts) {
3024   PetscFunctionBegin;
3025   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3026   if (ts->prestep) {
3027     Vec              U;
3028     PetscObjectId    idprev;
3029     PetscBool        sameObject;
3030     PetscObjectState sprev, spost;
3031 
3032     PetscCall(TSGetSolution(ts, &U));
3033     PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3034     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3035     PetscCallBack("TS callback preset", (*ts->prestep)(ts));
3036     PetscCall(TSGetSolution(ts, &U));
3037     PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3038     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3039     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3040   }
3041   PetscFunctionReturn(0);
3042 }
3043 
3044 /*@C
3045   TSSetPreStage - Sets the general-purpose function
3046   called once at the beginning of each stage.
3047 
3048   Logically Collective on TS
3049 
3050   Input Parameters:
3051 + ts   - The TS context obtained from TSCreate()
3052 - func - The function
3053 
3054   Calling sequence of func:
3055 .vb
3056   PetscErrorCode func(TS ts, PetscReal stagetime);
3057 .ve
3058 
3059   Level: intermediate
3060 
3061   Note:
3062   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3063   The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being
3064   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3065 
3066 .seealso: `TSSetPostStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3067 @*/
3068 PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS, PetscReal)) {
3069   PetscFunctionBegin;
3070   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3071   ts->prestage = func;
3072   PetscFunctionReturn(0);
3073 }
3074 
3075 /*@C
3076   TSSetPostStage - Sets the general-purpose function
3077   called once at the end of each stage.
3078 
3079   Logically Collective on TS
3080 
3081   Input Parameters:
3082 + ts   - The TS context obtained from TSCreate()
3083 - func - The function
3084 
3085   Calling sequence of func:
3086 .vb
3087   PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y);
3088 .ve
3089 
3090   Level: intermediate
3091 
3092   Note:
3093   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3094   The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being
3095   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3096 
3097 .seealso: `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3098 @*/
3099 PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS, PetscReal, PetscInt, Vec *)) {
3100   PetscFunctionBegin;
3101   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3102   ts->poststage = func;
3103   PetscFunctionReturn(0);
3104 }
3105 
3106 /*@C
3107   TSSetPostEvaluate - Sets the general-purpose function
3108   called once at the end of each step evaluation.
3109 
3110   Logically Collective on TS
3111 
3112   Input Parameters:
3113 + ts   - The TS context obtained from TSCreate()
3114 - func - The function
3115 
3116   Calling sequence of func:
3117 .vb
3118   PetscErrorCode func(TS ts);
3119 .ve
3120 
3121   Level: intermediate
3122 
3123   Note:
3124   Semantically, TSSetPostEvaluate() differs from TSSetPostStep() since the function it sets is called before event-handling
3125   thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, TSPostStep()
3126   may be passed a different solution, possibly changed by the event handler. TSPostEvaluate() is called after the next step
3127   solution is evaluated allowing to modify it, if need be. The solution can be obtained with TSGetSolution(), the time step
3128   with TSGetTimeStep(), and the time at the start of the step is available via TSGetTime()
3129 
3130 .seealso: `TSSetPreStage()`, `TSSetPreStep()`, `TSSetPostStep()`, `TSGetApplicationContext()`
3131 @*/
3132 PetscErrorCode TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS)) {
3133   PetscFunctionBegin;
3134   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3135   ts->postevaluate = func;
3136   PetscFunctionReturn(0);
3137 }
3138 
3139 /*@
3140   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
3141 
3142   Collective on TS
3143 
3144   Input Parameters:
3145 . ts          - The TS context obtained from TSCreate()
3146   stagetime   - The absolute time of the current stage
3147 
3148   Notes:
3149   TSPreStage() is typically used within time stepping implementations,
3150   most users would not generally call this routine themselves.
3151 
3152   Level: developer
3153 
3154 .seealso: `TSPostStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3155 @*/
3156 PetscErrorCode TSPreStage(TS ts, PetscReal stagetime) {
3157   PetscFunctionBegin;
3158   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3159   if (ts->prestage) PetscCallBack("TS callback prestage", (*ts->prestage)(ts, stagetime));
3160   PetscFunctionReturn(0);
3161 }
3162 
3163 /*@
3164   TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage()
3165 
3166   Collective on TS
3167 
3168   Input Parameters:
3169 . ts          - The TS context obtained from TSCreate()
3170   stagetime   - The absolute time of the current stage
3171   stageindex  - Stage number
3172   Y           - Array of vectors (of size = total number
3173                 of stages) with the stage solutions
3174 
3175   Notes:
3176   TSPostStage() is typically used within time stepping implementations,
3177   most users would not generally call this routine themselves.
3178 
3179   Level: developer
3180 
3181 .seealso: `TSPreStage()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3182 @*/
3183 PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y) {
3184   PetscFunctionBegin;
3185   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3186   if (ts->poststage) PetscCallBack("TS callback poststage", (*ts->poststage)(ts, stagetime, stageindex, Y));
3187   PetscFunctionReturn(0);
3188 }
3189 
3190 /*@
3191   TSPostEvaluate - Runs the user-defined post-evaluate function set using TSSetPostEvaluate()
3192 
3193   Collective on TS
3194 
3195   Input Parameters:
3196 . ts          - The TS context obtained from TSCreate()
3197 
3198   Notes:
3199   TSPostEvaluate() is typically used within time stepping implementations,
3200   most users would not generally call this routine themselves.
3201 
3202   Level: developer
3203 
3204 .seealso: `TSSetPostEvaluate()`, `TSSetPreStep()`, `TSPreStep()`, `TSPostStep()`
3205 @*/
3206 PetscErrorCode TSPostEvaluate(TS ts) {
3207   PetscFunctionBegin;
3208   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3209   if (ts->postevaluate) {
3210     Vec              U;
3211     PetscObjectState sprev, spost;
3212 
3213     PetscCall(TSGetSolution(ts, &U));
3214     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3215     PetscCallBack("TS callback postevaluate", (*ts->postevaluate)(ts));
3216     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3217     if (sprev != spost) PetscCall(TSRestartStep(ts));
3218   }
3219   PetscFunctionReturn(0);
3220 }
3221 
3222 /*@C
3223   TSSetPostStep - Sets the general-purpose function
3224   called once at the end of each time step.
3225 
3226   Logically Collective on TS
3227 
3228   Input Parameters:
3229 + ts   - The TS context obtained from TSCreate()
3230 - func - The function
3231 
3232   Calling sequence of func:
3233 $ func (TS ts);
3234 
3235   Notes:
3236   The function set by TSSetPostStep() is called after each successful step. The solution vector X
3237   obtained by TSGetSolution() may be different than that computed at the step end if the event handler
3238   locates an event and TSPostEvent() modifies it. Use TSSetPostEvaluate() if an unmodified solution is needed instead.
3239 
3240   Level: intermediate
3241 
3242 .seealso: `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostEvaluate()`, `TSGetTimeStep()`, `TSGetStepNumber()`, `TSGetTime()`, `TSRestartStep()`
3243 @*/
3244 PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS)) {
3245   PetscFunctionBegin;
3246   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3247   ts->poststep = func;
3248   PetscFunctionReturn(0);
3249 }
3250 
3251 /*@
3252   TSPostStep - Runs the user-defined post-step function.
3253 
3254   Collective on TS
3255 
3256   Input Parameters:
3257 . ts   - The TS context obtained from TSCreate()
3258 
3259   Notes:
3260   TSPostStep() is typically used within time stepping implementations,
3261   so most users would not generally call this routine themselves.
3262 
3263   Level: developer
3264 
3265 @*/
3266 PetscErrorCode TSPostStep(TS ts) {
3267   PetscFunctionBegin;
3268   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3269   if (ts->poststep) {
3270     Vec              U;
3271     PetscObjectId    idprev;
3272     PetscBool        sameObject;
3273     PetscObjectState sprev, spost;
3274 
3275     PetscCall(TSGetSolution(ts, &U));
3276     PetscCall(PetscObjectGetId((PetscObject)U, &idprev));
3277     PetscCall(PetscObjectStateGet((PetscObject)U, &sprev));
3278     PetscCallBack("TS callback poststep", (*ts->poststep)(ts));
3279     PetscCall(TSGetSolution(ts, &U));
3280     PetscCall(PetscObjectCompareId((PetscObject)U, idprev, &sameObject));
3281     PetscCall(PetscObjectStateGet((PetscObject)U, &spost));
3282     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3283   }
3284   PetscFunctionReturn(0);
3285 }
3286 
3287 /*@
3288    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
3289 
3290    Collective on TS
3291 
3292    Input Parameters:
3293 +  ts - time stepping context
3294 -  t - time to interpolate to
3295 
3296    Output Parameter:
3297 .  U - state at given time
3298 
3299    Level: intermediate
3300 
3301    Developer Notes:
3302    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
3303 
3304 .seealso: `TSSetExactFinalTime()`, `TSSolve()`
3305 @*/
3306 PetscErrorCode TSInterpolate(TS ts, PetscReal t, Vec U) {
3307   PetscFunctionBegin;
3308   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3309   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
3310   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);
3311   PetscUseTypeMethod(ts, interpolate, t, U);
3312   PetscFunctionReturn(0);
3313 }
3314 
3315 /*@
3316    TSStep - Steps one time step
3317 
3318    Collective on TS
3319 
3320    Input Parameter:
3321 .  ts - the TS context obtained from TSCreate()
3322 
3323    Level: developer
3324 
3325    Notes:
3326    The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine.
3327 
3328    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
3329    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3330 
3331    This may over-step the final time provided in TSSetMaxTime() depending on the time-step used. TSSolve() interpolates to exactly the
3332    time provided in TSSetMaxTime(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
3333 
3334 .seealso: `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSSetPostStage()`, `TSInterpolate()`
3335 @*/
3336 PetscErrorCode TSStep(TS ts) {
3337   static PetscBool cite = PETSC_FALSE;
3338   PetscReal        ptime;
3339 
3340   PetscFunctionBegin;
3341   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3342   PetscCall(PetscCitationsRegister("@article{tspaper,\n"
3343                                    "  title         = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3344                                    "  author        = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n"
3345                                    "  journal       = {arXiv e-preprints},\n"
3346                                    "  eprint        = {1806.01437},\n"
3347                                    "  archivePrefix = {arXiv},\n"
3348                                    "  year          = {2018}\n}\n",
3349                                    &cite));
3350   PetscCall(TSSetUp(ts));
3351   PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
3352 
3353   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>");
3354   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()");
3355   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");
3356 
3357   if (!ts->steps) ts->ptime_prev = ts->ptime;
3358   ptime                   = ts->ptime;
3359   ts->ptime_prev_rollback = ts->ptime_prev;
3360   ts->reason              = TS_CONVERGED_ITERATING;
3361 
3362   PetscCall(PetscLogEventBegin(TS_Step, ts, 0, 0, 0));
3363   PetscUseTypeMethod(ts, step);
3364   PetscCall(PetscLogEventEnd(TS_Step, ts, 0, 0, 0));
3365 
3366   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)
3367     PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[ts->tspan->spanctr++]));
3368   if (ts->reason >= 0) {
3369     ts->ptime_prev = ptime;
3370     ts->steps++;
3371     ts->steprollback = PETSC_FALSE;
3372     ts->steprestart  = PETSC_FALSE;
3373   }
3374   if (!ts->reason) {
3375     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
3376     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3377   }
3378 
3379   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]);
3380   PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed, PetscObjectComm((PetscObject)ts), PETSC_ERR_NOT_CONVERGED, "TSStep has failed due to %s", TSConvergedReasons[ts->reason]);
3381   PetscFunctionReturn(0);
3382 }
3383 
3384 /*@
3385    TSEvaluateWLTE - Evaluate the weighted local truncation error norm
3386    at the end of a time step with a given order of accuracy.
3387 
3388    Collective on TS
3389 
3390    Input Parameters:
3391 +  ts - time stepping context
3392 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
3393 
3394    Input/Output Parameter:
3395 .  order - optional, desired order for the error evaluation or PETSC_DECIDE;
3396            on output, the actual order of the error evaluation
3397 
3398    Output Parameter:
3399 .  wlte - the weighted local truncation error norm
3400 
3401    Level: advanced
3402 
3403    Notes:
3404    If the timestepper cannot evaluate the error in a particular step
3405    (eg. in the first step or restart steps after event handling),
3406    this routine returns wlte=-1.0 .
3407 
3408 .seealso: `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()`
3409 @*/
3410 PetscErrorCode TSEvaluateWLTE(TS ts, NormType wnormtype, PetscInt *order, PetscReal *wlte) {
3411   PetscFunctionBegin;
3412   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3413   PetscValidType(ts, 1);
3414   PetscValidLogicalCollectiveEnum(ts, wnormtype, 2);
3415   if (order) PetscValidIntPointer(order, 3);
3416   if (order) PetscValidLogicalCollectiveInt(ts, *order, 3);
3417   PetscValidRealPointer(wlte, 4);
3418   PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]);
3419   PetscUseTypeMethod(ts, evaluatewlte, wnormtype, order, wlte);
3420   PetscFunctionReturn(0);
3421 }
3422 
3423 /*@
3424    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
3425 
3426    Collective on TS
3427 
3428    Input Parameters:
3429 +  ts - time stepping context
3430 .  order - desired order of accuracy
3431 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
3432 
3433    Output Parameter:
3434 .  U - state at the end of the current step
3435 
3436    Level: advanced
3437 
3438    Notes:
3439    This function cannot be called until all stages have been evaluated.
3440    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.
3441 
3442 .seealso: `TSStep()`, `TSAdapt`
3443 @*/
3444 PetscErrorCode TSEvaluateStep(TS ts, PetscInt order, Vec U, PetscBool *done) {
3445   PetscFunctionBegin;
3446   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3447   PetscValidType(ts, 1);
3448   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
3449   PetscUseTypeMethod(ts, evaluatestep, order, U, done);
3450   PetscFunctionReturn(0);
3451 }
3452 
3453 /*@C
3454   TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping.
3455 
3456   Not collective
3457 
3458   Input Parameter:
3459 . ts        - time stepping context
3460 
3461   Output Parameter:
3462 . initConditions - The function which computes an initial condition
3463 
3464    Level: advanced
3465 
3466    Notes:
3467    The calling sequence for the function is
3468 $ initCondition(TS ts, Vec u)
3469 $ ts - The timestepping context
3470 $ u  - The input vector in which the initial condition is stored
3471 
3472 .seealso: `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()`
3473 @*/
3474 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS, Vec)) {
3475   PetscFunctionBegin;
3476   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3477   PetscValidPointer(initCondition, 2);
3478   *initCondition = ts->ops->initcondition;
3479   PetscFunctionReturn(0);
3480 }
3481 
3482 /*@C
3483   TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping.
3484 
3485   Logically collective on ts
3486 
3487   Input Parameters:
3488 + ts        - time stepping context
3489 - initCondition - The function which computes an initial condition
3490 
3491   Level: advanced
3492 
3493   Calling sequence for initCondition:
3494 $ PetscErrorCode initCondition(TS ts, Vec u)
3495 
3496 + ts - The timestepping context
3497 - u  - The input vector in which the initial condition is to be stored
3498 
3499 .seealso: `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()`
3500 @*/
3501 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS, Vec)) {
3502   PetscFunctionBegin;
3503   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3504   PetscValidFunction(initCondition, 2);
3505   ts->ops->initcondition = initCondition;
3506   PetscFunctionReturn(0);
3507 }
3508 
3509 /*@
3510   TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set.
3511 
3512   Collective on ts
3513 
3514   Input Parameters:
3515 + ts - time stepping context
3516 - u  - The Vec to store the condition in which will be used in TSSolve()
3517 
3518   Level: advanced
3519 
3520 .seealso: `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3521 @*/
3522 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u) {
3523   PetscFunctionBegin;
3524   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3525   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
3526   PetscTryTypeMethod(ts, initcondition, u);
3527   PetscFunctionReturn(0);
3528 }
3529 
3530 /*@C
3531   TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping.
3532 
3533   Not collective
3534 
3535   Input Parameter:
3536 . ts         - time stepping context
3537 
3538   Output Parameter:
3539 . exactError - The function which computes the solution error
3540 
3541   Level: advanced
3542 
3543   Calling sequence for exactError:
3544 $ PetscErrorCode exactError(TS ts, Vec u)
3545 
3546 + ts - The timestepping context
3547 . u  - The approximate solution vector
3548 - e  - The input vector in which the error is stored
3549 
3550 .seealso: `TSGetComputeExactError()`, `TSComputeExactError()`
3551 @*/
3552 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS, Vec, Vec)) {
3553   PetscFunctionBegin;
3554   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3555   PetscValidPointer(exactError, 2);
3556   *exactError = ts->ops->exacterror;
3557   PetscFunctionReturn(0);
3558 }
3559 
3560 /*@C
3561   TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping.
3562 
3563   Logically collective on ts
3564 
3565   Input Parameters:
3566 + ts         - time stepping context
3567 - exactError - The function which computes the solution error
3568 
3569   Level: advanced
3570 
3571   Calling sequence for exactError:
3572 $ PetscErrorCode exactError(TS ts, Vec u)
3573 
3574 + ts - The timestepping context
3575 . u  - The approximate solution vector
3576 - e  - The input vector in which the error is stored
3577 
3578 .seealso: `TSGetComputeExactError()`, `TSComputeExactError()`
3579 @*/
3580 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS, Vec, Vec)) {
3581   PetscFunctionBegin;
3582   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3583   PetscValidFunction(exactError, 2);
3584   ts->ops->exacterror = exactError;
3585   PetscFunctionReturn(0);
3586 }
3587 
3588 /*@
3589   TSComputeExactError - Compute the solution error for the timestepping using the function previously set.
3590 
3591   Collective on ts
3592 
3593   Input Parameters:
3594 + ts - time stepping context
3595 . u  - The approximate solution
3596 - e  - The Vec used to store the error
3597 
3598   Level: advanced
3599 
3600 .seealso: `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3601 @*/
3602 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e) {
3603   PetscFunctionBegin;
3604   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3605   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
3606   PetscValidHeaderSpecific(e, VEC_CLASSID, 3);
3607   PetscTryTypeMethod(ts, exacterror, u, e);
3608   PetscFunctionReturn(0);
3609 }
3610 
3611 /*@
3612    TSSolve - Steps the requested number of timesteps.
3613 
3614    Collective on TS
3615 
3616    Input Parameters:
3617 +  ts - the TS context obtained from TSCreate()
3618 -  u - the solution vector  (can be null if TSSetSolution() was used and TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP) was not used,
3619                              otherwise must contain the initial conditions and will contain the solution at the final requested time
3620 
3621    Level: beginner
3622 
3623    Notes:
3624    The final time returned by this function may be different from the time of the internally
3625    held state accessible by TSGetSolution() and TSGetTime() because the method may have
3626    stepped over the final time.
3627 
3628 .seealso: `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()`
3629 @*/
3630 PetscErrorCode TSSolve(TS ts, Vec u) {
3631   Vec solution;
3632 
3633   PetscFunctionBegin;
3634   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3635   if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
3636 
3637   PetscCall(TSSetExactFinalTimeDefault(ts));
3638   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 */
3639     if (!ts->vec_sol || u == ts->vec_sol) {
3640       PetscCall(VecDuplicate(u, &solution));
3641       PetscCall(TSSetSolution(ts, solution));
3642       PetscCall(VecDestroy(&solution)); /* grant ownership */
3643     }
3644     PetscCall(VecCopy(u, ts->vec_sol));
3645     PetscCheck(!ts->forward_solve, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
3646   } else if (u) PetscCall(TSSetSolution(ts, u));
3647   PetscCall(TSSetUp(ts));
3648   PetscCall(TSTrajectorySetUp(ts->trajectory, ts));
3649 
3650   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>");
3651   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()");
3652   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");
3653   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");
3654 
3655   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 */
3656     PetscCall(VecCopy(ts->vec_sol, ts->tspan->vecs_sol[0]));
3657     ts->tspan->spanctr = 1;
3658   }
3659 
3660   if (ts->forward_solve) PetscCall(TSForwardSetUp(ts));
3661 
3662   /* reset number of steps only when the step is not restarted. ARKIMEX
3663      restarts the step after an event. Resetting these counters in such case causes
3664      TSTrajectory to incorrectly save the output files
3665   */
3666   /* reset time step and iteration counters */
3667   if (!ts->steps) {
3668     ts->ksp_its           = 0;
3669     ts->snes_its          = 0;
3670     ts->num_snes_failures = 0;
3671     ts->reject            = 0;
3672     ts->steprestart       = PETSC_TRUE;
3673     ts->steprollback      = PETSC_FALSE;
3674     ts->rhsjacobian.time  = PETSC_MIN_REAL;
3675   }
3676 
3677   /* make sure initial time step does not overshoot final time or the next point in tspan */
3678   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
3679     PetscReal maxdt;
3680     PetscReal dt = ts->time_step;
3681 
3682     if (ts->tspan) maxdt = ts->tspan->span_times[ts->tspan->spanctr] - ts->ptime;
3683     else maxdt = ts->max_time - ts->ptime;
3684     ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt, maxdt, 10 * PETSC_MACHINE_EPSILON, 0) ? maxdt : dt);
3685   }
3686   ts->reason = TS_CONVERGED_ITERATING;
3687 
3688   {
3689     PetscViewer       viewer;
3690     PetscViewerFormat format;
3691     PetscBool         flg;
3692     static PetscBool  incall = PETSC_FALSE;
3693 
3694     if (!incall) {
3695       /* Estimate the convergence rate of the time discretization */
3696       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg));
3697       if (flg) {
3698         PetscConvEst conv;
3699         DM           dm;
3700         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
3701         PetscInt     Nf;
3702         PetscBool    checkTemporal = PETSC_TRUE;
3703 
3704         incall = PETSC_TRUE;
3705         PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg));
3706         PetscCall(TSGetDM(ts, &dm));
3707         PetscCall(DMGetNumFields(dm, &Nf));
3708         PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha));
3709         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject)ts), &conv));
3710         PetscCall(PetscConvEstUseTS(conv, checkTemporal));
3711         PetscCall(PetscConvEstSetSolver(conv, (PetscObject)ts));
3712         PetscCall(PetscConvEstSetFromOptions(conv));
3713         PetscCall(PetscConvEstSetUp(conv));
3714         PetscCall(PetscConvEstGetConvRate(conv, alpha));
3715         PetscCall(PetscViewerPushFormat(viewer, format));
3716         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
3717         PetscCall(PetscViewerPopFormat(viewer));
3718         PetscCall(PetscViewerDestroy(&viewer));
3719         PetscCall(PetscConvEstDestroy(&conv));
3720         PetscCall(PetscFree(alpha));
3721         incall = PETSC_FALSE;
3722       }
3723     }
3724   }
3725 
3726   PetscCall(TSViewFromOptions(ts, NULL, "-ts_view_pre"));
3727 
3728   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
3729     PetscUseTypeMethod(ts, solve);
3730     if (u) PetscCall(VecCopy(ts->vec_sol, u));
3731     ts->solvetime = ts->ptime;
3732     solution      = ts->vec_sol;
3733   } else { /* Step the requested number of timesteps. */
3734     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
3735     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3736 
3737     if (!ts->steps) {
3738       PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
3739       PetscCall(TSEventInitialize(ts->event, ts, ts->ptime, ts->vec_sol));
3740     }
3741 
3742     while (!ts->reason) {
3743       PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
3744       if (!ts->steprollback) PetscCall(TSPreStep(ts));
3745       PetscCall(TSStep(ts));
3746       if (ts->testjacobian) PetscCall(TSRHSJacobianTest(ts, NULL));
3747       if (ts->testjacobiantranspose) PetscCall(TSRHSJacobianTestTranspose(ts, NULL));
3748       if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
3749         if (ts->reason >= 0) ts->steps--;            /* Revert the step number changed by TSStep() */
3750         PetscCall(TSForwardCostIntegral(ts));
3751         if (ts->reason >= 0) ts->steps++;
3752       }
3753       if (ts->forward_solve) {            /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
3754         if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
3755         PetscCall(TSForwardStep(ts));
3756         if (ts->reason >= 0) ts->steps++;
3757       }
3758       PetscCall(TSPostEvaluate(ts));
3759       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. */
3760       if (ts->steprollback) PetscCall(TSPostEvaluate(ts));
3761       if (!ts->steprollback) {
3762         PetscCall(TSTrajectorySet(ts->trajectory, ts, ts->steps, ts->ptime, ts->vec_sol));
3763         PetscCall(TSPostStep(ts));
3764       }
3765     }
3766     PetscCall(TSMonitor(ts, ts->steps, ts->ptime, ts->vec_sol));
3767 
3768     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
3769       PetscCall(TSInterpolate(ts, ts->max_time, u));
3770       ts->solvetime = ts->max_time;
3771       solution      = u;
3772       PetscCall(TSMonitor(ts, -1, ts->solvetime, solution));
3773     } else {
3774       if (u) PetscCall(VecCopy(ts->vec_sol, u));
3775       ts->solvetime = ts->ptime;
3776       solution      = ts->vec_sol;
3777     }
3778   }
3779 
3780   PetscCall(TSViewFromOptions(ts, NULL, "-ts_view"));
3781   PetscCall(VecViewFromOptions(solution, (PetscObject)ts, "-ts_view_solution"));
3782   PetscCall(PetscObjectSAWsBlock((PetscObject)ts));
3783   if (ts->adjoint_solve) PetscCall(TSAdjointSolve(ts));
3784   PetscFunctionReturn(0);
3785 }
3786 
3787 /*@
3788    TSGetTime - Gets the time of the most recently completed step.
3789 
3790    Not Collective
3791 
3792    Input Parameter:
3793 .  ts - the TS context obtained from TSCreate()
3794 
3795    Output Parameter:
3796 .  t  - the current time. This time may not corresponds to the final time set with TSSetMaxTime(), use TSGetSolveTime().
3797 
3798    Level: beginner
3799 
3800    Note:
3801    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
3802    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
3803 
3804 .seealso: `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()`
3805 
3806 @*/
3807 PetscErrorCode TSGetTime(TS ts, PetscReal *t) {
3808   PetscFunctionBegin;
3809   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3810   PetscValidRealPointer(t, 2);
3811   *t = ts->ptime;
3812   PetscFunctionReturn(0);
3813 }
3814 
3815 /*@
3816    TSGetPrevTime - Gets the starting time of the previously completed step.
3817 
3818    Not Collective
3819 
3820    Input Parameter:
3821 .  ts - the TS context obtained from TSCreate()
3822 
3823    Output Parameter:
3824 .  t  - the previous time
3825 
3826    Level: beginner
3827 
3828 .seealso: `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()`
3829 
3830 @*/
3831 PetscErrorCode TSGetPrevTime(TS ts, PetscReal *t) {
3832   PetscFunctionBegin;
3833   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3834   PetscValidRealPointer(t, 2);
3835   *t = ts->ptime_prev;
3836   PetscFunctionReturn(0);
3837 }
3838 
3839 /*@
3840    TSSetTime - Allows one to reset the time.
3841 
3842    Logically Collective on TS
3843 
3844    Input Parameters:
3845 +  ts - the TS context obtained from TSCreate()
3846 -  time - the time
3847 
3848    Level: intermediate
3849 
3850 .seealso: `TSGetTime()`, `TSSetMaxSteps()`
3851 
3852 @*/
3853 PetscErrorCode TSSetTime(TS ts, PetscReal t) {
3854   PetscFunctionBegin;
3855   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3856   PetscValidLogicalCollectiveReal(ts, t, 2);
3857   ts->ptime = t;
3858   PetscFunctionReturn(0);
3859 }
3860 
3861 /*@C
3862    TSSetOptionsPrefix - Sets the prefix used for searching for all
3863    TS options in the database.
3864 
3865    Logically Collective on TS
3866 
3867    Input Parameters:
3868 +  ts     - The TS context
3869 -  prefix - The prefix to prepend to all option names
3870 
3871    Notes:
3872    A hyphen (-) must NOT be given at the beginning of the prefix name.
3873    The first character of all runtime options is AUTOMATICALLY the
3874    hyphen.
3875 
3876    Level: advanced
3877 
3878 .seealso: `TSSetFromOptions()`
3879 
3880 @*/
3881 PetscErrorCode TSSetOptionsPrefix(TS ts, const char prefix[]) {
3882   SNES snes;
3883 
3884   PetscFunctionBegin;
3885   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3886   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts, prefix));
3887   PetscCall(TSGetSNES(ts, &snes));
3888   PetscCall(SNESSetOptionsPrefix(snes, prefix));
3889   PetscFunctionReturn(0);
3890 }
3891 
3892 /*@C
3893    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
3894    TS options in the database.
3895 
3896    Logically Collective on TS
3897 
3898    Input Parameters:
3899 +  ts     - The TS context
3900 -  prefix - The prefix to prepend to all option names
3901 
3902    Notes:
3903    A hyphen (-) must NOT be given at the beginning of the prefix name.
3904    The first character of all runtime options is AUTOMATICALLY the
3905    hyphen.
3906 
3907    Level: advanced
3908 
3909 .seealso: `TSGetOptionsPrefix()`
3910 
3911 @*/
3912 PetscErrorCode TSAppendOptionsPrefix(TS ts, const char prefix[]) {
3913   SNES snes;
3914 
3915   PetscFunctionBegin;
3916   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3917   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts, prefix));
3918   PetscCall(TSGetSNES(ts, &snes));
3919   PetscCall(SNESAppendOptionsPrefix(snes, prefix));
3920   PetscFunctionReturn(0);
3921 }
3922 
3923 /*@C
3924    TSGetOptionsPrefix - Sets the prefix used for searching for all
3925    TS options in the database.
3926 
3927    Not Collective
3928 
3929    Input Parameter:
3930 .  ts - The TS context
3931 
3932    Output Parameter:
3933 .  prefix - A pointer to the prefix string used
3934 
3935    Notes:
3936     On the fortran side, the user should pass in a string 'prifix' of
3937    sufficient length to hold the prefix.
3938 
3939    Level: intermediate
3940 
3941 .seealso: `TSAppendOptionsPrefix()`
3942 @*/
3943 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[]) {
3944   PetscFunctionBegin;
3945   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3946   PetscValidPointer(prefix, 2);
3947   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix));
3948   PetscFunctionReturn(0);
3949 }
3950 
3951 /*@C
3952    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
3953 
3954    Not Collective, but parallel objects are returned if TS is parallel
3955 
3956    Input Parameter:
3957 .  ts  - The TS context obtained from TSCreate()
3958 
3959    Output Parameters:
3960 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
3961 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
3962 .  func - Function to compute the Jacobian of the RHS  (or NULL)
3963 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
3964 
3965    Notes:
3966     You can pass in NULL for any return argument you do not need.
3967 
3968    Level: intermediate
3969 
3970 .seealso: `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
3971 
3972 @*/
3973 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobian *func, void **ctx) {
3974   DM dm;
3975 
3976   PetscFunctionBegin;
3977   if (Amat || Pmat) {
3978     SNES snes;
3979     PetscCall(TSGetSNES(ts, &snes));
3980     PetscCall(SNESSetUpMatrices(snes));
3981     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
3982   }
3983   PetscCall(TSGetDM(ts, &dm));
3984   PetscCall(DMTSGetRHSJacobian(dm, func, ctx));
3985   PetscFunctionReturn(0);
3986 }
3987 
3988 /*@C
3989    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
3990 
3991    Not Collective, but parallel objects are returned if TS is parallel
3992 
3993    Input Parameter:
3994 .  ts  - The TS context obtained from TSCreate()
3995 
3996    Output Parameters:
3997 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
3998 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
3999 .  f   - The function to compute the matrices
4000 - ctx - User-defined context for Jacobian evaluation routine
4001 
4002    Notes:
4003     You can pass in NULL for any return argument you do not need.
4004 
4005    Level: advanced
4006 
4007 .seealso: `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4008 
4009 @*/
4010 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobian *f, void **ctx) {
4011   DM dm;
4012 
4013   PetscFunctionBegin;
4014   if (Amat || Pmat) {
4015     SNES snes;
4016     PetscCall(TSGetSNES(ts, &snes));
4017     PetscCall(SNESSetUpMatrices(snes));
4018     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4019   }
4020   PetscCall(TSGetDM(ts, &dm));
4021   PetscCall(DMTSGetIJacobian(dm, f, ctx));
4022   PetscFunctionReturn(0);
4023 }
4024 
4025 #include <petsc/private/dmimpl.h>
4026 /*@
4027    TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS
4028 
4029    Logically Collective on ts
4030 
4031    Input Parameters:
4032 +  ts - the ODE integrator object
4033 -  dm - the dm, cannot be NULL
4034 
4035    Notes:
4036    A DM can only be used for solving one problem at a time because information about the problem is stored on the DM,
4037    even when not using interfaces like DMTSSetIFunction().  Use DMClone() to get a distinct DM when solving
4038    different problems using the same function space.
4039 
4040    Level: intermediate
4041 
4042 .seealso: `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()`
4043 @*/
4044 PetscErrorCode TSSetDM(TS ts, DM dm) {
4045   SNES snes;
4046   DMTS tsdm;
4047 
4048   PetscFunctionBegin;
4049   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4050   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
4051   PetscCall(PetscObjectReference((PetscObject)dm));
4052   if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */
4053     if (ts->dm->dmts && !dm->dmts) {
4054       PetscCall(DMCopyDMTS(ts->dm, dm));
4055       PetscCall(DMGetDMTS(ts->dm, &tsdm));
4056       /* Grant write privileges to the replacement DM */
4057       if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm;
4058     }
4059     PetscCall(DMDestroy(&ts->dm));
4060   }
4061   ts->dm = dm;
4062 
4063   PetscCall(TSGetSNES(ts, &snes));
4064   PetscCall(SNESSetDM(snes, dm));
4065   PetscFunctionReturn(0);
4066 }
4067 
4068 /*@
4069    TSGetDM - Gets the DM that may be used by some preconditioners
4070 
4071    Not Collective
4072 
4073    Input Parameter:
4074 . ts - the preconditioner context
4075 
4076    Output Parameter:
4077 .  dm - the dm
4078 
4079    Level: intermediate
4080 
4081 .seealso: `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()`
4082 @*/
4083 PetscErrorCode TSGetDM(TS ts, DM *dm) {
4084   PetscFunctionBegin;
4085   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4086   if (!ts->dm) {
4087     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm));
4088     if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm));
4089   }
4090   *dm = ts->dm;
4091   PetscFunctionReturn(0);
4092 }
4093 
4094 /*@
4095    SNESTSFormFunction - Function to evaluate nonlinear residual
4096 
4097    Logically Collective on SNES
4098 
4099    Input Parameters:
4100 + snes - nonlinear solver
4101 . U - the current state at which to evaluate the residual
4102 - ctx - user context, must be a TS
4103 
4104    Output Parameter:
4105 . F - the nonlinear residual
4106 
4107    Notes:
4108    This function is not normally called by users and is automatically registered with the SNES used by TS.
4109    It is most frequently passed to MatFDColoringSetFunction().
4110 
4111    Level: advanced
4112 
4113 .seealso: `SNESSetFunction()`, `MatFDColoringSetFunction()`
4114 @*/
4115 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx) {
4116   TS ts = (TS)ctx;
4117 
4118   PetscFunctionBegin;
4119   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4120   PetscValidHeaderSpecific(U, VEC_CLASSID, 2);
4121   PetscValidHeaderSpecific(F, VEC_CLASSID, 3);
4122   PetscValidHeaderSpecific(ts, TS_CLASSID, 4);
4123   PetscCall((ts->ops->snesfunction)(snes, U, F, ts));
4124   PetscFunctionReturn(0);
4125 }
4126 
4127 /*@
4128    SNESTSFormJacobian - Function to evaluate the Jacobian
4129 
4130    Collective on SNES
4131 
4132    Input Parameters:
4133 + snes - nonlinear solver
4134 . U - the current state at which to evaluate the residual
4135 - ctx - user context, must be a TS
4136 
4137    Output Parameters:
4138 + A - the Jacobian
4139 - B - the preconditioning matrix (may be the same as A)
4140 
4141    Notes:
4142    This function is not normally called by users and is automatically registered with the SNES used by TS.
4143 
4144    Level: developer
4145 
4146 .seealso: `SNESSetJacobian()`
4147 @*/
4148 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx) {
4149   TS ts = (TS)ctx;
4150 
4151   PetscFunctionBegin;
4152   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4153   PetscValidHeaderSpecific(U, VEC_CLASSID, 2);
4154   PetscValidPointer(A, 3);
4155   PetscValidHeaderSpecific(A, MAT_CLASSID, 3);
4156   PetscValidPointer(B, 4);
4157   PetscValidHeaderSpecific(B, MAT_CLASSID, 4);
4158   PetscValidHeaderSpecific(ts, TS_CLASSID, 5);
4159   PetscCall((ts->ops->snesjacobian)(snes, U, A, B, ts));
4160   PetscFunctionReturn(0);
4161 }
4162 
4163 /*@C
4164    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only
4165 
4166    Collective on TS
4167 
4168    Input Parameters:
4169 +  ts - time stepping context
4170 .  t - time at which to evaluate
4171 .  U - state at which to evaluate
4172 -  ctx - context
4173 
4174    Output Parameter:
4175 .  F - right hand side
4176 
4177    Level: intermediate
4178 
4179    Notes:
4180    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
4181    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
4182 
4183 .seealso: `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
4184 @*/
4185 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx) {
4186   Mat Arhs, Brhs;
4187 
4188   PetscFunctionBegin;
4189   PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
4190   /* undo the damage caused by shifting */
4191   PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs));
4192   PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
4193   PetscCall(MatMult(Arhs, U, F));
4194   PetscFunctionReturn(0);
4195 }
4196 
4197 /*@C
4198    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
4199 
4200    Collective on TS
4201 
4202    Input Parameters:
4203 +  ts - time stepping context
4204 .  t - time at which to evaluate
4205 .  U - state at which to evaluate
4206 -  ctx - context
4207 
4208    Output Parameters:
4209 +  A - pointer to operator
4210 -  B - pointer to preconditioning matrix
4211 
4212    Level: intermediate
4213 
4214    Notes:
4215    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
4216 
4217 .seealso: `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()`
4218 @*/
4219 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx) {
4220   PetscFunctionBegin;
4221   PetscFunctionReturn(0);
4222 }
4223 
4224 /*@C
4225    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
4226 
4227    Collective on TS
4228 
4229    Input Parameters:
4230 +  ts - time stepping context
4231 .  t - time at which to evaluate
4232 .  U - state at which to evaluate
4233 .  Udot - time derivative of state vector
4234 -  ctx - context
4235 
4236    Output Parameter:
4237 .  F - left hand side
4238 
4239    Level: intermediate
4240 
4241    Notes:
4242    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
4243    user is required to write their own TSComputeIFunction.
4244    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
4245    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
4246 
4247    Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U
4248 
4249 .seealso: `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()`
4250 @*/
4251 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx) {
4252   Mat A, B;
4253 
4254   PetscFunctionBegin;
4255   PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL));
4256   PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE));
4257   PetscCall(MatMult(A, Udot, F));
4258   PetscFunctionReturn(0);
4259 }
4260 
4261 /*@C
4262    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
4263 
4264    Collective on TS
4265 
4266    Input Parameters:
4267 +  ts - time stepping context
4268 .  t - time at which to evaluate
4269 .  U - state at which to evaluate
4270 .  Udot - time derivative of state vector
4271 .  shift - shift to apply
4272 -  ctx - context
4273 
4274    Output Parameters:
4275 +  A - pointer to operator
4276 -  B - pointer to preconditioning matrix
4277 
4278    Level: advanced
4279 
4280    Notes:
4281    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
4282 
4283    It is only appropriate for problems of the form
4284 
4285 $     M Udot = F(U,t)
4286 
4287   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
4288   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
4289   an implicit operator of the form
4290 
4291 $    shift*M + J
4292 
4293   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
4294   a copy of M or reassemble it when requested.
4295 
4296 .seealso: `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()`
4297 @*/
4298 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx) {
4299   PetscFunctionBegin;
4300   PetscCall(MatScale(A, shift / ts->ijacobian.shift));
4301   ts->ijacobian.shift = shift;
4302   PetscFunctionReturn(0);
4303 }
4304 
4305 /*@
4306    TSGetEquationType - Gets the type of the equation that TS is solving.
4307 
4308    Not Collective
4309 
4310    Input Parameter:
4311 .  ts - the TS context
4312 
4313    Output Parameter:
4314 .  equation_type - see TSEquationType
4315 
4316    Level: beginner
4317 
4318 .seealso: `TSSetEquationType()`, `TSEquationType`
4319 @*/
4320 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type) {
4321   PetscFunctionBegin;
4322   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4323   PetscValidPointer(equation_type, 2);
4324   *equation_type = ts->equation_type;
4325   PetscFunctionReturn(0);
4326 }
4327 
4328 /*@
4329    TSSetEquationType - Sets the type of the equation that TS is solving.
4330 
4331    Not Collective
4332 
4333    Input Parameters:
4334 +  ts - the TS context
4335 -  equation_type - see TSEquationType
4336 
4337    Level: advanced
4338 
4339 .seealso: `TSGetEquationType()`, `TSEquationType`
4340 @*/
4341 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type) {
4342   PetscFunctionBegin;
4343   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4344   ts->equation_type = equation_type;
4345   PetscFunctionReturn(0);
4346 }
4347 
4348 /*@
4349    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
4350 
4351    Not Collective
4352 
4353    Input Parameter:
4354 .  ts - the TS context
4355 
4356    Output Parameter:
4357 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4358             manual pages for the individual convergence tests for complete lists
4359 
4360    Level: beginner
4361 
4362    Notes:
4363    Can only be called after the call to TSSolve() is complete.
4364 
4365 .seealso: `TSSetConvergenceTest()`, `TSConvergedReason`
4366 @*/
4367 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason) {
4368   PetscFunctionBegin;
4369   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4370   PetscValidPointer(reason, 2);
4371   *reason = ts->reason;
4372   PetscFunctionReturn(0);
4373 }
4374 
4375 /*@
4376    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
4377 
4378    Logically Collective; reason must contain common value
4379 
4380    Input Parameters:
4381 +  ts - the TS context
4382 -  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4383             manual pages for the individual convergence tests for complete lists
4384 
4385    Level: advanced
4386 
4387    Notes:
4388    Can only be called while TSSolve() is active.
4389 
4390 .seealso: `TSConvergedReason`
4391 @*/
4392 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason) {
4393   PetscFunctionBegin;
4394   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4395   ts->reason = reason;
4396   PetscFunctionReturn(0);
4397 }
4398 
4399 /*@
4400    TSGetSolveTime - Gets the time after a call to TSSolve()
4401 
4402    Not Collective
4403 
4404    Input Parameter:
4405 .  ts - the TS context
4406 
4407    Output Parameter:
4408 .  ftime - the final time. This time corresponds to the final time set with TSSetMaxTime()
4409 
4410    Level: beginner
4411 
4412    Notes:
4413    Can only be called after the call to TSSolve() is complete.
4414 
4415 .seealso: `TSSetConvergenceTest()`, `TSConvergedReason`
4416 @*/
4417 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime) {
4418   PetscFunctionBegin;
4419   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4420   PetscValidRealPointer(ftime, 2);
4421   *ftime = ts->solvetime;
4422   PetscFunctionReturn(0);
4423 }
4424 
4425 /*@
4426    TSGetSNESIterations - Gets the total number of nonlinear iterations
4427    used by the time integrator.
4428 
4429    Not Collective
4430 
4431    Input Parameter:
4432 .  ts - TS context
4433 
4434    Output Parameter:
4435 .  nits - number of nonlinear iterations
4436 
4437    Notes:
4438    This counter is reset to zero for each successive call to TSSolve().
4439 
4440    Level: intermediate
4441 
4442 .seealso: `TSGetKSPIterations()`
4443 @*/
4444 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits) {
4445   PetscFunctionBegin;
4446   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4447   PetscValidIntPointer(nits, 2);
4448   *nits = ts->snes_its;
4449   PetscFunctionReturn(0);
4450 }
4451 
4452 /*@
4453    TSGetKSPIterations - Gets the total number of linear iterations
4454    used by the time integrator.
4455 
4456    Not Collective
4457 
4458    Input Parameter:
4459 .  ts - TS context
4460 
4461    Output Parameter:
4462 .  lits - number of linear iterations
4463 
4464    Notes:
4465    This counter is reset to zero for each successive call to TSSolve().
4466 
4467    Level: intermediate
4468 
4469 .seealso: `TSGetSNESIterations()`, `SNESGetKSPIterations()`
4470 @*/
4471 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits) {
4472   PetscFunctionBegin;
4473   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4474   PetscValidIntPointer(lits, 2);
4475   *lits = ts->ksp_its;
4476   PetscFunctionReturn(0);
4477 }
4478 
4479 /*@
4480    TSGetStepRejections - Gets the total number of rejected steps.
4481 
4482    Not Collective
4483 
4484    Input Parameter:
4485 .  ts - TS context
4486 
4487    Output Parameter:
4488 .  rejects - number of steps rejected
4489 
4490    Notes:
4491    This counter is reset to zero for each successive call to TSSolve().
4492 
4493    Level: intermediate
4494 
4495 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()`
4496 @*/
4497 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects) {
4498   PetscFunctionBegin;
4499   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4500   PetscValidIntPointer(rejects, 2);
4501   *rejects = ts->reject;
4502   PetscFunctionReturn(0);
4503 }
4504 
4505 /*@
4506    TSGetSNESFailures - Gets the total number of failed SNES solves
4507 
4508    Not Collective
4509 
4510    Input Parameter:
4511 .  ts - TS context
4512 
4513    Output Parameter:
4514 .  fails - number of failed nonlinear solves
4515 
4516    Notes:
4517    This counter is reset to zero for each successive call to TSSolve().
4518 
4519    Level: intermediate
4520 
4521 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()`
4522 @*/
4523 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails) {
4524   PetscFunctionBegin;
4525   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4526   PetscValidIntPointer(fails, 2);
4527   *fails = ts->num_snes_failures;
4528   PetscFunctionReturn(0);
4529 }
4530 
4531 /*@
4532    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
4533 
4534    Not Collective
4535 
4536    Input Parameters:
4537 +  ts - TS context
4538 -  rejects - maximum number of rejected steps, pass -1 for unlimited
4539 
4540    Notes:
4541    The counter is reset to zero for each step
4542 
4543    Options Database Key:
4544 .  -ts_max_reject - Maximum number of step rejections before a step fails
4545 
4546    Level: intermediate
4547 
4548 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()`
4549 @*/
4550 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects) {
4551   PetscFunctionBegin;
4552   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4553   ts->max_reject = rejects;
4554   PetscFunctionReturn(0);
4555 }
4556 
4557 /*@
4558    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
4559 
4560    Not Collective
4561 
4562    Input Parameters:
4563 +  ts - TS context
4564 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
4565 
4566    Notes:
4567    The counter is reset to zero for each successive call to TSSolve().
4568 
4569    Options Database Key:
4570 .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
4571 
4572    Level: intermediate
4573 
4574 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()`
4575 @*/
4576 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails) {
4577   PetscFunctionBegin;
4578   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4579   ts->max_snes_failures = fails;
4580   PetscFunctionReturn(0);
4581 }
4582 
4583 /*@
4584    TSSetErrorIfStepFails - Error if no step succeeds
4585 
4586    Not Collective
4587 
4588    Input Parameters:
4589 +  ts - TS context
4590 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
4591 
4592    Options Database Key:
4593 .  -ts_error_if_step_fails - Error if no step succeeds
4594 
4595    Level: intermediate
4596 
4597 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()`
4598 @*/
4599 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err) {
4600   PetscFunctionBegin;
4601   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4602   ts->errorifstepfailed = err;
4603   PetscFunctionReturn(0);
4604 }
4605 
4606 /*@
4607    TSGetAdapt - Get the adaptive controller context for the current method
4608 
4609    Collective on TS if controller has not been created yet
4610 
4611    Input Parameter:
4612 .  ts - time stepping context
4613 
4614    Output Parameter:
4615 .  adapt - adaptive controller
4616 
4617    Level: intermediate
4618 
4619 .seealso: `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()`
4620 @*/
4621 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt) {
4622   PetscFunctionBegin;
4623   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4624   PetscValidPointer(adapt, 2);
4625   if (!ts->adapt) {
4626     PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt));
4627     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1));
4628   }
4629   *adapt = ts->adapt;
4630   PetscFunctionReturn(0);
4631 }
4632 
4633 /*@
4634    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
4635 
4636    Logically Collective
4637 
4638    Input Parameters:
4639 +  ts - time integration context
4640 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
4641 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
4642 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
4643 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
4644 
4645    Options Database keys:
4646 +  -ts_rtol <rtol> - relative tolerance for local truncation error
4647 -  -ts_atol <atol> - Absolute tolerance for local truncation error
4648 
4649    Notes:
4650    With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
4651    (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
4652    computed only for the differential or the algebraic part then this can be done using the vector of
4653    tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
4654    differential part and infinity for the algebraic part, the LTE calculation will include only the
4655    differential variables.
4656 
4657    Level: beginner
4658 
4659 .seealso: `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()`
4660 @*/
4661 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol) {
4662   PetscFunctionBegin;
4663   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
4664   if (vatol) {
4665     PetscCall(PetscObjectReference((PetscObject)vatol));
4666     PetscCall(VecDestroy(&ts->vatol));
4667     ts->vatol = vatol;
4668   }
4669   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
4670   if (vrtol) {
4671     PetscCall(PetscObjectReference((PetscObject)vrtol));
4672     PetscCall(VecDestroy(&ts->vrtol));
4673     ts->vrtol = vrtol;
4674   }
4675   PetscFunctionReturn(0);
4676 }
4677 
4678 /*@
4679    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
4680 
4681    Logically Collective
4682 
4683    Input Parameter:
4684 .  ts - time integration context
4685 
4686    Output Parameters:
4687 +  atol - scalar absolute tolerances, NULL to ignore
4688 .  vatol - vector of absolute tolerances, NULL to ignore
4689 .  rtol - scalar relative tolerances, NULL to ignore
4690 -  vrtol - vector of relative tolerances, NULL to ignore
4691 
4692    Level: beginner
4693 
4694 .seealso: `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()`
4695 @*/
4696 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol) {
4697   PetscFunctionBegin;
4698   if (atol) *atol = ts->atol;
4699   if (vatol) *vatol = ts->vatol;
4700   if (rtol) *rtol = ts->rtol;
4701   if (vrtol) *vrtol = ts->vrtol;
4702   PetscFunctionReturn(0);
4703 }
4704 
4705 /*@
4706    TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors
4707 
4708    Collective on TS
4709 
4710    Input Parameters:
4711 +  ts - time stepping context
4712 .  U - state vector, usually ts->vec_sol
4713 -  Y - state vector to be compared to U
4714 
4715    Output Parameters:
4716 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
4717 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
4718 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
4719 
4720    Level: developer
4721 
4722 .seealso: `TSErrorWeightedNorm()`, `TSErrorWeightedNormInfinity()`
4723 @*/
4724 PetscErrorCode TSErrorWeightedNorm2(TS ts, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) {
4725   PetscInt           i, n, N, rstart;
4726   PetscInt           n_loc, na_loc, nr_loc;
4727   PetscReal          n_glb, na_glb, nr_glb;
4728   const PetscScalar *u, *y;
4729   PetscReal          sum, suma, sumr, gsum, gsuma, gsumr, diff;
4730   PetscReal          tol, tola, tolr;
4731   PetscReal          err_loc[6], err_glb[6];
4732 
4733   PetscFunctionBegin;
4734   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4735   PetscValidHeaderSpecific(U, VEC_CLASSID, 2);
4736   PetscValidHeaderSpecific(Y, VEC_CLASSID, 3);
4737   PetscValidType(U, 2);
4738   PetscValidType(Y, 3);
4739   PetscCheckSameComm(U, 2, Y, 3);
4740   PetscValidRealPointer(norm, 4);
4741   PetscValidRealPointer(norma, 5);
4742   PetscValidRealPointer(normr, 6);
4743   PetscCheck(U != Y, PetscObjectComm((PetscObject)U), PETSC_ERR_ARG_IDN, "U and Y cannot be the same vector");
4744 
4745   PetscCall(VecGetSize(U, &N));
4746   PetscCall(VecGetLocalSize(U, &n));
4747   PetscCall(VecGetOwnershipRange(U, &rstart, NULL));
4748   PetscCall(VecGetArrayRead(U, &u));
4749   PetscCall(VecGetArrayRead(Y, &y));
4750   sum    = 0.;
4751   n_loc  = 0;
4752   suma   = 0.;
4753   na_loc = 0;
4754   sumr   = 0.;
4755   nr_loc = 0;
4756   if (ts->vatol && ts->vrtol) {
4757     const PetscScalar *atol, *rtol;
4758     PetscCall(VecGetArrayRead(ts->vatol, &atol));
4759     PetscCall(VecGetArrayRead(ts->vrtol, &rtol));
4760     for (i = 0; i < n; i++) {
4761       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
4762       diff = PetscAbsScalar(y[i] - u[i]);
4763       tola = PetscRealPart(atol[i]);
4764       if (tola > 0.) {
4765         suma += PetscSqr(diff / tola);
4766         na_loc++;
4767       }
4768       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
4769       if (tolr > 0.) {
4770         sumr += PetscSqr(diff / tolr);
4771         nr_loc++;
4772       }
4773       tol = tola + tolr;
4774       if (tol > 0.) {
4775         sum += PetscSqr(diff / tol);
4776         n_loc++;
4777       }
4778     }
4779     PetscCall(VecRestoreArrayRead(ts->vatol, &atol));
4780     PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol));
4781   } else if (ts->vatol) { /* vector atol, scalar rtol */
4782     const PetscScalar *atol;
4783     PetscCall(VecGetArrayRead(ts->vatol, &atol));
4784     for (i = 0; i < n; i++) {
4785       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
4786       diff = PetscAbsScalar(y[i] - u[i]);
4787       tola = PetscRealPart(atol[i]);
4788       if (tola > 0.) {
4789         suma += PetscSqr(diff / tola);
4790         na_loc++;
4791       }
4792       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
4793       if (tolr > 0.) {
4794         sumr += PetscSqr(diff / tolr);
4795         nr_loc++;
4796       }
4797       tol = tola + tolr;
4798       if (tol > 0.) {
4799         sum += PetscSqr(diff / tol);
4800         n_loc++;
4801       }
4802     }
4803     PetscCall(VecRestoreArrayRead(ts->vatol, &atol));
4804   } else if (ts->vrtol) { /* scalar atol, vector rtol */
4805     const PetscScalar *rtol;
4806     PetscCall(VecGetArrayRead(ts->vrtol, &rtol));
4807     for (i = 0; i < n; i++) {
4808       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
4809       diff = PetscAbsScalar(y[i] - u[i]);
4810       tola = ts->atol;
4811       if (tola > 0.) {
4812         suma += PetscSqr(diff / tola);
4813         na_loc++;
4814       }
4815       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
4816       if (tolr > 0.) {
4817         sumr += PetscSqr(diff / tolr);
4818         nr_loc++;
4819       }
4820       tol = tola + tolr;
4821       if (tol > 0.) {
4822         sum += PetscSqr(diff / tol);
4823         n_loc++;
4824       }
4825     }
4826     PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol));
4827   } else { /* scalar atol, scalar rtol */
4828     for (i = 0; i < n; i++) {
4829       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
4830       diff = PetscAbsScalar(y[i] - u[i]);
4831       tola = ts->atol;
4832       if (tola > 0.) {
4833         suma += PetscSqr(diff / tola);
4834         na_loc++;
4835       }
4836       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
4837       if (tolr > 0.) {
4838         sumr += PetscSqr(diff / tolr);
4839         nr_loc++;
4840       }
4841       tol = tola + tolr;
4842       if (tol > 0.) {
4843         sum += PetscSqr(diff / tol);
4844         n_loc++;
4845       }
4846     }
4847   }
4848   PetscCall(VecRestoreArrayRead(U, &u));
4849   PetscCall(VecRestoreArrayRead(Y, &y));
4850 
4851   err_loc[0] = sum;
4852   err_loc[1] = suma;
4853   err_loc[2] = sumr;
4854   err_loc[3] = (PetscReal)n_loc;
4855   err_loc[4] = (PetscReal)na_loc;
4856   err_loc[5] = (PetscReal)nr_loc;
4857 
4858   PetscCall(MPIU_Allreduce(err_loc, err_glb, 6, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ts)));
4859 
4860   gsum   = err_glb[0];
4861   gsuma  = err_glb[1];
4862   gsumr  = err_glb[2];
4863   n_glb  = err_glb[3];
4864   na_glb = err_glb[4];
4865   nr_glb = err_glb[5];
4866 
4867   *norm = 0.;
4868   if (n_glb > 0.) *norm = PetscSqrtReal(gsum / n_glb);
4869   *norma = 0.;
4870   if (na_glb > 0.) *norma = PetscSqrtReal(gsuma / na_glb);
4871   *normr = 0.;
4872   if (nr_glb > 0.) *normr = PetscSqrtReal(gsumr / nr_glb);
4873 
4874   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
4875   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
4876   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
4877   PetscFunctionReturn(0);
4878 }
4879 
4880 /*@
4881    TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors
4882 
4883    Collective on TS
4884 
4885    Input Parameters:
4886 +  ts - time stepping context
4887 .  U - state vector, usually ts->vec_sol
4888 -  Y - state vector to be compared to U
4889 
4890    Output Parameters:
4891 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
4892 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
4893 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
4894 
4895    Level: developer
4896 
4897 .seealso: `TSErrorWeightedNorm()`, `TSErrorWeightedNorm2()`
4898 @*/
4899 PetscErrorCode TSErrorWeightedNormInfinity(TS ts, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) {
4900   PetscInt           i, n, N, rstart;
4901   const PetscScalar *u, *y;
4902   PetscReal          max, gmax, maxa, gmaxa, maxr, gmaxr;
4903   PetscReal          tol, tola, tolr, diff;
4904   PetscReal          err_loc[3], err_glb[3];
4905 
4906   PetscFunctionBegin;
4907   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4908   PetscValidHeaderSpecific(U, VEC_CLASSID, 2);
4909   PetscValidHeaderSpecific(Y, VEC_CLASSID, 3);
4910   PetscValidType(U, 2);
4911   PetscValidType(Y, 3);
4912   PetscCheckSameComm(U, 2, Y, 3);
4913   PetscValidRealPointer(norm, 4);
4914   PetscValidRealPointer(norma, 5);
4915   PetscValidRealPointer(normr, 6);
4916   PetscCheck(U != Y, PetscObjectComm((PetscObject)U), PETSC_ERR_ARG_IDN, "U and Y cannot be the same vector");
4917 
4918   PetscCall(VecGetSize(U, &N));
4919   PetscCall(VecGetLocalSize(U, &n));
4920   PetscCall(VecGetOwnershipRange(U, &rstart, NULL));
4921   PetscCall(VecGetArrayRead(U, &u));
4922   PetscCall(VecGetArrayRead(Y, &y));
4923 
4924   max  = 0.;
4925   maxa = 0.;
4926   maxr = 0.;
4927 
4928   if (ts->vatol && ts->vrtol) { /* vector atol, vector rtol */
4929     const PetscScalar *atol, *rtol;
4930     PetscCall(VecGetArrayRead(ts->vatol, &atol));
4931     PetscCall(VecGetArrayRead(ts->vrtol, &rtol));
4932 
4933     for (i = 0; i < n; i++) {
4934       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
4935       diff = PetscAbsScalar(y[i] - u[i]);
4936       tola = PetscRealPart(atol[i]);
4937       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
4938       tol  = tola + tolr;
4939       if (tola > 0.) maxa = PetscMax(maxa, diff / tola);
4940       if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr);
4941       if (tol > 0.) max = PetscMax(max, diff / tol);
4942     }
4943     PetscCall(VecRestoreArrayRead(ts->vatol, &atol));
4944     PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol));
4945   } else if (ts->vatol) { /* vector atol, scalar rtol */
4946     const PetscScalar *atol;
4947     PetscCall(VecGetArrayRead(ts->vatol, &atol));
4948     for (i = 0; i < n; i++) {
4949       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
4950       diff = PetscAbsScalar(y[i] - u[i]);
4951       tola = PetscRealPart(atol[i]);
4952       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
4953       tol  = tola + tolr;
4954       if (tola > 0.) maxa = PetscMax(maxa, diff / tola);
4955       if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr);
4956       if (tol > 0.) max = PetscMax(max, diff / tol);
4957     }
4958     PetscCall(VecRestoreArrayRead(ts->vatol, &atol));
4959   } else if (ts->vrtol) { /* scalar atol, vector rtol */
4960     const PetscScalar *rtol;
4961     PetscCall(VecGetArrayRead(ts->vrtol, &rtol));
4962 
4963     for (i = 0; i < n; i++) {
4964       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
4965       diff = PetscAbsScalar(y[i] - u[i]);
4966       tola = ts->atol;
4967       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
4968       tol  = tola + tolr;
4969       if (tola > 0.) maxa = PetscMax(maxa, diff / tola);
4970       if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr);
4971       if (tol > 0.) max = PetscMax(max, diff / tol);
4972     }
4973     PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol));
4974   } else { /* scalar atol, scalar rtol */
4975 
4976     for (i = 0; i < n; i++) {
4977       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
4978       diff = PetscAbsScalar(y[i] - u[i]);
4979       tola = ts->atol;
4980       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
4981       tol  = tola + tolr;
4982       if (tola > 0.) maxa = PetscMax(maxa, diff / tola);
4983       if (tolr > 0.) maxr = PetscMax(maxr, diff / tolr);
4984       if (tol > 0.) max = PetscMax(max, diff / tol);
4985     }
4986   }
4987   PetscCall(VecRestoreArrayRead(U, &u));
4988   PetscCall(VecRestoreArrayRead(Y, &y));
4989   err_loc[0] = max;
4990   err_loc[1] = maxa;
4991   err_loc[2] = maxr;
4992   PetscCall(MPIU_Allreduce(err_loc, err_glb, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)ts)));
4993   gmax  = err_glb[0];
4994   gmaxa = err_glb[1];
4995   gmaxr = err_glb[2];
4996 
4997   *norm  = gmax;
4998   *norma = gmaxa;
4999   *normr = gmaxr;
5000   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5001   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5002   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5003   PetscFunctionReturn(0);
5004 }
5005 
5006 /*@
5007    TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
5008 
5009    Collective on TS
5010 
5011    Input Parameters:
5012 +  ts - time stepping context
5013 .  U - state vector, usually ts->vec_sol
5014 .  Y - state vector to be compared to U
5015 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
5016 
5017    Output Parameters:
5018 +  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5019 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5020 -  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5021 
5022    Options Database Keys:
5023 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5024 
5025    Level: developer
5026 
5027 .seealso: `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()`, `TSErrorWeightedENorm`
5028 @*/
5029 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) {
5030   PetscFunctionBegin;
5031   if (wnormtype == NORM_2) PetscCall(TSErrorWeightedNorm2(ts, U, Y, norm, norma, normr));
5032   else if (wnormtype == NORM_INFINITY) PetscCall(TSErrorWeightedNormInfinity(ts, U, Y, norm, norma, normr));
5033   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]);
5034   PetscFunctionReturn(0);
5035 }
5036 
5037 /*@
5038    TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances
5039 
5040    Collective on TS
5041 
5042    Input Parameters:
5043 +  ts - time stepping context
5044 .  E - error vector
5045 .  U - state vector, usually ts->vec_sol
5046 -  Y - state vector, previous time step
5047 
5048    Output Parameters:
5049 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5050 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5051 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5052 
5053    Level: developer
5054 
5055 .seealso: `TSErrorWeightedENorm()`, `TSErrorWeightedENormInfinity()`
5056 @*/
5057 PetscErrorCode TSErrorWeightedENorm2(TS ts, Vec E, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) {
5058   PetscInt           i, n, N, rstart;
5059   PetscInt           n_loc, na_loc, nr_loc;
5060   PetscReal          n_glb, na_glb, nr_glb;
5061   const PetscScalar *e, *u, *y;
5062   PetscReal          err, sum, suma, sumr, gsum, gsuma, gsumr;
5063   PetscReal          tol, tola, tolr;
5064   PetscReal          err_loc[6], err_glb[6];
5065 
5066   PetscFunctionBegin;
5067   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5068   PetscValidHeaderSpecific(E, VEC_CLASSID, 2);
5069   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
5070   PetscValidHeaderSpecific(Y, VEC_CLASSID, 4);
5071   PetscValidType(E, 2);
5072   PetscValidType(U, 3);
5073   PetscValidType(Y, 4);
5074   PetscCheckSameComm(E, 2, U, 3);
5075   PetscCheckSameComm(U, 3, Y, 4);
5076   PetscValidRealPointer(norm, 5);
5077   PetscValidRealPointer(norma, 6);
5078   PetscValidRealPointer(normr, 7);
5079 
5080   PetscCall(VecGetSize(E, &N));
5081   PetscCall(VecGetLocalSize(E, &n));
5082   PetscCall(VecGetOwnershipRange(E, &rstart, NULL));
5083   PetscCall(VecGetArrayRead(E, &e));
5084   PetscCall(VecGetArrayRead(U, &u));
5085   PetscCall(VecGetArrayRead(Y, &y));
5086   sum    = 0.;
5087   n_loc  = 0;
5088   suma   = 0.;
5089   na_loc = 0;
5090   sumr   = 0.;
5091   nr_loc = 0;
5092   if (ts->vatol && ts->vrtol) {
5093     const PetscScalar *atol, *rtol;
5094     PetscCall(VecGetArrayRead(ts->vatol, &atol));
5095     PetscCall(VecGetArrayRead(ts->vrtol, &rtol));
5096     for (i = 0; i < n; i++) {
5097       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
5098       err  = PetscAbsScalar(e[i]);
5099       tola = PetscRealPart(atol[i]);
5100       if (tola > 0.) {
5101         suma += PetscSqr(err / tola);
5102         na_loc++;
5103       }
5104       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
5105       if (tolr > 0.) {
5106         sumr += PetscSqr(err / tolr);
5107         nr_loc++;
5108       }
5109       tol = tola + tolr;
5110       if (tol > 0.) {
5111         sum += PetscSqr(err / tol);
5112         n_loc++;
5113       }
5114     }
5115     PetscCall(VecRestoreArrayRead(ts->vatol, &atol));
5116     PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol));
5117   } else if (ts->vatol) { /* vector atol, scalar rtol */
5118     const PetscScalar *atol;
5119     PetscCall(VecGetArrayRead(ts->vatol, &atol));
5120     for (i = 0; i < n; i++) {
5121       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
5122       err  = PetscAbsScalar(e[i]);
5123       tola = PetscRealPart(atol[i]);
5124       if (tola > 0.) {
5125         suma += PetscSqr(err / tola);
5126         na_loc++;
5127       }
5128       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
5129       if (tolr > 0.) {
5130         sumr += PetscSqr(err / tolr);
5131         nr_loc++;
5132       }
5133       tol = tola + tolr;
5134       if (tol > 0.) {
5135         sum += PetscSqr(err / tol);
5136         n_loc++;
5137       }
5138     }
5139     PetscCall(VecRestoreArrayRead(ts->vatol, &atol));
5140   } else if (ts->vrtol) { /* scalar atol, vector rtol */
5141     const PetscScalar *rtol;
5142     PetscCall(VecGetArrayRead(ts->vrtol, &rtol));
5143     for (i = 0; i < n; i++) {
5144       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
5145       err  = PetscAbsScalar(e[i]);
5146       tola = ts->atol;
5147       if (tola > 0.) {
5148         suma += PetscSqr(err / tola);
5149         na_loc++;
5150       }
5151       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
5152       if (tolr > 0.) {
5153         sumr += PetscSqr(err / tolr);
5154         nr_loc++;
5155       }
5156       tol = tola + tolr;
5157       if (tol > 0.) {
5158         sum += PetscSqr(err / tol);
5159         n_loc++;
5160       }
5161     }
5162     PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol));
5163   } else { /* scalar atol, scalar rtol */
5164     for (i = 0; i < n; i++) {
5165       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
5166       err  = PetscAbsScalar(e[i]);
5167       tola = ts->atol;
5168       if (tola > 0.) {
5169         suma += PetscSqr(err / tola);
5170         na_loc++;
5171       }
5172       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
5173       if (tolr > 0.) {
5174         sumr += PetscSqr(err / tolr);
5175         nr_loc++;
5176       }
5177       tol = tola + tolr;
5178       if (tol > 0.) {
5179         sum += PetscSqr(err / tol);
5180         n_loc++;
5181       }
5182     }
5183   }
5184   PetscCall(VecRestoreArrayRead(E, &e));
5185   PetscCall(VecRestoreArrayRead(U, &u));
5186   PetscCall(VecRestoreArrayRead(Y, &y));
5187 
5188   err_loc[0] = sum;
5189   err_loc[1] = suma;
5190   err_loc[2] = sumr;
5191   err_loc[3] = (PetscReal)n_loc;
5192   err_loc[4] = (PetscReal)na_loc;
5193   err_loc[5] = (PetscReal)nr_loc;
5194 
5195   PetscCall(MPIU_Allreduce(err_loc, err_glb, 6, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ts)));
5196 
5197   gsum   = err_glb[0];
5198   gsuma  = err_glb[1];
5199   gsumr  = err_glb[2];
5200   n_glb  = err_glb[3];
5201   na_glb = err_glb[4];
5202   nr_glb = err_glb[5];
5203 
5204   *norm = 0.;
5205   if (n_glb > 0.) *norm = PetscSqrtReal(gsum / n_glb);
5206   *norma = 0.;
5207   if (na_glb > 0.) *norma = PetscSqrtReal(gsuma / na_glb);
5208   *normr = 0.;
5209   if (nr_glb > 0.) *normr = PetscSqrtReal(gsumr / nr_glb);
5210 
5211   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5212   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5213   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5214   PetscFunctionReturn(0);
5215 }
5216 
5217 /*@
5218    TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances
5219    Collective on TS
5220 
5221    Input Parameters:
5222 +  ts - time stepping context
5223 .  E - error vector
5224 .  U - state vector, usually ts->vec_sol
5225 -  Y - state vector, previous time step
5226 
5227    Output Parameters:
5228 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5229 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5230 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5231 
5232    Level: developer
5233 
5234 .seealso: `TSErrorWeightedENorm()`, `TSErrorWeightedENorm2()`
5235 @*/
5236 PetscErrorCode TSErrorWeightedENormInfinity(TS ts, Vec E, Vec U, Vec Y, PetscReal *norm, PetscReal *norma, PetscReal *normr) {
5237   PetscInt           i, n, N, rstart;
5238   const PetscScalar *e, *u, *y;
5239   PetscReal          err, max, gmax, maxa, gmaxa, maxr, gmaxr;
5240   PetscReal          tol, tola, tolr;
5241   PetscReal          err_loc[3], err_glb[3];
5242 
5243   PetscFunctionBegin;
5244   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5245   PetscValidHeaderSpecific(E, VEC_CLASSID, 2);
5246   PetscValidHeaderSpecific(U, VEC_CLASSID, 3);
5247   PetscValidHeaderSpecific(Y, VEC_CLASSID, 4);
5248   PetscValidType(E, 2);
5249   PetscValidType(U, 3);
5250   PetscValidType(Y, 4);
5251   PetscCheckSameComm(E, 2, U, 3);
5252   PetscCheckSameComm(U, 3, Y, 4);
5253   PetscValidRealPointer(norm, 5);
5254   PetscValidRealPointer(norma, 6);
5255   PetscValidRealPointer(normr, 7);
5256 
5257   PetscCall(VecGetSize(E, &N));
5258   PetscCall(VecGetLocalSize(E, &n));
5259   PetscCall(VecGetOwnershipRange(E, &rstart, NULL));
5260   PetscCall(VecGetArrayRead(E, &e));
5261   PetscCall(VecGetArrayRead(U, &u));
5262   PetscCall(VecGetArrayRead(Y, &y));
5263 
5264   max  = 0.;
5265   maxa = 0.;
5266   maxr = 0.;
5267 
5268   if (ts->vatol && ts->vrtol) { /* vector atol, vector rtol */
5269     const PetscScalar *atol, *rtol;
5270     PetscCall(VecGetArrayRead(ts->vatol, &atol));
5271     PetscCall(VecGetArrayRead(ts->vrtol, &rtol));
5272 
5273     for (i = 0; i < n; i++) {
5274       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
5275       err  = PetscAbsScalar(e[i]);
5276       tola = PetscRealPart(atol[i]);
5277       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
5278       tol  = tola + tolr;
5279       if (tola > 0.) maxa = PetscMax(maxa, err / tola);
5280       if (tolr > 0.) maxr = PetscMax(maxr, err / tolr);
5281       if (tol > 0.) max = PetscMax(max, err / tol);
5282     }
5283     PetscCall(VecRestoreArrayRead(ts->vatol, &atol));
5284     PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol));
5285   } else if (ts->vatol) { /* vector atol, scalar rtol */
5286     const PetscScalar *atol;
5287     PetscCall(VecGetArrayRead(ts->vatol, &atol));
5288     for (i = 0; i < n; i++) {
5289       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
5290       err  = PetscAbsScalar(e[i]);
5291       tola = PetscRealPart(atol[i]);
5292       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
5293       tol  = tola + tolr;
5294       if (tola > 0.) maxa = PetscMax(maxa, err / tola);
5295       if (tolr > 0.) maxr = PetscMax(maxr, err / tolr);
5296       if (tol > 0.) max = PetscMax(max, err / tol);
5297     }
5298     PetscCall(VecRestoreArrayRead(ts->vatol, &atol));
5299   } else if (ts->vrtol) { /* scalar atol, vector rtol */
5300     const PetscScalar *rtol;
5301     PetscCall(VecGetArrayRead(ts->vrtol, &rtol));
5302 
5303     for (i = 0; i < n; i++) {
5304       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
5305       err  = PetscAbsScalar(e[i]);
5306       tola = ts->atol;
5307       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
5308       tol  = tola + tolr;
5309       if (tola > 0.) maxa = PetscMax(maxa, err / tola);
5310       if (tolr > 0.) maxr = PetscMax(maxr, err / tolr);
5311       if (tol > 0.) max = PetscMax(max, err / tol);
5312     }
5313     PetscCall(VecRestoreArrayRead(ts->vrtol, &rtol));
5314   } else { /* scalar atol, scalar rtol */
5315 
5316     for (i = 0; i < n; i++) {
5317       SkipSmallValue(y[i], u[i], ts->adapt->ignore_max);
5318       err  = PetscAbsScalar(e[i]);
5319       tola = ts->atol;
5320       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]), PetscAbsScalar(y[i]));
5321       tol  = tola + tolr;
5322       if (tola > 0.) maxa = PetscMax(maxa, err / tola);
5323       if (tolr > 0.) maxr = PetscMax(maxr, err / tolr);
5324       if (tol > 0.) max = PetscMax(max, err / tol);
5325     }
5326   }
5327   PetscCall(VecRestoreArrayRead(E, &e));
5328   PetscCall(VecRestoreArrayRead(U, &u));
5329   PetscCall(VecRestoreArrayRead(Y, &y));
5330   err_loc[0] = max;
5331   err_loc[1] = maxa;
5332   err_loc[2] = maxr;
5333   PetscCall(MPIU_Allreduce(err_loc, err_glb, 3, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)ts)));
5334   gmax  = err_glb[0];
5335   gmaxa = err_glb[1];
5336   gmaxr = err_glb[2];
5337 
5338   *norm  = gmax;
5339   *norma = gmaxa;
5340   *normr = gmaxr;
5341   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5342   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5343   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5344   PetscFunctionReturn(0);
5345 }
5346 
5347 /*@
5348    TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
5349 
5350    Collective on TS
5351 
5352    Input Parameters:
5353 +  ts - time stepping context
5354 .  E - error vector
5355 .  U - state vector, usually ts->vec_sol
5356 .  Y - state vector, previous time step
5357 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
5358 
5359    Output Parameters:
5360 +  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5361 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5362 -  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5363 
5364    Options Database Keys:
5365 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5366 
5367    Level: developer
5368 
5369 .seealso: `TSErrorWeightedENormInfinity()`, `TSErrorWeightedENorm2()`, `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()`
5370 @*/
5371 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr) {
5372   PetscFunctionBegin;
5373   if (wnormtype == NORM_2) PetscCall(TSErrorWeightedENorm2(ts, E, U, Y, norm, norma, normr));
5374   else if (wnormtype == NORM_INFINITY) PetscCall(TSErrorWeightedENormInfinity(ts, E, U, Y, norm, norma, normr));
5375   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for norm type %s", NormTypes[wnormtype]);
5376   PetscFunctionReturn(0);
5377 }
5378 
5379 /*@
5380    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
5381 
5382    Logically Collective on TS
5383 
5384    Input Parameters:
5385 +  ts - time stepping context
5386 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
5387 
5388    Note:
5389    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
5390 
5391    Level: intermediate
5392 
5393 .seealso: `TSGetCFLTime()`, `TSADAPTCFL`
5394 @*/
5395 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime) {
5396   PetscFunctionBegin;
5397   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5398   ts->cfltime_local = cfltime;
5399   ts->cfltime       = -1.;
5400   PetscFunctionReturn(0);
5401 }
5402 
5403 /*@
5404    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
5405 
5406    Collective on TS
5407 
5408    Input Parameter:
5409 .  ts - time stepping context
5410 
5411    Output Parameter:
5412 .  cfltime - maximum stable time step for forward Euler
5413 
5414    Level: advanced
5415 
5416 .seealso: `TSSetCFLTimeLocal()`
5417 @*/
5418 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime) {
5419   PetscFunctionBegin;
5420   if (ts->cfltime < 0) PetscCall(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts)));
5421   *cfltime = ts->cfltime;
5422   PetscFunctionReturn(0);
5423 }
5424 
5425 /*@
5426    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
5427 
5428    Input Parameters:
5429 +  ts   - the TS context.
5430 .  xl   - lower bound.
5431 -  xu   - upper bound.
5432 
5433    Notes:
5434    If this routine is not called then the lower and upper bounds are set to
5435    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
5436 
5437    Level: advanced
5438 
5439 @*/
5440 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu) {
5441   SNES snes;
5442 
5443   PetscFunctionBegin;
5444   PetscCall(TSGetSNES(ts, &snes));
5445   PetscCall(SNESVISetVariableBounds(snes, xl, xu));
5446   PetscFunctionReturn(0);
5447 }
5448 
5449 /*@
5450    TSComputeLinearStability - computes the linear stability function at a point
5451 
5452    Collective on TS
5453 
5454    Input Parameters:
5455 +  ts - the TS context
5456 -  xr,xi - real and imaginary part of input arguments
5457 
5458    Output Parameters:
5459 .  yr,yi - real and imaginary part of function value
5460 
5461    Level: developer
5462 
5463 .seealso: `TSSetRHSFunction()`, `TSComputeIFunction()`
5464 @*/
5465 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi) {
5466   PetscFunctionBegin;
5467   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5468   PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi);
5469   PetscFunctionReturn(0);
5470 }
5471 
5472 /*@
5473    TSRestartStep - Flags the solver to restart the next step
5474 
5475    Collective on TS
5476 
5477    Input Parameter:
5478 .  ts - the TS context obtained from TSCreate()
5479 
5480    Level: advanced
5481 
5482    Notes:
5483    Multistep methods like BDF or Runge-Kutta methods with FSAL property require restarting the solver in the event of
5484    discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
5485    vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
5486    the sake of correctness and maximum safety, users are expected to call TSRestart() whenever they introduce
5487    discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
5488    discontinuous source terms).
5489 
5490 .seealso: `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()`
5491 @*/
5492 PetscErrorCode TSRestartStep(TS ts) {
5493   PetscFunctionBegin;
5494   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5495   ts->steprestart = PETSC_TRUE;
5496   PetscFunctionReturn(0);
5497 }
5498 
5499 /*@
5500    TSRollBack - Rolls back one time step
5501 
5502    Collective on TS
5503 
5504    Input Parameter:
5505 .  ts - the TS context obtained from TSCreate()
5506 
5507    Level: advanced
5508 
5509 .seealso: `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()`
5510 @*/
5511 PetscErrorCode TSRollBack(TS ts) {
5512   PetscFunctionBegin;
5513   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5514   PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called");
5515   PetscUseTypeMethod(ts, rollback);
5516   ts->time_step  = ts->ptime - ts->ptime_prev;
5517   ts->ptime      = ts->ptime_prev;
5518   ts->ptime_prev = ts->ptime_prev_rollback;
5519   ts->steps--;
5520   ts->steprollback = PETSC_TRUE;
5521   PetscFunctionReturn(0);
5522 }
5523 
5524 /*@
5525    TSGetStages - Get the number of stages and stage values
5526 
5527    Input Parameter:
5528 .  ts - the TS context obtained from TSCreate()
5529 
5530    Output Parameters:
5531 +  ns - the number of stages
5532 -  Y - the current stage vectors
5533 
5534    Level: advanced
5535 
5536    Notes: Both ns and Y can be NULL.
5537 
5538 .seealso: `TSCreate()`
5539 @*/
5540 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y) {
5541   PetscFunctionBegin;
5542   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5543   if (ns) PetscValidIntPointer(ns, 2);
5544   if (Y) PetscValidPointer(Y, 3);
5545   if (!ts->ops->getstages) {
5546     if (ns) *ns = 0;
5547     if (Y) *Y = NULL;
5548   } else PetscUseTypeMethod(ts, getstages, ns, Y);
5549   PetscFunctionReturn(0);
5550 }
5551 
5552 /*@C
5553   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
5554 
5555   Collective on SNES
5556 
5557   Input Parameters:
5558 + ts - the TS context
5559 . t - current timestep
5560 . U - state vector
5561 . Udot - time derivative of state vector
5562 . shift - shift to apply, see note below
5563 - ctx - an optional user context
5564 
5565   Output Parameters:
5566 + J - Jacobian matrix (not altered in this routine)
5567 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
5568 
5569   Level: intermediate
5570 
5571   Notes:
5572   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
5573 
5574   dF/dU + shift*dF/dUdot
5575 
5576   Most users should not need to explicitly call this routine, as it
5577   is used internally within the nonlinear solvers.
5578 
5579   This will first try to get the coloring from the DM.  If the DM type has no coloring
5580   routine, then it will try to get the coloring from the matrix.  This requires that the
5581   matrix have nonzero entries precomputed.
5582 
5583 .seealso: `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
5584 @*/
5585 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx) {
5586   SNES          snes;
5587   MatFDColoring color;
5588   PetscBool     hascolor, matcolor = PETSC_FALSE;
5589 
5590   PetscFunctionBegin;
5591   PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL));
5592   PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color));
5593   if (!color) {
5594     DM         dm;
5595     ISColoring iscoloring;
5596 
5597     PetscCall(TSGetDM(ts, &dm));
5598     PetscCall(DMHasColoring(dm, &hascolor));
5599     if (hascolor && !matcolor) {
5600       PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring));
5601       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5602       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts));
5603       PetscCall(MatFDColoringSetFromOptions(color));
5604       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5605       PetscCall(ISColoringDestroy(&iscoloring));
5606     } else {
5607       MatColoring mc;
5608 
5609       PetscCall(MatColoringCreate(B, &mc));
5610       PetscCall(MatColoringSetDistance(mc, 2));
5611       PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
5612       PetscCall(MatColoringSetFromOptions(mc));
5613       PetscCall(MatColoringApply(mc, &iscoloring));
5614       PetscCall(MatColoringDestroy(&mc));
5615       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5616       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode(*)(void))SNESTSFormFunction, (void *)ts));
5617       PetscCall(MatFDColoringSetFromOptions(color));
5618       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5619       PetscCall(ISColoringDestroy(&iscoloring));
5620     }
5621     PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color));
5622     PetscCall(PetscObjectDereference((PetscObject)color));
5623   }
5624   PetscCall(TSGetSNES(ts, &snes));
5625   PetscCall(MatFDColoringApply(B, color, U, snes));
5626   if (J != B) {
5627     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
5628     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
5629   }
5630   PetscFunctionReturn(0);
5631 }
5632 
5633 /*@
5634     TSSetFunctionDomainError - Set a function that tests if the current state vector is valid
5635 
5636     Input Parameters:
5637 +    ts - the TS context
5638 -    func - function called within TSFunctionDomainError
5639 
5640     Calling sequence of func:
5641 $     PetscErrorCode func(TS ts,PetscReal time,Vec state,PetscBool reject)
5642 
5643 +   ts - the TS context
5644 .   time - the current time (of the stage)
5645 .   state - the state to check if it is valid
5646 -   reject - (output parameter) PETSC_FALSE if the state is acceptable, PETSC_TRUE if not acceptable
5647 
5648     Level: intermediate
5649 
5650     Notes:
5651       If an implicit ODE solver is being used then, in addition to providing this routine, the
5652       user's code should call SNESSetFunctionDomainError() when domain errors occur during
5653       function evaluations where the functions are provided by TSSetIFunction() or TSSetRHSFunction().
5654       Use TSGetSNES() to obtain the SNES object
5655 
5656     Developer Notes:
5657       The naming of this function is inconsistent with the SNESSetFunctionDomainError()
5658       since one takes a function pointer and the other does not.
5659 
5660 .seealso: `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()`
5661 @*/
5662 
5663 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS, PetscReal, Vec, PetscBool *)) {
5664   PetscFunctionBegin;
5665   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5666   ts->functiondomainerror = func;
5667   PetscFunctionReturn(0);
5668 }
5669 
5670 /*@
5671     TSFunctionDomainError - Checks if the current state is valid
5672 
5673     Input Parameters:
5674 +    ts - the TS context
5675 .    stagetime - time of the simulation
5676 -    Y - state vector to check.
5677 
5678     Output Parameter:
5679 .    accept - Set to PETSC_FALSE if the current state vector is valid.
5680 
5681     Note:
5682     This function is called by the TS integration routines and calls the user provided function (set with TSSetFunctionDomainError())
5683     to check if the current state is valid.
5684 
5685     Level: developer
5686 
5687 .seealso: `TSSetFunctionDomainError()`
5688 @*/
5689 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept) {
5690   PetscFunctionBegin;
5691   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5692   *accept = PETSC_TRUE;
5693   if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept));
5694   PetscFunctionReturn(0);
5695 }
5696 
5697 /*@C
5698   TSClone - This function clones a time step object.
5699 
5700   Collective
5701 
5702   Input Parameter:
5703 . tsin    - The input TS
5704 
5705   Output Parameter:
5706 . tsout   - The output TS (cloned)
5707 
5708   Notes:
5709   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.
5710 
5711   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);
5712 
5713   Level: developer
5714 
5715 .seealso: `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()`
5716 @*/
5717 PetscErrorCode TSClone(TS tsin, TS *tsout) {
5718   TS     t;
5719   SNES   snes_start;
5720   DM     dm;
5721   TSType type;
5722 
5723   PetscFunctionBegin;
5724   PetscValidPointer(tsin, 1);
5725   *tsout = NULL;
5726 
5727   PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView));
5728 
5729   /* General TS description */
5730   t->numbermonitors    = 0;
5731   t->monitorFrequency  = 1;
5732   t->setupcalled       = 0;
5733   t->ksp_its           = 0;
5734   t->snes_its          = 0;
5735   t->nwork             = 0;
5736   t->rhsjacobian.time  = PETSC_MIN_REAL;
5737   t->rhsjacobian.scale = 1.;
5738   t->ijacobian.shift   = 1.;
5739 
5740   PetscCall(TSGetSNES(tsin, &snes_start));
5741   PetscCall(TSSetSNES(t, snes_start));
5742 
5743   PetscCall(TSGetDM(tsin, &dm));
5744   PetscCall(TSSetDM(t, dm));
5745 
5746   t->adapt = tsin->adapt;
5747   PetscCall(PetscObjectReference((PetscObject)t->adapt));
5748 
5749   t->trajectory = tsin->trajectory;
5750   PetscCall(PetscObjectReference((PetscObject)t->trajectory));
5751 
5752   t->event = tsin->event;
5753   if (t->event) t->event->refct++;
5754 
5755   t->problem_type      = tsin->problem_type;
5756   t->ptime             = tsin->ptime;
5757   t->ptime_prev        = tsin->ptime_prev;
5758   t->time_step         = tsin->time_step;
5759   t->max_time          = tsin->max_time;
5760   t->steps             = tsin->steps;
5761   t->max_steps         = tsin->max_steps;
5762   t->equation_type     = tsin->equation_type;
5763   t->atol              = tsin->atol;
5764   t->rtol              = tsin->rtol;
5765   t->max_snes_failures = tsin->max_snes_failures;
5766   t->max_reject        = tsin->max_reject;
5767   t->errorifstepfailed = tsin->errorifstepfailed;
5768 
5769   PetscCall(TSGetType(tsin, &type));
5770   PetscCall(TSSetType(t, type));
5771 
5772   t->vec_sol = NULL;
5773 
5774   t->cfltime          = tsin->cfltime;
5775   t->cfltime_local    = tsin->cfltime_local;
5776   t->exact_final_time = tsin->exact_final_time;
5777 
5778   PetscCall(PetscMemcpy(t->ops, tsin->ops, sizeof(struct _TSOps)));
5779 
5780   if (((PetscObject)tsin)->fortran_func_pointers) {
5781     PetscInt i;
5782     PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers));
5783     for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
5784   }
5785   *tsout = t;
5786   PetscFunctionReturn(0);
5787 }
5788 
5789 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y) {
5790   TS ts = (TS)ctx;
5791 
5792   PetscFunctionBegin;
5793   PetscCall(TSComputeRHSFunction(ts, 0, x, y));
5794   PetscFunctionReturn(0);
5795 }
5796 
5797 /*@
5798     TSRHSJacobianTest - Compares the multiply routine provided to the MATSHELL with differencing on the TS given RHS function.
5799 
5800    Logically Collective on TS
5801 
5802     Input Parameters:
5803     TS - the time stepping routine
5804 
5805    Output Parameter:
5806 .   flg - PETSC_TRUE if the multiply is likely correct
5807 
5808    Options Database:
5809  .   -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
5810 
5811    Level: advanced
5812 
5813    Notes:
5814     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
5815 
5816 .seealso: `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()`
5817 @*/
5818 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg) {
5819   Mat           J, B;
5820   TSRHSJacobian func;
5821   void         *ctx;
5822 
5823   PetscFunctionBegin;
5824   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5825   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5826   PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5827   PetscFunctionReturn(0);
5828 }
5829 
5830 /*@C
5831     TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the MATSHELL with differencing on the TS given RHS function.
5832 
5833    Logically Collective on TS
5834 
5835     Input Parameters:
5836     TS - the time stepping routine
5837 
5838    Output Parameter:
5839 .   flg - PETSC_TRUE if the multiply is likely correct
5840 
5841    Options Database:
5842 .   -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
5843 
5844    Notes:
5845     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
5846 
5847    Level: advanced
5848 
5849 .seealso: `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()`
5850 @*/
5851 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg) {
5852   Mat           J, B;
5853   void         *ctx;
5854   TSRHSJacobian func;
5855 
5856   PetscFunctionBegin;
5857   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5858   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5859   PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5860   PetscFunctionReturn(0);
5861 }
5862 
5863 /*@
5864   TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used.
5865 
5866   Logically collective
5867 
5868   Input Parameters:
5869 +  ts - timestepping context
5870 -  use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used
5871 
5872   Options Database:
5873 .   -ts_use_splitrhsfunction - <true,false>
5874 
5875   Notes:
5876     This is only useful for multirate methods
5877 
5878   Level: intermediate
5879 
5880 .seealso: `TSGetUseSplitRHSFunction()`
5881 @*/
5882 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction) {
5883   PetscFunctionBegin;
5884   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5885   ts->use_splitrhsfunction = use_splitrhsfunction;
5886   PetscFunctionReturn(0);
5887 }
5888 
5889 /*@
5890   TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used.
5891 
5892   Not collective
5893 
5894   Input Parameter:
5895 .  ts - timestepping context
5896 
5897   Output Parameter:
5898 .  use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used
5899 
5900   Level: intermediate
5901 
5902 .seealso: `TSSetUseSplitRHSFunction()`
5903 @*/
5904 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction) {
5905   PetscFunctionBegin;
5906   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5907   *use_splitrhsfunction = ts->use_splitrhsfunction;
5908   PetscFunctionReturn(0);
5909 }
5910 
5911 /*@
5912     TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix.
5913 
5914    Logically  Collective on ts
5915 
5916    Input Parameters:
5917 +  ts - the time-stepper
5918 -  str - the structure (the default is UNKNOWN_NONZERO_PATTERN)
5919 
5920    Level: intermediate
5921 
5922    Notes:
5923      When the relationship between the nonzero structures is known and supplied the solution process can be much faster
5924 
5925 .seealso: `MatAXPY()`, `MatStructure`
5926  @*/
5927 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str) {
5928   PetscFunctionBegin;
5929   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5930   ts->axpy_pattern = str;
5931   PetscFunctionReturn(0);
5932 }
5933 
5934 /*@
5935   TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested.
5936 
5937   Collective on ts
5938 
5939   Input Parameters:
5940 + ts - the time-stepper
5941 . n - number of the time points (>=2)
5942 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively.
5943 
5944   Options Database Keys:
5945 . -ts_time_span <t0,...tf> - Sets the time span
5946 
5947   Level: beginner
5948 
5949   Notes:
5950   The elements in tspan must be all increasing. They correspond to the intermediate points for time integration.
5951   TS_EXACTFINALTIME_MATCHSTEP must be used to make the last time step in each sub-interval match the intermediate points specified.
5952   The intermediate solutions are saved in a vector array that can be accessed with TSGetSolutions(). Thus using time span may
5953   pressure the memory system when using a large number of span points.
5954 
5955 .seealso: `TSGetTimeSpan()`, `TSGetSolutions()`
5956  @*/
5957 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times) {
5958   PetscFunctionBegin;
5959   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5960   PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n);
5961   if (ts->tspan && n != ts->tspan->num_span_times) {
5962     PetscCall(PetscFree(ts->tspan->span_times));
5963     PetscCall(VecDestroyVecs(ts->tspan->num_span_times, &ts->tspan->vecs_sol));
5964     PetscCall(PetscMalloc1(n, &ts->tspan->span_times));
5965   }
5966   if (!ts->tspan) {
5967     TSTimeSpan tspan;
5968     PetscCall(PetscNew(&tspan));
5969     PetscCall(PetscMalloc1(n, &tspan->span_times));
5970     tspan->reltol = 1e-6;
5971     tspan->abstol = 10 * PETSC_MACHINE_EPSILON;
5972     ts->tspan     = tspan;
5973   }
5974   ts->tspan->num_span_times = n;
5975   PetscCall(PetscArraycpy(ts->tspan->span_times, span_times, n));
5976   PetscCall(TSSetTime(ts, ts->tspan->span_times[0]));
5977   PetscCall(TSSetMaxTime(ts, ts->tspan->span_times[n - 1]));
5978   PetscFunctionReturn(0);
5979 }
5980 
5981 /*@C
5982   TSGetTimeSpan - gets the time span.
5983 
5984   Not Collective
5985 
5986   Input Parameter:
5987 . ts - the time-stepper
5988 
5989   Output Parameters:
5990 + n - number of the time points (>=2)
5991 - 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.
5992 
5993   Level: beginner
5994   Notes: Both n and span_times can be NULL.
5995 
5996 .seealso: `TSSetTimeSpan()`, `TSGetSolutions()`
5997  @*/
5998 PetscErrorCode TSGetTimeSpan(TS ts, PetscInt *n, const PetscReal **span_times) {
5999   PetscFunctionBegin;
6000   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
6001   if (n) PetscValidIntPointer(n, 2);
6002   if (span_times) PetscValidPointer(span_times, 3);
6003   if (!ts->tspan) {
6004     if (n) *n = 0;
6005     if (span_times) *span_times = NULL;
6006   } else {
6007     if (n) *n = ts->tspan->num_span_times;
6008     if (span_times) *span_times = ts->tspan->span_times;
6009   }
6010   PetscFunctionReturn(0);
6011 }
6012 
6013 /*@
6014    TSGetTimeSpanSolutions - Get the number of solutions and the solutions at the time points specified by the time span.
6015 
6016    Input Parameter:
6017 .  ts - the TS context obtained from TSCreate()
6018 
6019    Output Parameters:
6020 +  nsol - the number of solutions
6021 -  Sols - the solution vectors
6022 
6023    Level: beginner
6024 
6025    Notes:
6026     Both nsol and Sols can be NULL.
6027     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.
6028 
6029 .seealso: `TSSetTimeSpan()`
6030 @*/
6031 PetscErrorCode TSGetTimeSpanSolutions(TS ts, PetscInt *nsol, Vec **Sols) {
6032   PetscFunctionBegin;
6033   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
6034   if (nsol) PetscValidIntPointer(nsol, 2);
6035   if (Sols) PetscValidPointer(Sols, 3);
6036   if (!ts->tspan) {
6037     if (nsol) *nsol = 0;
6038     if (Sols) *Sols = NULL;
6039   } else {
6040     if (nsol) *nsol = ts->tspan->spanctr;
6041     if (Sols) *Sols = ts->tspan->vecs_sol;
6042   }
6043   PetscFunctionReturn(0);
6044 }
6045