xref: /petsc/src/ts/interface/ts.c (revision f0b74427b291237450348b8514d67555ad08bce6)
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 prototype 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()`, `TSSetPostStep()`
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 .seealso: [](ch_ts), `TS`, `TSAppendOptionsPrefix()`, `TSSetFromOptions()`
4324 @*/
4325 PetscErrorCode TSGetOptionsPrefix(TS ts, const char *prefix[])
4326 {
4327   PetscFunctionBegin;
4328   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4329   PetscAssertPointer(prefix, 2);
4330   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts, prefix));
4331   PetscFunctionReturn(PETSC_SUCCESS);
4332 }
4333 
4334 /*@C
4335   TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4336 
4337   Not Collective, but parallel objects are returned if ts is parallel
4338 
4339   Input Parameter:
4340 . ts - The `TS` context obtained from `TSCreate()`
4341 
4342   Output Parameters:
4343 + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or `NULL`)
4344 . Pmat - The matrix from which the preconditioner is constructed, usually the same as `Amat`  (or `NULL`)
4345 . func - Function to compute the Jacobian of the RHS  (or `NULL`)
4346 - ctx  - User-defined context for Jacobian evaluation routine  (or `NULL`)
4347 
4348   Level: intermediate
4349 
4350   Note:
4351   You can pass in `NULL` for any return argument you do not need.
4352 
4353 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4354 
4355 @*/
4356 PetscErrorCode TSGetRHSJacobian(TS ts, Mat *Amat, Mat *Pmat, TSRHSJacobianFn **func, void **ctx)
4357 {
4358   DM dm;
4359 
4360   PetscFunctionBegin;
4361   if (Amat || Pmat) {
4362     SNES snes;
4363     PetscCall(TSGetSNES(ts, &snes));
4364     PetscCall(SNESSetUpMatrices(snes));
4365     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4366   }
4367   PetscCall(TSGetDM(ts, &dm));
4368   PetscCall(DMTSGetRHSJacobian(dm, func, ctx));
4369   PetscFunctionReturn(PETSC_SUCCESS);
4370 }
4371 
4372 /*@C
4373   TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4374 
4375   Not Collective, but parallel objects are returned if ts is parallel
4376 
4377   Input Parameter:
4378 . ts - The `TS` context obtained from `TSCreate()`
4379 
4380   Output Parameters:
4381 + Amat - The (approximate) Jacobian of F(t,U,U_t)
4382 . Pmat - The matrix from which the preconditioner is constructed, often the same as `Amat`
4383 . f    - The function to compute the matrices
4384 - ctx  - User-defined context for Jacobian evaluation routine
4385 
4386   Level: advanced
4387 
4388   Note:
4389   You can pass in `NULL` for any return argument you do not need.
4390 
4391 .seealso: [](ch_ts), `TS`, `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4392 @*/
4393 PetscErrorCode TSGetIJacobian(TS ts, Mat *Amat, Mat *Pmat, TSIJacobianFn **f, void **ctx)
4394 {
4395   DM dm;
4396 
4397   PetscFunctionBegin;
4398   if (Amat || Pmat) {
4399     SNES snes;
4400     PetscCall(TSGetSNES(ts, &snes));
4401     PetscCall(SNESSetUpMatrices(snes));
4402     PetscCall(SNESGetJacobian(snes, Amat, Pmat, NULL, NULL));
4403   }
4404   PetscCall(TSGetDM(ts, &dm));
4405   PetscCall(DMTSGetIJacobian(dm, f, ctx));
4406   PetscFunctionReturn(PETSC_SUCCESS);
4407 }
4408 
4409 #include <petsc/private/dmimpl.h>
4410 /*@
4411   TSSetDM - Sets the `DM` that may be used by some nonlinear solvers or preconditioners under the `TS`
4412 
4413   Logically Collective
4414 
4415   Input Parameters:
4416 + ts - the `TS` integrator object
4417 - dm - the dm, cannot be `NULL`
4418 
4419   Level: intermediate
4420 
4421   Notes:
4422   A `DM` can only be used for solving one problem at a time because information about the problem is stored on the `DM`,
4423   even when not using interfaces like `DMTSSetIFunction()`.  Use `DMClone()` to get a distinct `DM` when solving
4424   different problems using the same function space.
4425 
4426 .seealso: [](ch_ts), `TS`, `DM`, `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()`
4427 @*/
4428 PetscErrorCode TSSetDM(TS ts, DM dm)
4429 {
4430   SNES snes;
4431   DMTS tsdm;
4432 
4433   PetscFunctionBegin;
4434   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4435   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
4436   PetscCall(PetscObjectReference((PetscObject)dm));
4437   if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */
4438     if (ts->dm->dmts && !dm->dmts) {
4439       PetscCall(DMCopyDMTS(ts->dm, dm));
4440       PetscCall(DMGetDMTS(ts->dm, &tsdm));
4441       /* Grant write privileges to the replacement DM */
4442       if (tsdm->originaldm == ts->dm) tsdm->originaldm = dm;
4443     }
4444     PetscCall(DMDestroy(&ts->dm));
4445   }
4446   ts->dm = dm;
4447 
4448   PetscCall(TSGetSNES(ts, &snes));
4449   PetscCall(SNESSetDM(snes, dm));
4450   PetscFunctionReturn(PETSC_SUCCESS);
4451 }
4452 
4453 /*@
4454   TSGetDM - Gets the `DM` that may be used by some preconditioners
4455 
4456   Not Collective
4457 
4458   Input Parameter:
4459 . ts - the `TS`
4460 
4461   Output Parameter:
4462 . dm - the `DM`
4463 
4464   Level: intermediate
4465 
4466 .seealso: [](ch_ts), `TS`, `DM`, `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()`
4467 @*/
4468 PetscErrorCode TSGetDM(TS ts, DM *dm)
4469 {
4470   PetscFunctionBegin;
4471   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4472   if (!ts->dm) {
4473     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts), &ts->dm));
4474     if (ts->snes) PetscCall(SNESSetDM(ts->snes, ts->dm));
4475   }
4476   *dm = ts->dm;
4477   PetscFunctionReturn(PETSC_SUCCESS);
4478 }
4479 
4480 /*@
4481   SNESTSFormFunction - Function to evaluate nonlinear residual
4482 
4483   Logically Collective
4484 
4485   Input Parameters:
4486 + snes - nonlinear solver
4487 . U    - the current state at which to evaluate the residual
4488 - ctx  - user context, must be a TS
4489 
4490   Output Parameter:
4491 . F - the nonlinear residual
4492 
4493   Level: advanced
4494 
4495   Note:
4496   This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.
4497   It is most frequently passed to `MatFDColoringSetFunction()`.
4498 
4499 .seealso: [](ch_ts), `SNESSetFunction()`, `MatFDColoringSetFunction()`
4500 @*/
4501 PetscErrorCode SNESTSFormFunction(SNES snes, Vec U, Vec F, void *ctx)
4502 {
4503   TS ts = (TS)ctx;
4504 
4505   PetscFunctionBegin;
4506   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4507   PetscValidHeaderSpecific(U, VEC_CLASSID, 2);
4508   PetscValidHeaderSpecific(F, VEC_CLASSID, 3);
4509   PetscValidHeaderSpecific(ts, TS_CLASSID, 4);
4510   PetscCheck(ts->ops->snesfunction, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesfunction for TS of type %s", ((PetscObject)ts)->type_name);
4511   PetscCall((*ts->ops->snesfunction)(snes, U, F, ts));
4512   PetscFunctionReturn(PETSC_SUCCESS);
4513 }
4514 
4515 /*@
4516   SNESTSFormJacobian - Function to evaluate the Jacobian
4517 
4518   Collective
4519 
4520   Input Parameters:
4521 + snes - nonlinear solver
4522 . U    - the current state at which to evaluate the residual
4523 - ctx  - user context, must be a `TS`
4524 
4525   Output Parameters:
4526 + A - the Jacobian
4527 - B - the preconditioning matrix (may be the same as A)
4528 
4529   Level: developer
4530 
4531   Note:
4532   This function is not normally called by users and is automatically registered with the `SNES` used by `TS`.
4533 
4534 .seealso: [](ch_ts), `SNESSetJacobian()`
4535 @*/
4536 PetscErrorCode SNESTSFormJacobian(SNES snes, Vec U, Mat A, Mat B, void *ctx)
4537 {
4538   TS ts = (TS)ctx;
4539 
4540   PetscFunctionBegin;
4541   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
4542   PetscValidHeaderSpecific(U, VEC_CLASSID, 2);
4543   PetscValidHeaderSpecific(A, MAT_CLASSID, 3);
4544   PetscValidHeaderSpecific(B, MAT_CLASSID, 4);
4545   PetscValidHeaderSpecific(ts, TS_CLASSID, 5);
4546   PetscCheck(ts->ops->snesjacobian, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "No method snesjacobian for TS of type %s", ((PetscObject)ts)->type_name);
4547   PetscCall((*ts->ops->snesjacobian)(snes, U, A, B, ts));
4548   PetscFunctionReturn(PETSC_SUCCESS);
4549 }
4550 
4551 /*@C
4552   TSComputeRHSFunctionLinear - Evaluate the right-hand side via the user-provided Jacobian, for linear problems Udot = A U only
4553 
4554   Collective
4555 
4556   Input Parameters:
4557 + ts  - time stepping context
4558 . t   - time at which to evaluate
4559 . U   - state at which to evaluate
4560 - ctx - context
4561 
4562   Output Parameter:
4563 . F - right-hand side
4564 
4565   Level: intermediate
4566 
4567   Note:
4568   This function is intended to be passed to `TSSetRHSFunction()` to evaluate the right-hand side for linear problems.
4569   The matrix (and optionally the evaluation context) should be passed to `TSSetRHSJacobian()`.
4570 
4571 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
4572 @*/
4573 PetscErrorCode TSComputeRHSFunctionLinear(TS ts, PetscReal t, Vec U, Vec F, void *ctx)
4574 {
4575   Mat Arhs, Brhs;
4576 
4577   PetscFunctionBegin;
4578   PetscCall(TSGetRHSMats_Private(ts, &Arhs, &Brhs));
4579   /* undo the damage caused by shifting */
4580   PetscCall(TSRecoverRHSJacobian(ts, Arhs, Brhs));
4581   PetscCall(TSComputeRHSJacobian(ts, t, U, Arhs, Brhs));
4582   PetscCall(MatMult(Arhs, U, F));
4583   PetscFunctionReturn(PETSC_SUCCESS);
4584 }
4585 
4586 /*@C
4587   TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
4588 
4589   Collective
4590 
4591   Input Parameters:
4592 + ts  - time stepping context
4593 . t   - time at which to evaluate
4594 . U   - state at which to evaluate
4595 - ctx - context
4596 
4597   Output Parameters:
4598 + A - pointer to operator
4599 - B - pointer to preconditioning matrix
4600 
4601   Level: intermediate
4602 
4603   Note:
4604   This function is intended to be passed to `TSSetRHSJacobian()` to evaluate the Jacobian for linear time-independent problems.
4605 
4606 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()`
4607 @*/
4608 PetscErrorCode TSComputeRHSJacobianConstant(TS ts, PetscReal t, Vec U, Mat A, Mat B, void *ctx)
4609 {
4610   PetscFunctionBegin;
4611   PetscFunctionReturn(PETSC_SUCCESS);
4612 }
4613 
4614 /*@C
4615   TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
4616 
4617   Collective
4618 
4619   Input Parameters:
4620 + ts   - time stepping context
4621 . t    - time at which to evaluate
4622 . U    - state at which to evaluate
4623 . Udot - time derivative of state vector
4624 - ctx  - context
4625 
4626   Output Parameter:
4627 . F - left hand side
4628 
4629   Level: intermediate
4630 
4631   Notes:
4632   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
4633   user is required to write their own `TSComputeIFunction()`.
4634   This function is intended to be passed to `TSSetIFunction()` to evaluate the left hand side for linear problems.
4635   The matrix (and optionally the evaluation context) should be passed to `TSSetIJacobian()`.
4636 
4637   Note that using this function is NOT equivalent to using `TSComputeRHSFunctionLinear()` since that solves Udot = A U
4638 
4639 .seealso: [](ch_ts), `TS`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()`
4640 @*/
4641 PetscErrorCode TSComputeIFunctionLinear(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, void *ctx)
4642 {
4643   Mat A, B;
4644 
4645   PetscFunctionBegin;
4646   PetscCall(TSGetIJacobian(ts, &A, &B, NULL, NULL));
4647   PetscCall(TSComputeIJacobian(ts, t, U, Udot, 1.0, A, B, PETSC_TRUE));
4648   PetscCall(MatMult(A, Udot, F));
4649   PetscFunctionReturn(PETSC_SUCCESS);
4650 }
4651 
4652 /*@C
4653   TSComputeIJacobianConstant - Reuses the matrix previously computed with the provided `TSIJacobianFn` for a semi-implicit DAE or ODE
4654 
4655   Collective
4656 
4657   Input Parameters:
4658 + ts    - time stepping context
4659 . t     - time at which to evaluate
4660 . U     - state at which to evaluate
4661 . Udot  - time derivative of state vector
4662 . shift - shift to apply
4663 - ctx   - context
4664 
4665   Output Parameters:
4666 + A - pointer to operator
4667 - B - pointer to matrix from which the preconditioner is built (often `A`)
4668 
4669   Level: advanced
4670 
4671   Notes:
4672   This function is intended to be passed to `TSSetIJacobian()` to evaluate the Jacobian for linear time-independent problems.
4673 
4674   It is only appropriate for problems of the form
4675 
4676   $$
4677   M \dot{U} = F(U,t)
4678   $$
4679 
4680   where M is constant and F is non-stiff.  The user must pass M to `TSSetIJacobian()`.  The current implementation only
4681   works with IMEX time integration methods such as `TSROSW` and `TSARKIMEX`, since there is no support for de-constructing
4682   an implicit operator of the form
4683 
4684   $$
4685   shift*M + J
4686   $$
4687 
4688   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
4689   a copy of M or reassemble it when requested.
4690 
4691 .seealso: [](ch_ts), `TS`, `TSROSW`, `TSARKIMEX`, `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()`
4692 @*/
4693 PetscErrorCode TSComputeIJacobianConstant(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat A, Mat B, void *ctx)
4694 {
4695   PetscFunctionBegin;
4696   PetscCall(MatScale(A, shift / ts->ijacobian.shift));
4697   ts->ijacobian.shift = shift;
4698   PetscFunctionReturn(PETSC_SUCCESS);
4699 }
4700 
4701 /*@
4702   TSGetEquationType - Gets the type of the equation that `TS` is solving.
4703 
4704   Not Collective
4705 
4706   Input Parameter:
4707 . ts - the `TS` context
4708 
4709   Output Parameter:
4710 . equation_type - see `TSEquationType`
4711 
4712   Level: beginner
4713 
4714 .seealso: [](ch_ts), `TS`, `TSSetEquationType()`, `TSEquationType`
4715 @*/
4716 PetscErrorCode TSGetEquationType(TS ts, TSEquationType *equation_type)
4717 {
4718   PetscFunctionBegin;
4719   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4720   PetscAssertPointer(equation_type, 2);
4721   *equation_type = ts->equation_type;
4722   PetscFunctionReturn(PETSC_SUCCESS);
4723 }
4724 
4725 /*@
4726   TSSetEquationType - Sets the type of the equation that `TS` is solving.
4727 
4728   Not Collective
4729 
4730   Input Parameters:
4731 + ts            - the `TS` context
4732 - equation_type - see `TSEquationType`
4733 
4734   Level: advanced
4735 
4736 .seealso: [](ch_ts), `TS`, `TSGetEquationType()`, `TSEquationType`
4737 @*/
4738 PetscErrorCode TSSetEquationType(TS ts, TSEquationType equation_type)
4739 {
4740   PetscFunctionBegin;
4741   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4742   ts->equation_type = equation_type;
4743   PetscFunctionReturn(PETSC_SUCCESS);
4744 }
4745 
4746 /*@
4747   TSGetConvergedReason - Gets the reason the `TS` iteration was stopped.
4748 
4749   Not Collective
4750 
4751   Input Parameter:
4752 . ts - the `TS` context
4753 
4754   Output Parameter:
4755 . reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4756             manual pages for the individual convergence tests for complete lists
4757 
4758   Level: beginner
4759 
4760   Note:
4761   Can only be called after the call to `TSSolve()` is complete.
4762 
4763 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4764 @*/
4765 PetscErrorCode TSGetConvergedReason(TS ts, TSConvergedReason *reason)
4766 {
4767   PetscFunctionBegin;
4768   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4769   PetscAssertPointer(reason, 2);
4770   *reason = ts->reason;
4771   PetscFunctionReturn(PETSC_SUCCESS);
4772 }
4773 
4774 /*@
4775   TSSetConvergedReason - Sets the reason for handling the convergence of `TSSolve()`.
4776 
4777   Logically Collective; reason must contain common value
4778 
4779   Input Parameters:
4780 + ts     - the `TS` context
4781 - reason - negative value indicates diverged, positive value converged, see `TSConvergedReason` or the
4782             manual pages for the individual convergence tests for complete lists
4783 
4784   Level: advanced
4785 
4786   Note:
4787   Can only be called while `TSSolve()` is active.
4788 
4789 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4790 @*/
4791 PetscErrorCode TSSetConvergedReason(TS ts, TSConvergedReason reason)
4792 {
4793   PetscFunctionBegin;
4794   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4795   ts->reason = reason;
4796   PetscFunctionReturn(PETSC_SUCCESS);
4797 }
4798 
4799 /*@
4800   TSGetSolveTime - Gets the time after a call to `TSSolve()`
4801 
4802   Not Collective
4803 
4804   Input Parameter:
4805 . ts - the `TS` context
4806 
4807   Output Parameter:
4808 . ftime - the final time. This time corresponds to the final time set with `TSSetMaxTime()`
4809 
4810   Level: beginner
4811 
4812   Note:
4813   Can only be called after the call to `TSSolve()` is complete.
4814 
4815 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSConvergedReason`
4816 @*/
4817 PetscErrorCode TSGetSolveTime(TS ts, PetscReal *ftime)
4818 {
4819   PetscFunctionBegin;
4820   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4821   PetscAssertPointer(ftime, 2);
4822   *ftime = ts->solvetime;
4823   PetscFunctionReturn(PETSC_SUCCESS);
4824 }
4825 
4826 /*@
4827   TSGetSNESIterations - Gets the total number of nonlinear iterations
4828   used by the time integrator.
4829 
4830   Not Collective
4831 
4832   Input Parameter:
4833 . ts - `TS` context
4834 
4835   Output Parameter:
4836 . nits - number of nonlinear iterations
4837 
4838   Level: intermediate
4839 
4840   Note:
4841   This counter is reset to zero for each successive call to `TSSolve()`.
4842 
4843 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetKSPIterations()`
4844 @*/
4845 PetscErrorCode TSGetSNESIterations(TS ts, PetscInt *nits)
4846 {
4847   PetscFunctionBegin;
4848   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4849   PetscAssertPointer(nits, 2);
4850   *nits = ts->snes_its;
4851   PetscFunctionReturn(PETSC_SUCCESS);
4852 }
4853 
4854 /*@
4855   TSGetKSPIterations - Gets the total number of linear iterations
4856   used by the time integrator.
4857 
4858   Not Collective
4859 
4860   Input Parameter:
4861 . ts - `TS` context
4862 
4863   Output Parameter:
4864 . lits - number of linear iterations
4865 
4866   Level: intermediate
4867 
4868   Note:
4869   This counter is reset to zero for each successive call to `TSSolve()`.
4870 
4871 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`
4872 @*/
4873 PetscErrorCode TSGetKSPIterations(TS ts, PetscInt *lits)
4874 {
4875   PetscFunctionBegin;
4876   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4877   PetscAssertPointer(lits, 2);
4878   *lits = ts->ksp_its;
4879   PetscFunctionReturn(PETSC_SUCCESS);
4880 }
4881 
4882 /*@
4883   TSGetStepRejections - Gets the total number of rejected steps.
4884 
4885   Not Collective
4886 
4887   Input Parameter:
4888 . ts - `TS` context
4889 
4890   Output Parameter:
4891 . rejects - number of steps rejected
4892 
4893   Level: intermediate
4894 
4895   Note:
4896   This counter is reset to zero for each successive call to `TSSolve()`.
4897 
4898 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()`
4899 @*/
4900 PetscErrorCode TSGetStepRejections(TS ts, PetscInt *rejects)
4901 {
4902   PetscFunctionBegin;
4903   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4904   PetscAssertPointer(rejects, 2);
4905   *rejects = ts->reject;
4906   PetscFunctionReturn(PETSC_SUCCESS);
4907 }
4908 
4909 /*@
4910   TSGetSNESFailures - Gets the total number of failed `SNES` solves in a `TS`
4911 
4912   Not Collective
4913 
4914   Input Parameter:
4915 . ts - `TS` context
4916 
4917   Output Parameter:
4918 . fails - number of failed nonlinear solves
4919 
4920   Level: intermediate
4921 
4922   Note:
4923   This counter is reset to zero for each successive call to `TSSolve()`.
4924 
4925 .seealso: [](ch_ts), `TS`, `TSSolve()`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()`
4926 @*/
4927 PetscErrorCode TSGetSNESFailures(TS ts, PetscInt *fails)
4928 {
4929   PetscFunctionBegin;
4930   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4931   PetscAssertPointer(fails, 2);
4932   *fails = ts->num_snes_failures;
4933   PetscFunctionReturn(PETSC_SUCCESS);
4934 }
4935 
4936 /*@
4937   TSSetMaxStepRejections - Sets the maximum number of step rejections before a time step fails
4938 
4939   Not Collective
4940 
4941   Input Parameters:
4942 + ts      - `TS` context
4943 - rejects - maximum number of rejected steps, pass `PETSC_UNLIMITED` for unlimited
4944 
4945   Options Database Key:
4946 . -ts_max_reject - Maximum number of step rejections before a step fails
4947 
4948   Level: intermediate
4949 
4950   Developer Note:
4951   The options database name is incorrect.
4952 
4953 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()`
4954 @*/
4955 PetscErrorCode TSSetMaxStepRejections(TS ts, PetscInt rejects)
4956 {
4957   PetscFunctionBegin;
4958   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4959   if (rejects == PETSC_UNLIMITED || rejects == -1) {
4960     ts->max_reject = PETSC_UNLIMITED;
4961   } else {
4962     PetscCheck(rejects >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of rejections");
4963     ts->max_reject = rejects;
4964   }
4965   PetscFunctionReturn(PETSC_SUCCESS);
4966 }
4967 
4968 /*@
4969   TSSetMaxSNESFailures - Sets the maximum number of failed `SNES` solves
4970 
4971   Not Collective
4972 
4973   Input Parameters:
4974 + ts    - `TS` context
4975 - fails - maximum number of failed nonlinear solves, pass `PETSC_UNLIMITED` to allow any number of failures.
4976 
4977   Options Database Key:
4978 . -ts_max_snes_failures - Maximum number of nonlinear solve failures
4979 
4980   Level: intermediate
4981 
4982 .seealso: [](ch_ts), `TS`, `SNES`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()`
4983 @*/
4984 PetscErrorCode TSSetMaxSNESFailures(TS ts, PetscInt fails)
4985 {
4986   PetscFunctionBegin;
4987   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
4988   if (fails == PETSC_UNLIMITED || fails == -1) {
4989     ts->max_snes_failures = PETSC_UNLIMITED;
4990   } else {
4991     PetscCheck(fails >= 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a negative maximum number of failures");
4992     ts->max_snes_failures = fails;
4993   }
4994   PetscFunctionReturn(PETSC_SUCCESS);
4995 }
4996 
4997 /*@
4998   TSSetErrorIfStepFails - Immediately error if no step succeeds during `TSSolve()`
4999 
5000   Not Collective
5001 
5002   Input Parameters:
5003 + ts  - `TS` context
5004 - err - `PETSC_TRUE` to error if no step succeeds, `PETSC_FALSE` to return without failure
5005 
5006   Options Database Key:
5007 . -ts_error_if_step_fails - Error if no step succeeds
5008 
5009   Level: intermediate
5010 
5011 .seealso: [](ch_ts), `TS`, `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSGetConvergedReason()`
5012 @*/
5013 PetscErrorCode TSSetErrorIfStepFails(TS ts, PetscBool err)
5014 {
5015   PetscFunctionBegin;
5016   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5017   ts->errorifstepfailed = err;
5018   PetscFunctionReturn(PETSC_SUCCESS);
5019 }
5020 
5021 /*@
5022   TSGetAdapt - Get the adaptive controller context for the current method
5023 
5024   Collective if controller has not yet been created
5025 
5026   Input Parameter:
5027 . ts - time stepping context
5028 
5029   Output Parameter:
5030 . adapt - adaptive controller
5031 
5032   Level: intermediate
5033 
5034 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()`
5035 @*/
5036 PetscErrorCode TSGetAdapt(TS ts, TSAdapt *adapt)
5037 {
5038   PetscFunctionBegin;
5039   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5040   PetscAssertPointer(adapt, 2);
5041   if (!ts->adapt) {
5042     PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts), &ts->adapt));
5043     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt, (PetscObject)ts, 1));
5044   }
5045   *adapt = ts->adapt;
5046   PetscFunctionReturn(PETSC_SUCCESS);
5047 }
5048 
5049 /*@
5050   TSSetTolerances - Set tolerances for local truncation error when using an adaptive controller
5051 
5052   Logically Collective
5053 
5054   Input Parameters:
5055 + ts    - time integration context
5056 . atol  - scalar absolute tolerances
5057 . vatol - vector of absolute tolerances or `NULL`, used in preference to `atol` if present
5058 . rtol  - scalar relative tolerances
5059 - vrtol - vector of relative tolerances or `NULL`, used in preference to `rtol` if present
5060 
5061   Options Database Keys:
5062 + -ts_rtol <rtol> - relative tolerance for local truncation error
5063 - -ts_atol <atol> - Absolute tolerance for local truncation error
5064 
5065   Level: beginner
5066 
5067   Notes:
5068   `PETSC_CURRENT` or `PETSC_DETERMINE` may be used for `atol` or `rtol` to indicate the current value
5069   or the default value from when the object's type was set.
5070 
5071   With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5072   (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5073   computed only for the differential or the algebraic part then this can be done using the vector of
5074   tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5075   differential part and infinity for the algebraic part, the LTE calculation will include only the
5076   differential variables.
5077 
5078   Fortran Note:
5079   Use `PETSC_CURRENT_INTEGER` or `PETSC_DETERMINE_INTEGER`.
5080 
5081 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()`
5082 @*/
5083 PetscErrorCode TSSetTolerances(TS ts, PetscReal atol, Vec vatol, PetscReal rtol, Vec vrtol)
5084 {
5085   PetscFunctionBegin;
5086   if (atol == (PetscReal)PETSC_DETERMINE) {
5087     ts->atol = ts->default_atol;
5088   } else if (atol != (PetscReal)PETSC_CURRENT) {
5089     PetscCheck(atol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g must be non-negative", (double)atol);
5090     ts->atol = atol;
5091   }
5092 
5093   if (vatol) {
5094     PetscCall(PetscObjectReference((PetscObject)vatol));
5095     PetscCall(VecDestroy(&ts->vatol));
5096     ts->vatol = vatol;
5097   }
5098 
5099   if (rtol == (PetscReal)PETSC_DETERMINE) {
5100     ts->rtol = ts->default_rtol;
5101   } else if (rtol != (PetscReal)PETSC_CURRENT) {
5102     PetscCheck(rtol >= 0.0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_OUTOFRANGE, "Relative tolerance %g must be non-negative", (double)rtol);
5103     ts->rtol = rtol;
5104   }
5105 
5106   if (vrtol) {
5107     PetscCall(PetscObjectReference((PetscObject)vrtol));
5108     PetscCall(VecDestroy(&ts->vrtol));
5109     ts->vrtol = vrtol;
5110   }
5111   PetscFunctionReturn(PETSC_SUCCESS);
5112 }
5113 
5114 /*@
5115   TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
5116 
5117   Logically Collective
5118 
5119   Input Parameter:
5120 . ts - time integration context
5121 
5122   Output Parameters:
5123 + atol  - scalar absolute tolerances, `NULL` to ignore
5124 . vatol - vector of absolute tolerances, `NULL` to ignore
5125 . rtol  - scalar relative tolerances, `NULL` to ignore
5126 - vrtol - vector of relative tolerances, `NULL` to ignore
5127 
5128   Level: beginner
5129 
5130 .seealso: [](ch_ts), `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()`
5131 @*/
5132 PetscErrorCode TSGetTolerances(TS ts, PetscReal *atol, Vec *vatol, PetscReal *rtol, Vec *vrtol)
5133 {
5134   PetscFunctionBegin;
5135   if (atol) *atol = ts->atol;
5136   if (vatol) *vatol = ts->vatol;
5137   if (rtol) *rtol = ts->rtol;
5138   if (vrtol) *vrtol = ts->vrtol;
5139   PetscFunctionReturn(PETSC_SUCCESS);
5140 }
5141 
5142 /*@
5143   TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
5144 
5145   Collective
5146 
5147   Input Parameters:
5148 + ts        - time stepping context
5149 . U         - state vector, usually ts->vec_sol
5150 . Y         - state vector to be compared to U
5151 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
5152 
5153   Output Parameters:
5154 + norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5155 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5156 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5157 
5158   Options Database Key:
5159 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5160 
5161   Level: developer
5162 
5163 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedENorm()`
5164 @*/
5165 PetscErrorCode TSErrorWeightedNorm(TS ts, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5166 {
5167   PetscInt norma_loc, norm_loc, normr_loc;
5168 
5169   PetscFunctionBegin;
5170   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5171   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));
5172   if (wnormtype == NORM_2) {
5173     if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5174     if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5175     if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5176   }
5177   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5178   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5179   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5180   PetscFunctionReturn(PETSC_SUCCESS);
5181 }
5182 
5183 /*@
5184   TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
5185 
5186   Collective
5187 
5188   Input Parameters:
5189 + ts        - time stepping context
5190 . E         - error vector
5191 . U         - state vector, usually ts->vec_sol
5192 . Y         - state vector, previous time step
5193 - wnormtype - norm type, either `NORM_2` or `NORM_INFINITY`
5194 
5195   Output Parameters:
5196 + norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5197 . norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5198 - normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5199 
5200   Options Database Key:
5201 . -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5202 
5203   Level: developer
5204 
5205 .seealso: [](ch_ts), `TS`, `VecErrorWeightedNorms()`, `TSErrorWeightedNorm()`
5206 @*/
5207 PetscErrorCode TSErrorWeightedENorm(TS ts, Vec E, Vec U, Vec Y, NormType wnormtype, PetscReal *norm, PetscReal *norma, PetscReal *normr)
5208 {
5209   PetscInt norma_loc, norm_loc, normr_loc;
5210 
5211   PetscFunctionBegin;
5212   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5213   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));
5214   if (wnormtype == NORM_2) {
5215     if (norm_loc) *norm = PetscSqrtReal(PetscSqr(*norm) / norm_loc);
5216     if (norma_loc) *norma = PetscSqrtReal(PetscSqr(*norma) / norma_loc);
5217     if (normr_loc) *normr = PetscSqrtReal(PetscSqr(*normr) / normr_loc);
5218   }
5219   PetscCheck(!PetscIsInfOrNanScalar(*norm), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norm");
5220   PetscCheck(!PetscIsInfOrNanScalar(*norma), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in norma");
5221   PetscCheck(!PetscIsInfOrNanScalar(*normr), PetscObjectComm((PetscObject)ts), PETSC_ERR_FP, "Infinite or not-a-number generated in normr");
5222   PetscFunctionReturn(PETSC_SUCCESS);
5223 }
5224 
5225 /*@
5226   TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
5227 
5228   Logically Collective
5229 
5230   Input Parameters:
5231 + ts      - time stepping context
5232 - cfltime - maximum stable time step if using forward Euler (value can be different on each process)
5233 
5234   Note:
5235   After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
5236 
5237   Level: intermediate
5238 
5239 .seealso: [](ch_ts), `TSGetCFLTime()`, `TSADAPTCFL`
5240 @*/
5241 PetscErrorCode TSSetCFLTimeLocal(TS ts, PetscReal cfltime)
5242 {
5243   PetscFunctionBegin;
5244   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5245   ts->cfltime_local = cfltime;
5246   ts->cfltime       = -1.;
5247   PetscFunctionReturn(PETSC_SUCCESS);
5248 }
5249 
5250 /*@
5251   TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
5252 
5253   Collective
5254 
5255   Input Parameter:
5256 . ts - time stepping context
5257 
5258   Output Parameter:
5259 . cfltime - maximum stable time step for forward Euler
5260 
5261   Level: advanced
5262 
5263 .seealso: [](ch_ts), `TSSetCFLTimeLocal()`
5264 @*/
5265 PetscErrorCode TSGetCFLTime(TS ts, PetscReal *cfltime)
5266 {
5267   PetscFunctionBegin;
5268   if (ts->cfltime < 0) PetscCallMPI(MPIU_Allreduce(&ts->cfltime_local, &ts->cfltime, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts)));
5269   *cfltime = ts->cfltime;
5270   PetscFunctionReturn(PETSC_SUCCESS);
5271 }
5272 
5273 /*@
5274   TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
5275 
5276   Input Parameters:
5277 + ts - the `TS` context.
5278 . xl - lower bound.
5279 - xu - upper bound.
5280 
5281   Level: advanced
5282 
5283   Note:
5284   If this routine is not called then the lower and upper bounds are set to
5285   `PETSC_NINFINITY` and `PETSC_INFINITY` respectively during `SNESSetUp()`.
5286 
5287 .seealso: [](ch_ts), `TS`
5288 @*/
5289 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
5290 {
5291   SNES snes;
5292 
5293   PetscFunctionBegin;
5294   PetscCall(TSGetSNES(ts, &snes));
5295   PetscCall(SNESVISetVariableBounds(snes, xl, xu));
5296   PetscFunctionReturn(PETSC_SUCCESS);
5297 }
5298 
5299 /*@
5300   TSComputeLinearStability - computes the linear stability function at a point
5301 
5302   Collective
5303 
5304   Input Parameters:
5305 + ts - the `TS` context
5306 . xr - real part of input argument
5307 - xi - imaginary part of input argument
5308 
5309   Output Parameters:
5310 + yr - real part of function value
5311 - yi - imaginary part of function value
5312 
5313   Level: developer
5314 
5315 .seealso: [](ch_ts), `TS`, `TSSetRHSFunction()`, `TSComputeIFunction()`
5316 @*/
5317 PetscErrorCode TSComputeLinearStability(TS ts, PetscReal xr, PetscReal xi, PetscReal *yr, PetscReal *yi)
5318 {
5319   PetscFunctionBegin;
5320   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5321   PetscUseTypeMethod(ts, linearstability, xr, xi, yr, yi);
5322   PetscFunctionReturn(PETSC_SUCCESS);
5323 }
5324 
5325 /*@
5326   TSRestartStep - Flags the solver to restart the next step
5327 
5328   Collective
5329 
5330   Input Parameter:
5331 . ts - the `TS` context obtained from `TSCreate()`
5332 
5333   Level: advanced
5334 
5335   Notes:
5336   Multistep methods like `TSBDF` or Runge-Kutta methods with FSAL property require restarting the solver in the event of
5337   discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
5338   vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
5339   the sake of correctness and maximum safety, users are expected to call `TSRestart()` whenever they introduce
5340   discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
5341   discontinuous source terms).
5342 
5343 .seealso: [](ch_ts), `TS`, `TSBDF`, `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()`
5344 @*/
5345 PetscErrorCode TSRestartStep(TS ts)
5346 {
5347   PetscFunctionBegin;
5348   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5349   ts->steprestart = PETSC_TRUE;
5350   PetscFunctionReturn(PETSC_SUCCESS);
5351 }
5352 
5353 /*@
5354   TSRollBack - Rolls back one time step
5355 
5356   Collective
5357 
5358   Input Parameter:
5359 . ts - the `TS` context obtained from `TSCreate()`
5360 
5361   Level: advanced
5362 
5363 .seealso: [](ch_ts), `TS`, `TSGetStepRollBack()`, `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()`
5364 @*/
5365 PetscErrorCode TSRollBack(TS ts)
5366 {
5367   PetscFunctionBegin;
5368   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5369   PetscCheck(!ts->steprollback, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "TSRollBack already called");
5370   PetscTryTypeMethod(ts, rollback);
5371   PetscCall(VecCopy(ts->vec_sol0, ts->vec_sol));
5372   ts->time_step  = ts->ptime - ts->ptime_prev;
5373   ts->ptime      = ts->ptime_prev;
5374   ts->ptime_prev = ts->ptime_prev_rollback;
5375   ts->steps--;
5376   ts->steprollback = PETSC_TRUE;
5377   PetscFunctionReturn(PETSC_SUCCESS);
5378 }
5379 
5380 /*@
5381   TSGetStepRollBack - Get the internal flag indicating if you are rolling back a step
5382 
5383   Not collective
5384 
5385   Input Parameter:
5386 . ts - the `TS` context obtained from `TSCreate()`
5387 
5388   Output Parameter:
5389 . flg - the rollback flag
5390 
5391   Level: advanced
5392 
5393 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSRollBack()`
5394 @*/
5395 PetscErrorCode TSGetStepRollBack(TS ts, PetscBool *flg)
5396 {
5397   PetscFunctionBegin;
5398   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5399   PetscAssertPointer(flg, 2);
5400   *flg = ts->steprollback;
5401   PetscFunctionReturn(PETSC_SUCCESS);
5402 }
5403 
5404 /*@
5405   TSGetStepResize - Get the internal flag indicating if the current step is after a resize.
5406 
5407   Not collective
5408 
5409   Input Parameter:
5410 . ts - the `TS` context obtained from `TSCreate()`
5411 
5412   Output Parameter:
5413 . flg - the resize flag
5414 
5415   Level: advanced
5416 
5417 .seealso: [](ch_ts), `TS`, `TSCreate()`, `TSSetResize()`
5418 @*/
5419 PetscErrorCode TSGetStepResize(TS ts, PetscBool *flg)
5420 {
5421   PetscFunctionBegin;
5422   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5423   PetscAssertPointer(flg, 2);
5424   *flg = ts->stepresize;
5425   PetscFunctionReturn(PETSC_SUCCESS);
5426 }
5427 
5428 /*@
5429   TSGetStages - Get the number of stages and stage values
5430 
5431   Input Parameter:
5432 . ts - the `TS` context obtained from `TSCreate()`
5433 
5434   Output Parameters:
5435 + ns - the number of stages
5436 - Y  - the current stage vectors
5437 
5438   Level: advanced
5439 
5440   Note:
5441   Both `ns` and `Y` can be `NULL`.
5442 
5443 .seealso: [](ch_ts), `TS`, `TSCreate()`
5444 @*/
5445 PetscErrorCode TSGetStages(TS ts, PetscInt *ns, Vec **Y)
5446 {
5447   PetscFunctionBegin;
5448   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5449   if (ns) PetscAssertPointer(ns, 2);
5450   if (Y) PetscAssertPointer(Y, 3);
5451   if (!ts->ops->getstages) {
5452     if (ns) *ns = 0;
5453     if (Y) *Y = NULL;
5454   } else PetscUseTypeMethod(ts, getstages, ns, Y);
5455   PetscFunctionReturn(PETSC_SUCCESS);
5456 }
5457 
5458 /*@C
5459   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
5460 
5461   Collective
5462 
5463   Input Parameters:
5464 + ts    - the `TS` context
5465 . t     - current timestep
5466 . U     - state vector
5467 . Udot  - time derivative of state vector
5468 . shift - shift to apply, see note below
5469 - ctx   - an optional user context
5470 
5471   Output Parameters:
5472 + J - Jacobian matrix (not altered in this routine)
5473 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as `J`)
5474 
5475   Level: intermediate
5476 
5477   Notes:
5478   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
5479 
5480   dF/dU + shift*dF/dUdot
5481 
5482   Most users should not need to explicitly call this routine, as it
5483   is used internally within the nonlinear solvers.
5484 
5485   This will first try to get the coloring from the `DM`.  If the `DM` type has no coloring
5486   routine, then it will try to get the coloring from the matrix.  This requires that the
5487   matrix have nonzero entries precomputed.
5488 
5489 .seealso: [](ch_ts), `TS`, `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
5490 @*/
5491 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal shift, Mat J, Mat B, void *ctx)
5492 {
5493   SNES          snes;
5494   MatFDColoring color;
5495   PetscBool     hascolor, matcolor = PETSC_FALSE;
5496 
5497   PetscFunctionBegin;
5498   PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL));
5499   PetscCall(PetscObjectQuery((PetscObject)B, "TSMatFDColoring", (PetscObject *)&color));
5500   if (!color) {
5501     DM         dm;
5502     ISColoring iscoloring;
5503 
5504     PetscCall(TSGetDM(ts, &dm));
5505     PetscCall(DMHasColoring(dm, &hascolor));
5506     if (hascolor && !matcolor) {
5507       PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring));
5508       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5509       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
5510       PetscCall(MatFDColoringSetFromOptions(color));
5511       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5512       PetscCall(ISColoringDestroy(&iscoloring));
5513     } else {
5514       MatColoring mc;
5515 
5516       PetscCall(MatColoringCreate(B, &mc));
5517       PetscCall(MatColoringSetDistance(mc, 2));
5518       PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
5519       PetscCall(MatColoringSetFromOptions(mc));
5520       PetscCall(MatColoringApply(mc, &iscoloring));
5521       PetscCall(MatColoringDestroy(&mc));
5522       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5523       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
5524       PetscCall(MatFDColoringSetFromOptions(color));
5525       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5526       PetscCall(ISColoringDestroy(&iscoloring));
5527     }
5528     PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)color));
5529     PetscCall(PetscObjectDereference((PetscObject)color));
5530   }
5531   PetscCall(TSGetSNES(ts, &snes));
5532   PetscCall(MatFDColoringApply(B, color, U, snes));
5533   if (J != B) {
5534     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
5535     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
5536   }
5537   PetscFunctionReturn(PETSC_SUCCESS);
5538 }
5539 
5540 /*@C
5541   TSSetFunctionDomainError - Set a function that tests if the current state vector is valid
5542 
5543   Input Parameters:
5544 + ts   - the `TS` context
5545 - func - function called within `TSFunctionDomainError()`
5546 
5547   Calling sequence of `func`:
5548 + ts     - the `TS` context
5549 . time   - the current time (of the stage)
5550 . state  - the state to check if it is valid
5551 - accept - (output parameter) `PETSC_FALSE` if the state is not acceptable, `PETSC_TRUE` if acceptable
5552 
5553   Level: intermediate
5554 
5555   Notes:
5556   If an implicit ODE solver is being used then, in addition to providing this routine, the
5557   user's code should call `SNESSetFunctionDomainError()` when domain errors occur during
5558   function evaluations where the functions are provided by `TSSetIFunction()` or `TSSetRHSFunction()`.
5559   Use `TSGetSNES()` to obtain the `SNES` object
5560 
5561   Developer Notes:
5562   The naming of this function is inconsistent with the `SNESSetFunctionDomainError()`
5563   since one takes a function pointer and the other does not.
5564 
5565 .seealso: [](ch_ts), `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()`
5566 @*/
5567 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS ts, PetscReal time, Vec state, PetscBool *accept))
5568 {
5569   PetscFunctionBegin;
5570   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5571   ts->functiondomainerror = func;
5572   PetscFunctionReturn(PETSC_SUCCESS);
5573 }
5574 
5575 /*@
5576   TSFunctionDomainError - Checks if the current state is valid
5577 
5578   Input Parameters:
5579 + ts        - the `TS` context
5580 . stagetime - time of the simulation
5581 - Y         - state vector to check.
5582 
5583   Output Parameter:
5584 . accept - Set to `PETSC_FALSE` if the current state vector is valid.
5585 
5586   Level: developer
5587 
5588   Note:
5589   This function is called by the `TS` integration routines and calls the user provided function (set with `TSSetFunctionDomainError()`)
5590   to check if the current state is valid.
5591 
5592 .seealso: [](ch_ts), `TS`, `TSSetFunctionDomainError()`
5593 @*/
5594 PetscErrorCode TSFunctionDomainError(TS ts, PetscReal stagetime, Vec Y, PetscBool *accept)
5595 {
5596   PetscFunctionBegin;
5597   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5598   *accept = PETSC_TRUE;
5599   if (ts->functiondomainerror) PetscCall((*ts->functiondomainerror)(ts, stagetime, Y, accept));
5600   PetscFunctionReturn(PETSC_SUCCESS);
5601 }
5602 
5603 /*@
5604   TSClone - This function clones a time step `TS` object.
5605 
5606   Collective
5607 
5608   Input Parameter:
5609 . tsin - The input `TS`
5610 
5611   Output Parameter:
5612 . tsout - The output `TS` (cloned)
5613 
5614   Level: developer
5615 
5616   Notes:
5617   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.
5618   It will likely be replaced in the future with a mechanism of switching methods on the fly.
5619 
5620   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
5621 .vb
5622  SNES snes_dup = NULL;
5623  TSGetSNES(ts,&snes_dup);
5624  TSSetSNES(ts,snes_dup);
5625 .ve
5626 
5627 .seealso: [](ch_ts), `TS`, `SNES`, `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()`
5628 @*/
5629 PetscErrorCode TSClone(TS tsin, TS *tsout)
5630 {
5631   TS     t;
5632   SNES   snes_start;
5633   DM     dm;
5634   TSType type;
5635 
5636   PetscFunctionBegin;
5637   PetscAssertPointer(tsin, 1);
5638   *tsout = NULL;
5639 
5640   PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView));
5641 
5642   /* General TS description */
5643   t->numbermonitors    = 0;
5644   t->monitorFrequency  = 1;
5645   t->setupcalled       = 0;
5646   t->ksp_its           = 0;
5647   t->snes_its          = 0;
5648   t->nwork             = 0;
5649   t->rhsjacobian.time  = PETSC_MIN_REAL;
5650   t->rhsjacobian.scale = 1.;
5651   t->ijacobian.shift   = 1.;
5652 
5653   PetscCall(TSGetSNES(tsin, &snes_start));
5654   PetscCall(TSSetSNES(t, snes_start));
5655 
5656   PetscCall(TSGetDM(tsin, &dm));
5657   PetscCall(TSSetDM(t, dm));
5658 
5659   t->adapt = tsin->adapt;
5660   PetscCall(PetscObjectReference((PetscObject)t->adapt));
5661 
5662   t->trajectory = tsin->trajectory;
5663   PetscCall(PetscObjectReference((PetscObject)t->trajectory));
5664 
5665   t->event = tsin->event;
5666   if (t->event) t->event->refct++;
5667 
5668   t->problem_type      = tsin->problem_type;
5669   t->ptime             = tsin->ptime;
5670   t->ptime_prev        = tsin->ptime_prev;
5671   t->time_step         = tsin->time_step;
5672   t->max_time          = tsin->max_time;
5673   t->steps             = tsin->steps;
5674   t->max_steps         = tsin->max_steps;
5675   t->equation_type     = tsin->equation_type;
5676   t->atol              = tsin->atol;
5677   t->rtol              = tsin->rtol;
5678   t->max_snes_failures = tsin->max_snes_failures;
5679   t->max_reject        = tsin->max_reject;
5680   t->errorifstepfailed = tsin->errorifstepfailed;
5681 
5682   PetscCall(TSGetType(tsin, &type));
5683   PetscCall(TSSetType(t, type));
5684 
5685   t->vec_sol = NULL;
5686 
5687   t->cfltime          = tsin->cfltime;
5688   t->cfltime_local    = tsin->cfltime_local;
5689   t->exact_final_time = tsin->exact_final_time;
5690 
5691   t->ops[0] = tsin->ops[0];
5692 
5693   if (((PetscObject)tsin)->fortran_func_pointers) {
5694     PetscInt i;
5695     PetscCall(PetscMalloc((10) * sizeof(void (*)(void)), &((PetscObject)t)->fortran_func_pointers));
5696     for (i = 0; i < 10; i++) ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
5697   }
5698   *tsout = t;
5699   PetscFunctionReturn(PETSC_SUCCESS);
5700 }
5701 
5702 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void *ctx, Vec x, Vec y)
5703 {
5704   TS ts = (TS)ctx;
5705 
5706   PetscFunctionBegin;
5707   PetscCall(TSComputeRHSFunction(ts, 0, x, y));
5708   PetscFunctionReturn(PETSC_SUCCESS);
5709 }
5710 
5711 /*@
5712   TSRHSJacobianTest - Compares the multiply routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.
5713 
5714   Logically Collective
5715 
5716   Input Parameter:
5717 . ts - the time stepping routine
5718 
5719   Output Parameter:
5720 . flg - `PETSC_TRUE` if the multiply is likely correct
5721 
5722   Options Database Key:
5723 . -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
5724 
5725   Level: advanced
5726 
5727   Note:
5728   This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian
5729 
5730 .seealso: [](ch_ts), `TS`, `Mat`, `MATSHELL`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()`
5731 @*/
5732 PetscErrorCode TSRHSJacobianTest(TS ts, PetscBool *flg)
5733 {
5734   Mat              J, B;
5735   TSRHSJacobianFn *func;
5736   void            *ctx;
5737 
5738   PetscFunctionBegin;
5739   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5740   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5741   PetscCall(MatShellTestMult(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5742   PetscFunctionReturn(PETSC_SUCCESS);
5743 }
5744 
5745 /*@
5746   TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the `MATSHELL` with differencing on the `TS` given RHS function.
5747 
5748   Logically Collective
5749 
5750   Input Parameter:
5751 . ts - the time stepping routine
5752 
5753   Output Parameter:
5754 . flg - `PETSC_TRUE` if the multiply is likely correct
5755 
5756   Options Database Key:
5757 . -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
5758 
5759   Level: advanced
5760 
5761   Notes:
5762   This only works for problems defined using `TSSetRHSFunction()` and Jacobian NOT `TSSetIFunction()` and Jacobian
5763 
5764 .seealso: [](ch_ts), `TS`, `Mat`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()`
5765 @*/
5766 PetscErrorCode TSRHSJacobianTestTranspose(TS ts, PetscBool *flg)
5767 {
5768   Mat              J, B;
5769   void            *ctx;
5770   TSRHSJacobianFn *func;
5771 
5772   PetscFunctionBegin;
5773   PetscCall(TSGetRHSJacobian(ts, &J, &B, &func, &ctx));
5774   PetscCall((*func)(ts, 0.0, ts->vec_sol, J, B, ctx));
5775   PetscCall(MatShellTestMultTranspose(J, RHSWrapperFunction_TSRHSJacobianTest, ts->vec_sol, ts, flg));
5776   PetscFunctionReturn(PETSC_SUCCESS);
5777 }
5778 
5779 /*@
5780   TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used.
5781 
5782   Logically Collective
5783 
5784   Input Parameters:
5785 + ts                   - timestepping context
5786 - use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used
5787 
5788   Options Database Key:
5789 . -ts_use_splitrhsfunction - <true,false>
5790 
5791   Level: intermediate
5792 
5793   Note:
5794   This is only for multirate methods
5795 
5796 .seealso: [](ch_ts), `TS`, `TSGetUseSplitRHSFunction()`
5797 @*/
5798 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction)
5799 {
5800   PetscFunctionBegin;
5801   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5802   ts->use_splitrhsfunction = use_splitrhsfunction;
5803   PetscFunctionReturn(PETSC_SUCCESS);
5804 }
5805 
5806 /*@
5807   TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used.
5808 
5809   Not Collective
5810 
5811   Input Parameter:
5812 . ts - timestepping context
5813 
5814   Output Parameter:
5815 . use_splitrhsfunction - `PETSC_TRUE` indicates that the split RHSFunction will be used
5816 
5817   Level: intermediate
5818 
5819 .seealso: [](ch_ts), `TS`, `TSSetUseSplitRHSFunction()`
5820 @*/
5821 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction)
5822 {
5823   PetscFunctionBegin;
5824   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5825   *use_splitrhsfunction = ts->use_splitrhsfunction;
5826   PetscFunctionReturn(PETSC_SUCCESS);
5827 }
5828 
5829 /*@
5830   TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix.
5831 
5832   Logically  Collective
5833 
5834   Input Parameters:
5835 + ts  - the time-stepper
5836 - str - the structure (the default is `UNKNOWN_NONZERO_PATTERN`)
5837 
5838   Level: intermediate
5839 
5840   Note:
5841   When the relationship between the nonzero structures is known and supplied the solution process can be much faster
5842 
5843 .seealso: [](ch_ts), `TS`, `MatAXPY()`, `MatStructure`
5844  @*/
5845 PetscErrorCode TSSetMatStructure(TS ts, MatStructure str)
5846 {
5847   PetscFunctionBegin;
5848   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5849   ts->axpy_pattern = str;
5850   PetscFunctionReturn(PETSC_SUCCESS);
5851 }
5852 
5853 /*@
5854   TSSetEvaluationTimes - sets the evaluation points. The solution will be computed and stored for each time requested
5855 
5856   Collective
5857 
5858   Input Parameters:
5859 + ts          - the time-stepper
5860 . n           - number of the time points
5861 - time_points - array of the time points
5862 
5863   Options Database Key:
5864 . -ts_eval_times <t0,...tn> - Sets the evaluation times
5865 
5866   Level: intermediate
5867 
5868   Notes:
5869   The elements in `time_points` must be all increasing. They correspond to the intermediate points for time integration.
5870 
5871   `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.
5872 
5873   The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using evaluation times may
5874   pressure the memory system when using a large number of time points.
5875 
5876 .seealso: [](ch_ts), `TS`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`, `TSSetTimeSpan()`
5877  @*/
5878 PetscErrorCode TSSetEvaluationTimes(TS ts, PetscInt n, PetscReal *time_points)
5879 {
5880   PetscBool is_sorted;
5881 
5882   PetscFunctionBegin;
5883   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5884   if (ts->eval_times && n != ts->eval_times->num_time_points) {
5885     PetscCall(PetscFree(ts->eval_times->time_points));
5886     PetscCall(VecDestroyVecs(ts->eval_times->num_time_points, &ts->eval_times->sol_vecs));
5887     PetscCall(PetscMalloc1(n, &ts->eval_times->time_points));
5888   }
5889   if (!ts->eval_times) {
5890     TSEvaluationTimes eval_times;
5891     PetscCall(PetscNew(&eval_times));
5892     PetscCall(PetscMalloc1(n, &eval_times->time_points));
5893     eval_times->reltol  = 1e-6;
5894     eval_times->abstol  = 10 * PETSC_MACHINE_EPSILON;
5895     eval_times->worktol = 0;
5896     ts->eval_times      = eval_times;
5897   }
5898   ts->eval_times->num_time_points = n;
5899   PetscCall(PetscSortedReal(n, time_points, &is_sorted));
5900   PetscCheck(is_sorted, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "time_points array must be sorted");
5901   PetscCall(PetscArraycpy(ts->eval_times->time_points, time_points, n));
5902   PetscFunctionReturn(PETSC_SUCCESS);
5903 }
5904 
5905 /*@C
5906   TSGetEvaluationTimes - gets the evaluation times set with `TSSetEvaluationTimes()`
5907 
5908   Not Collective
5909 
5910   Input Parameter:
5911 . ts - the time-stepper
5912 
5913   Output Parameters:
5914 + n           - number of the time points
5915 - time_points - array of the time points
5916 
5917   Level: beginner
5918 
5919   Note:
5920   The values obtained are valid until the `TS` object is destroyed.
5921 
5922   Both `n` and `time_points` can be `NULL`.
5923 
5924   Also used to see time points set by `TSSetTimeSpan()`.
5925 
5926 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationSolutions()`
5927  @*/
5928 PetscErrorCode TSGetEvaluationTimes(TS ts, PetscInt *n, const PetscReal *time_points[])
5929 {
5930   PetscFunctionBegin;
5931   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5932   if (n) PetscAssertPointer(n, 2);
5933   if (time_points) PetscAssertPointer(time_points, 3);
5934   if (!ts->eval_times) {
5935     if (n) *n = 0;
5936     if (time_points) *time_points = NULL;
5937   } else {
5938     if (n) *n = ts->eval_times->num_time_points;
5939     if (time_points) *time_points = ts->eval_times->time_points;
5940   }
5941   PetscFunctionReturn(PETSC_SUCCESS);
5942 }
5943 
5944 /*@C
5945   TSGetEvaluationSolutions - Get the number of solutions and the solutions at the evaluation time points specified
5946 
5947   Input Parameter:
5948 . ts - the `TS` context obtained from `TSCreate()`
5949 
5950   Output Parameters:
5951 + nsol      - the number of solutions
5952 . sol_times - array of solution times corresponding to the solution vectors. See note below
5953 - Sols      - the solution vectors
5954 
5955   Level: intermediate
5956 
5957   Notes:
5958   Both `nsol` and `Sols` can be `NULL`.
5959 
5960   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()`.
5961   For example, manipulating the step size, especially with a reduced precision, may cause `TS` to step over certain evaluation times.
5962 
5963   Also used to see view solutions requested by `TSSetTimeSpan()`.
5964 
5965 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`
5966 @*/
5967 PetscErrorCode TSGetEvaluationSolutions(TS ts, PetscInt *nsol, const PetscReal *sol_times[], Vec **Sols)
5968 {
5969   PetscFunctionBegin;
5970   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
5971   if (nsol) PetscAssertPointer(nsol, 2);
5972   if (sol_times) PetscAssertPointer(sol_times, 3);
5973   if (Sols) PetscAssertPointer(Sols, 4);
5974   if (!ts->eval_times) {
5975     if (nsol) *nsol = 0;
5976     if (sol_times) *sol_times = NULL;
5977     if (Sols) *Sols = NULL;
5978   } else {
5979     if (nsol) *nsol = ts->eval_times->sol_ctr;
5980     if (sol_times) *sol_times = ts->eval_times->sol_times;
5981     if (Sols) *Sols = ts->eval_times->sol_vecs;
5982   }
5983   PetscFunctionReturn(PETSC_SUCCESS);
5984 }
5985 
5986 /*@
5987   TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested in the span
5988 
5989   Collective
5990 
5991   Input Parameters:
5992 + ts         - the time-stepper
5993 . n          - number of the time points (>=2)
5994 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively.
5995 
5996   Options Database Key:
5997 . -ts_time_span <t0,...tf> - Sets the time span
5998 
5999   Level: intermediate
6000 
6001   Notes:
6002   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.
6003 
6004   The elements in tspan must be all increasing. They correspond to the intermediate points for time integration.
6005 
6006   `TS_EXACTFINALTIME_MATCHSTEP` must be used to make the last time step in each sub-interval match the intermediate points specified.
6007 
6008   The intermediate solutions are saved in a vector array that can be accessed with `TSGetEvaluationSolutions()`. Thus using time span may
6009   pressure the memory system when using a large number of span points.
6010 
6011 .seealso: [](ch_ts), `TS`, `TSSetEvaluationTimes()`, `TSGetEvaluationTimes()`, `TSGetEvaluationSolutions()`
6012  @*/
6013 PetscErrorCode TSSetTimeSpan(TS ts, PetscInt n, PetscReal *span_times)
6014 {
6015   PetscFunctionBegin;
6016   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
6017   PetscCheck(n >= 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONG, "Minimum time span size is 2 but %" PetscInt_FMT " is provided", n);
6018   PetscCall(TSSetEvaluationTimes(ts, n, span_times));
6019   PetscCall(TSSetTime(ts, span_times[0]));
6020   PetscCall(TSSetMaxTime(ts, span_times[n - 1]));
6021   PetscFunctionReturn(PETSC_SUCCESS);
6022 }
6023 
6024 /*@
6025   TSPruneIJacobianColor - Remove nondiagonal zeros in the Jacobian matrix and update the `MatMFFD` coloring information.
6026 
6027   Collective
6028 
6029   Input Parameters:
6030 + ts - the `TS` context
6031 . J  - Jacobian matrix (not altered in this routine)
6032 - B  - newly computed Jacobian matrix to use with preconditioner
6033 
6034   Level: intermediate
6035 
6036   Notes:
6037   This function improves the `MatFDColoring` performance when the Jacobian matrix was over-allocated or contains
6038   many constant zeros entries, which is typically the case when the matrix is generated by a `DM`
6039   and multiple fields are involved.
6040 
6041   Users need to make sure that the Jacobian matrix is properly filled to reflect the sparsity
6042   structure. For `MatFDColoring`, the values of nonzero entries are not important. So one can
6043   usually call `TSComputeIJacobian()` with randomized input vectors to generate a dummy Jacobian.
6044   `TSComputeIJacobian()` should be called before `TSSolve()` but after `TSSetUp()`.
6045 
6046 .seealso: [](ch_ts), `TS`, `MatFDColoring`, `TSComputeIJacobianDefaultColor()`, `MatEliminateZeros()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
6047 @*/
6048 PetscErrorCode TSPruneIJacobianColor(TS ts, Mat J, Mat B)
6049 {
6050   MatColoring   mc            = NULL;
6051   ISColoring    iscoloring    = NULL;
6052   MatFDColoring matfdcoloring = NULL;
6053 
6054   PetscFunctionBegin;
6055   /* Generate new coloring after eliminating zeros in the matrix */
6056   PetscCall(MatEliminateZeros(B, PETSC_TRUE));
6057   PetscCall(MatColoringCreate(B, &mc));
6058   PetscCall(MatColoringSetDistance(mc, 2));
6059   PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
6060   PetscCall(MatColoringSetFromOptions(mc));
6061   PetscCall(MatColoringApply(mc, &iscoloring));
6062   PetscCall(MatColoringDestroy(&mc));
6063   /* Replace the old coloring with the new one */
6064   PetscCall(MatFDColoringCreate(B, iscoloring, &matfdcoloring));
6065   PetscCall(MatFDColoringSetFunction(matfdcoloring, (PetscErrorCode (*)(void))SNESTSFormFunction, (void *)ts));
6066   PetscCall(MatFDColoringSetFromOptions(matfdcoloring));
6067   PetscCall(MatFDColoringSetUp(B, iscoloring, matfdcoloring));
6068   PetscCall(PetscObjectCompose((PetscObject)B, "TSMatFDColoring", (PetscObject)matfdcoloring));
6069   PetscCall(PetscObjectDereference((PetscObject)matfdcoloring));
6070   PetscCall(ISColoringDestroy(&iscoloring));
6071   PetscFunctionReturn(PETSC_SUCCESS);
6072 }
6073