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