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