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