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