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