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