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