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