xref: /petsc/src/ts/interface/ts.c (revision 08401ef684002a709c6d3db98a0c9f54a8bcf1ec)
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   PetscErrorCode         ierr;
89   char                   monfilename[PETSC_MAX_PATH_LEN];
90   PetscReal              time_step,tspan[100];
91   PetscInt               nt = PETSC_STATIC_ARRAY_LENGTH(tspan);
92   TSExactFinalTimeOption eftopt;
93   char                   dir[16];
94   TSIFunction            ifun;
95   const char             *defaultType;
96   char                   typeName[256];
97 
98   PetscFunctionBegin;
99   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
100 
101   PetscCall(TSRegisterAll());
102   PetscCall(TSGetIFunction(ts,NULL,&ifun,NULL));
103 
104   ierr = PetscObjectOptionsBegin((PetscObject)ts);PetscCall(ierr);
105   if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name;
106   else defaultType = ifun ? TSBEULER : TSEULER;
107   PetscCall(PetscOptionsFList("-ts_type","TS method","TSSetType",TSList,defaultType,typeName,256,&opt));
108   if (opt) {
109     PetscCall(TSSetType(ts,typeName));
110   } else {
111     PetscCall(TSSetType(ts,defaultType));
112   }
113 
114   /* Handle generic TS options */
115   PetscCall(PetscOptionsDeprecated("-ts_final_time","-ts_max_time","3.10",NULL));
116   PetscCall(PetscOptionsReal("-ts_max_time","Maximum time to run to","TSSetMaxTime",ts->max_time,&ts->max_time,NULL));
117   PetscCall(PetscOptionsRealArray("-ts_time_span","Time span","TSSetTimeSpan",tspan,&nt,&flg));
118   if (flg) PetscCall(TSSetTimeSpan(ts,nt,tspan));
119   PetscCall(PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetMaxSteps",ts->max_steps,&ts->max_steps,NULL));
120   PetscCall(PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,NULL));
121   PetscCall(PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&time_step,&flg));
122   if (flg) PetscCall(TSSetTimeStep(ts,time_step));
123   PetscCall(PetscOptionsEnum("-ts_exact_final_time","Option for handling of final time step","TSSetExactFinalTime",TSExactFinalTimeOptions,(PetscEnum)ts->exact_final_time,(PetscEnum*)&eftopt,&flg));
124   if (flg) PetscCall(TSSetExactFinalTime(ts,eftopt));
125   PetscCall(PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","TSSetMaxSNESFailures",ts->max_snes_failures,&ts->max_snes_failures,NULL));
126   PetscCall(PetscOptionsInt("-ts_max_reject","Maximum number of step rejections before step fails","TSSetMaxStepRejections",ts->max_reject,&ts->max_reject,NULL));
127   PetscCall(PetscOptionsBool("-ts_error_if_step_fails","Error if no step succeeds","TSSetErrorIfStepFails",ts->errorifstepfailed,&ts->errorifstepfailed,NULL));
128   PetscCall(PetscOptionsReal("-ts_rtol","Relative tolerance for local truncation error","TSSetTolerances",ts->rtol,&ts->rtol,NULL));
129   PetscCall(PetscOptionsReal("-ts_atol","Absolute tolerance for local truncation error","TSSetTolerances",ts->atol,&ts->atol,NULL));
130 
131   PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult","Test the RHS Jacobian for consistency with RHS at each solve ","None",ts->testjacobian,&ts->testjacobian,NULL));
132   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));
133   PetscCall(PetscOptionsBool("-ts_use_splitrhsfunction","Use the split RHS function for multirate solvers ","TSSetUseSplitRHSFunction",ts->use_splitrhsfunction,&ts->use_splitrhsfunction,NULL));
134 #if defined(PETSC_HAVE_SAWS)
135   {
136     PetscBool set;
137     flg  = PETSC_FALSE;
138     PetscCall(PetscOptionsBool("-ts_saws_block","Block for SAWs memory snooper at end of TSSolve","PetscObjectSAWsBlock",((PetscObject)ts)->amspublishblock,&flg,&set));
139     if (set) {
140       PetscCall(PetscObjectSAWsSetBlock((PetscObject)ts,flg));
141     }
142   }
143 #endif
144 
145   /* Monitor options */
146   PetscCall(PetscOptionsInt("-ts_monitor_frequency", "Number of time steps between monitor output", "TSMonitorSetFrequency", ts->monitorFrequency, &ts->monitorFrequency, NULL));
147   PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor","Monitor time and timestep size","TSMonitorDefault",TSMonitorDefault,NULL));
148   PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_extreme","Monitor extreme values of the solution","TSMonitorExtreme",TSMonitorExtreme,NULL));
149   PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_solution","View the solution at each timestep","TSMonitorSolution",TSMonitorSolution,NULL));
150   PetscCall(TSMonitorSetFromOptions(ts,"-ts_dmswarm_monitor_moments","Monitor moments of particle distribution","TSDMSwarmMonitorMoments",TSDMSwarmMonitorMoments,NULL));
151 
152   PetscCall(PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",NULL,monfilename,sizeof(monfilename),&flg));
153   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts,monfilename));
154 
155   PetscCall(PetscOptionsName("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",&opt));
156   if (opt) {
157     PetscInt       howoften = 1;
158     DM             dm;
159     PetscBool      net;
160 
161     PetscCall(PetscOptionsInt("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",howoften,&howoften,NULL));
162     PetscCall(TSGetDM(ts,&dm));
163     PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMNETWORK,&net));
164     if (net) {
165       TSMonitorLGCtxNetwork ctx;
166       PetscCall(TSMonitorLGCtxNetworkCreate(ts,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx));
167       PetscCall(TSMonitorSet(ts,TSMonitorLGCtxNetworkSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxNetworkDestroy));
168       PetscCall(PetscOptionsBool("-ts_monitor_lg_solution_semilogy","Plot the solution with a semi-log axis","",ctx->semilogy,&ctx->semilogy,NULL));
169     } else {
170       TSMonitorLGCtx ctx;
171       PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
172       PetscCall(TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
173     }
174   }
175 
176   PetscCall(PetscOptionsName("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",&opt));
177   if (opt) {
178     TSMonitorLGCtx ctx;
179     PetscInt       howoften = 1;
180 
181     PetscCall(PetscOptionsInt("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",howoften,&howoften,NULL));
182     PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
183     PetscCall(TSMonitorSet(ts,TSMonitorLGError,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
184   }
185   PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_error","View the error at each timestep","TSMonitorError",TSMonitorError,NULL));
186 
187   PetscCall(PetscOptionsName("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",&opt));
188   if (opt) {
189     TSMonitorLGCtx ctx;
190     PetscInt       howoften = 1;
191 
192     PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL));
193     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
194     PetscCall(TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
195   }
196   PetscCall(PetscOptionsName("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",&opt));
197   if (opt) {
198     TSMonitorLGCtx ctx;
199     PetscInt       howoften = 1;
200 
201     PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL));
202     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
203     PetscCall(TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
204     ctx->semilogy = PETSC_TRUE;
205   }
206 
207   PetscCall(PetscOptionsName("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",&opt));
208   if (opt) {
209     TSMonitorLGCtx ctx;
210     PetscInt       howoften = 1;
211 
212     PetscCall(PetscOptionsInt("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",howoften,&howoften,NULL));
213     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
214     PetscCall(TSMonitorSet(ts,TSMonitorLGSNESIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
215   }
216   PetscCall(PetscOptionsName("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",&opt));
217   if (opt) {
218     TSMonitorLGCtx ctx;
219     PetscInt       howoften = 1;
220 
221     PetscCall(PetscOptionsInt("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",howoften,&howoften,NULL));
222     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
223     PetscCall(TSMonitorSet(ts,TSMonitorLGKSPIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
224   }
225   PetscCall(PetscOptionsName("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",&opt));
226   if (opt) {
227     TSMonitorSPEigCtx ctx;
228     PetscInt          howoften = 1;
229 
230     PetscCall(PetscOptionsInt("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",howoften,&howoften,NULL));
231     PetscCall(TSMonitorSPEigCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx));
232     PetscCall(TSMonitorSet(ts,TSMonitorSPEig,ctx,(PetscErrorCode (*)(void**))TSMonitorSPEigCtxDestroy));
233   }
234   PetscCall(PetscOptionsName("-ts_monitor_sp_swarm","Display particle phase from the DMSwarm","TSMonitorSPSwarm",&opt));
235   if (opt) {
236     TSMonitorSPCtx  ctx;
237     PetscInt        howoften = 1, retain = 0;
238     PetscBool       phase = PETSC_TRUE;
239 
240     PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm","Display particles phase from the DMSwarm", "TSMonitorSPSwarm", howoften, &howoften, NULL));
241     PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm_retain", "Retain n points plotted to show trajectory, -1 for all points", "TSMonitorSPSwarm", retain, &retain, NULL));
242     PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_phase", "Plot in phase space rather than coordinate space", "TSMonitorSPSwarm", phase, &phase, NULL));
243     PetscCall(TSMonitorSPCtxCreate(PetscObjectComm((PetscObject) ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, retain, phase, &ctx));
244     PetscCall(TSMonitorSet(ts, TSMonitorSPSwarmSolution, ctx, (PetscErrorCode (*)(void**))TSMonitorSPCtxDestroy));
245   }
246   opt  = PETSC_FALSE;
247   PetscCall(PetscOptionsName("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",&opt));
248   if (opt) {
249     TSMonitorDrawCtx ctx;
250     PetscInt         howoften = 1;
251 
252     PetscCall(PetscOptionsInt("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",howoften,&howoften,NULL));
253     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Computed Solution",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx));
254     PetscCall(TSMonitorSet(ts,TSMonitorDrawSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy));
255   }
256   opt  = PETSC_FALSE;
257   PetscCall(PetscOptionsName("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",&opt));
258   if (opt) {
259     TSMonitorDrawCtx ctx;
260     PetscReal        bounds[4];
261     PetscInt         n = 4;
262     PetscDraw        draw;
263     PetscDrawAxis    axis;
264 
265     PetscCall(PetscOptionsRealArray("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",bounds,&n,NULL));
266     PetscCheck(n == 4,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Must provide bounding box of phase field");
267     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,1,&ctx));
268     PetscCall(PetscViewerDrawGetDraw(ctx->viewer,0,&draw));
269     PetscCall(PetscViewerDrawGetDrawAxis(ctx->viewer,0,&axis));
270     PetscCall(PetscDrawAxisSetLimits(axis,bounds[0],bounds[2],bounds[1],bounds[3]));
271     PetscCall(PetscDrawAxisSetLabels(axis,"Phase Diagram","Variable 1","Variable 2"));
272     PetscCall(TSMonitorSet(ts,TSMonitorDrawSolutionPhase,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy));
273   }
274   opt  = PETSC_FALSE;
275   PetscCall(PetscOptionsName("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",&opt));
276   if (opt) {
277     TSMonitorDrawCtx ctx;
278     PetscInt         howoften = 1;
279 
280     PetscCall(PetscOptionsInt("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",howoften,&howoften,NULL));
281     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Error",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx));
282     PetscCall(TSMonitorSet(ts,TSMonitorDrawError,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy));
283   }
284   opt  = PETSC_FALSE;
285   PetscCall(PetscOptionsName("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",&opt));
286   if (opt) {
287     TSMonitorDrawCtx ctx;
288     PetscInt         howoften = 1;
289 
290     PetscCall(PetscOptionsInt("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",howoften,&howoften,NULL));
291     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Solution provided by user function",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx));
292     PetscCall(TSMonitorSet(ts,TSMonitorDrawSolutionFunction,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy));
293   }
294 
295   opt  = PETSC_FALSE;
296   PetscCall(PetscOptionsString("-ts_monitor_solution_vtk","Save each time step to a binary file, use filename-%%03D.vts","TSMonitorSolutionVTK",NULL,monfilename,sizeof(monfilename),&flg));
297   if (flg) {
298     const char *ptr,*ptr2;
299     char       *filetemplate;
300     PetscCheck(monfilename[0],PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
301     /* Do some cursory validation of the input. */
302     PetscCall(PetscStrstr(monfilename,"%",(char**)&ptr));
303     PetscCheck(ptr,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
304     for (ptr++; ptr && *ptr; ptr++) {
305       PetscCall(PetscStrchr("DdiouxX",*ptr,(char**)&ptr2));
306       PetscCheck(ptr2 || (*ptr >= '0' && *ptr <= '9'),PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03D.vts");
307       if (ptr2) break;
308     }
309     PetscCall(PetscStrallocpy(monfilename,&filetemplate));
310     PetscCall(TSMonitorSet(ts,TSMonitorSolutionVTK,filetemplate,(PetscErrorCode (*)(void**))TSMonitorSolutionVTKDestroy));
311   }
312 
313   PetscCall(PetscOptionsString("-ts_monitor_dmda_ray","Display a ray of the solution","None","y=0",dir,sizeof(dir),&flg));
314   if (flg) {
315     TSMonitorDMDARayCtx *rayctx;
316     int                  ray = 0;
317     DMDirection          ddir;
318     DM                   da;
319     PetscMPIInt          rank;
320 
321     PetscCheck(dir[1] == '=',PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
322     if (dir[0] == 'x') ddir = DM_X;
323     else if (dir[0] == 'y') ddir = DM_Y;
324     else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
325     sscanf(dir+2,"%d",&ray);
326 
327     PetscCall(PetscInfo(((PetscObject)ts),"Displaying DMDA ray %c = %d\n",dir[0],ray));
328     PetscCall(PetscNew(&rayctx));
329     PetscCall(TSGetDM(ts,&da));
330     PetscCall(DMDAGetRay(da,ddir,ray,&rayctx->ray,&rayctx->scatter));
331     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ts),&rank));
332     if (rank == 0) {
333       PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF,NULL,NULL,0,0,600,300,&rayctx->viewer));
334     }
335     rayctx->lgctx = NULL;
336     PetscCall(TSMonitorSet(ts,TSMonitorDMDARay,rayctx,TSMonitorDMDARayDestroy));
337   }
338   PetscCall(PetscOptionsString("-ts_monitor_lg_dmda_ray","Display a ray of the solution","None","x=0",dir,sizeof(dir),&flg));
339   if (flg) {
340     TSMonitorDMDARayCtx *rayctx;
341     int                 ray = 0;
342     DMDirection         ddir;
343     DM                  da;
344     PetscInt            howoften = 1;
345 
346     PetscCheck(dir[1] == '=',PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir);
347     if      (dir[0] == 'x') ddir = DM_X;
348     else if (dir[0] == 'y') ddir = DM_Y;
349     else SETERRQ(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir);
350     sscanf(dir+2, "%d", &ray);
351 
352     PetscCall(PetscInfo(((PetscObject) ts),"Displaying LG DMDA ray %c = %d\n", dir[0], ray));
353     PetscCall(PetscNew(&rayctx));
354     PetscCall(TSGetDM(ts, &da));
355     PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter));
356     PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&rayctx->lgctx));
357     PetscCall(TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy));
358   }
359 
360   PetscCall(PetscOptionsName("-ts_monitor_envelope","Monitor maximum and minimum value of each component of the solution","TSMonitorEnvelope",&opt));
361   if (opt) {
362     TSMonitorEnvelopeCtx ctx;
363 
364     PetscCall(TSMonitorEnvelopeCtxCreate(ts,&ctx));
365     PetscCall(TSMonitorSet(ts,TSMonitorEnvelope,ctx,(PetscErrorCode (*)(void**))TSMonitorEnvelopeCtxDestroy));
366   }
367   flg  = PETSC_FALSE;
368   PetscCall(PetscOptionsBool("-ts_monitor_cancel","Remove all monitors","TSMonitorCancel",flg,&flg,&opt));
369   if (opt && flg) PetscCall(TSMonitorCancel(ts));
370 
371   flg  = PETSC_FALSE;
372   PetscCall(PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeJacobianDefaultColor", flg, &flg, NULL));
373   if (flg) {
374     DM   dm;
375     DMTS tdm;
376 
377     PetscCall(TSGetDM(ts, &dm));
378     PetscCall(DMGetDMTS(dm, &tdm));
379     tdm->ijacobianctx = NULL;
380     PetscCall(TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, NULL));
381     PetscCall(PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n"));
382   }
383 
384   /* Handle specific TS options */
385   if (ts->ops->setfromoptions) {
386     PetscCall((*ts->ops->setfromoptions)(PetscOptionsObject,ts));
387   }
388 
389   /* Handle TSAdapt options */
390   PetscCall(TSGetAdapt(ts,&ts->adapt));
391   PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type));
392   PetscCall(TSAdaptSetFromOptions(PetscOptionsObject,ts->adapt));
393 
394   /* TS trajectory must be set after TS, since it may use some TS options above */
395   tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE;
396   PetscCall(PetscOptionsBool("-ts_save_trajectory","Save the solution at each timestep","TSSetSaveTrajectory",tflg,&tflg,NULL));
397   if (tflg) {
398     PetscCall(TSSetSaveTrajectory(ts));
399   }
400 
401   PetscCall(TSAdjointSetFromOptions(PetscOptionsObject,ts));
402 
403   /* process any options handlers added with PetscObjectAddOptionsHandler() */
404   PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)ts));
405   ierr = PetscOptionsEnd();PetscCall(ierr);
406 
407   if (ts->trajectory) {
408     PetscCall(TSTrajectorySetFromOptions(ts->trajectory,ts));
409   }
410 
411   /* why do we have to do this here and not during TSSetUp? */
412   PetscCall(TSGetSNES(ts,&ts->snes));
413   if (ts->problem_type == TS_LINEAR) {
414     PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes,&flg,SNESKSPONLY,SNESKSPTRANSPOSEONLY,""));
415     if (!flg) PetscCall(SNESSetType(ts->snes,SNESKSPONLY));
416   }
417   PetscCall(SNESSetFromOptions(ts->snes));
418   PetscFunctionReturn(0);
419 }
420 
421 /*@
422    TSGetTrajectory - Gets the trajectory from a TS if it exists
423 
424    Collective on TS
425 
426    Input Parameters:
427 .  ts - the TS context obtained from TSCreate()
428 
429    Output Parameters:
430 .  tr - the TSTrajectory object, if it exists
431 
432    Note: This routine should be called after all TS options have been set
433 
434    Level: advanced
435 
436 .seealso: TSGetTrajectory(), TSAdjointSolve(), TSTrajectory, TSTrajectoryCreate()
437 
438 @*/
439 PetscErrorCode  TSGetTrajectory(TS ts,TSTrajectory *tr)
440 {
441   PetscFunctionBegin;
442   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
443   *tr = ts->trajectory;
444   PetscFunctionReturn(0);
445 }
446 
447 /*@
448    TSSetSaveTrajectory - Causes the TS to save its solutions as it iterates forward in time in a TSTrajectory object
449 
450    Collective on TS
451 
452    Input Parameter:
453 .  ts - the TS context obtained from TSCreate()
454 
455    Options Database:
456 +  -ts_save_trajectory - saves the trajectory to a file
457 -  -ts_trajectory_type type - set trajectory type
458 
459 Note: This routine should be called after all TS options have been set
460 
461     The TSTRAJECTORYVISUALIZATION files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and
462    MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m
463 
464    Level: intermediate
465 
466 .seealso: TSGetTrajectory(), TSAdjointSolve()
467 
468 @*/
469 PetscErrorCode  TSSetSaveTrajectory(TS ts)
470 {
471   PetscFunctionBegin;
472   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
473   if (!ts->trajectory) {
474     PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory));
475   }
476   PetscFunctionReturn(0);
477 }
478 
479 /*@
480    TSResetTrajectory - Destroys and recreates the internal TSTrajectory object
481 
482    Collective on TS
483 
484    Input Parameters:
485 .  ts - the TS context obtained from TSCreate()
486 
487    Level: intermediate
488 
489 .seealso: TSGetTrajectory(), TSAdjointSolve(), TSRemoveTrajectory()
490 
491 @*/
492 PetscErrorCode  TSResetTrajectory(TS ts)
493 {
494   PetscFunctionBegin;
495   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
496   if (ts->trajectory) {
497     PetscCall(TSTrajectoryDestroy(&ts->trajectory));
498     PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory));
499   }
500   PetscFunctionReturn(0);
501 }
502 
503 /*@
504    TSRemoveTrajectory - Destroys and removes the internal TSTrajectory object from TS
505 
506    Collective on TS
507 
508    Input Parameters:
509 .  ts - the TS context obtained from TSCreate()
510 
511    Level: intermediate
512 
513 .seealso: TSResetTrajectory(), TSAdjointSolve()
514 
515 @*/
516 PetscErrorCode TSRemoveTrajectory(TS ts)
517 {
518   PetscFunctionBegin;
519   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
520   if (ts->trajectory) {
521     PetscCall(TSTrajectoryDestroy(&ts->trajectory));
522   }
523   PetscFunctionReturn(0);
524 }
525 
526 /*@
527    TSComputeRHSJacobian - Computes the Jacobian matrix that has been
528       set with TSSetRHSJacobian().
529 
530    Collective on TS
531 
532    Input Parameters:
533 +  ts - the TS context
534 .  t - current timestep
535 -  U - input vector
536 
537    Output Parameters:
538 +  A - Jacobian matrix
539 -  B - optional preconditioning matrix
540 
541    Notes:
542    Most users should not need to explicitly call this routine, as it
543    is used internally within the nonlinear solvers.
544 
545    Level: developer
546 
547 .seealso:  TSSetRHSJacobian(), KSPSetOperators()
548 @*/
549 PetscErrorCode  TSComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat B)
550 {
551   PetscObjectState Ustate;
552   PetscObjectId    Uid;
553   DM               dm;
554   DMTS             tsdm;
555   TSRHSJacobian    rhsjacobianfunc;
556   void             *ctx;
557   TSRHSFunction    rhsfunction;
558 
559   PetscFunctionBegin;
560   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
561   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
562   PetscCheckSameComm(ts,1,U,3);
563   PetscCall(TSGetDM(ts,&dm));
564   PetscCall(DMGetDMTS(dm,&tsdm));
565   PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL));
566   PetscCall(DMTSGetRHSJacobian(dm,&rhsjacobianfunc,&ctx));
567   PetscCall(PetscObjectStateGet((PetscObject)U,&Ustate));
568   PetscCall(PetscObjectGetId((PetscObject)U,&Uid));
569 
570   if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.Xid == Uid && ts->rhsjacobian.Xstate == Ustate)) && (rhsfunction != TSComputeRHSFunctionLinear)) PetscFunctionReturn(0);
571 
572   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);
573   if (rhsjacobianfunc) {
574     PetscCall(PetscLogEventBegin(TS_JacobianEval,ts,U,A,B));
575     PetscStackPush("TS user Jacobian function");
576     PetscCall((*rhsjacobianfunc)(ts,t,U,A,B,ctx));
577     PetscStackPop;
578     ts->rhsjacs++;
579     PetscCall(PetscLogEventEnd(TS_JacobianEval,ts,U,A,B));
580   } else {
581     PetscCall(MatZeroEntries(A));
582     if (B && A != B) PetscCall(MatZeroEntries(B));
583   }
584   ts->rhsjacobian.time  = t;
585   ts->rhsjacobian.shift = 0;
586   ts->rhsjacobian.scale = 1.;
587   PetscCall(PetscObjectGetId((PetscObject)U,&ts->rhsjacobian.Xid));
588   PetscCall(PetscObjectStateGet((PetscObject)U,&ts->rhsjacobian.Xstate));
589   PetscFunctionReturn(0);
590 }
591 
592 /*@
593    TSComputeRHSFunction - Evaluates the right-hand-side function.
594 
595    Collective on TS
596 
597    Input Parameters:
598 +  ts - the TS context
599 .  t - current time
600 -  U - state vector
601 
602    Output Parameter:
603 .  y - right hand side
604 
605    Note:
606    Most users should not need to explicitly call this routine, as it
607    is used internally within the nonlinear solvers.
608 
609    Level: developer
610 
611 .seealso: TSSetRHSFunction(), TSComputeIFunction()
612 @*/
613 PetscErrorCode TSComputeRHSFunction(TS ts,PetscReal t,Vec U,Vec y)
614 {
615   TSRHSFunction  rhsfunction;
616   TSIFunction    ifunction;
617   void           *ctx;
618   DM             dm;
619 
620   PetscFunctionBegin;
621   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
622   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
623   PetscValidHeaderSpecific(y,VEC_CLASSID,4);
624   PetscCall(TSGetDM(ts,&dm));
625   PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,&ctx));
626   PetscCall(DMTSGetIFunction(dm,&ifunction,NULL));
627 
628   PetscCheck(rhsfunction || ifunction,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
629 
630   if (rhsfunction) {
631     PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,y,0));
632     PetscCall(VecLockReadPush(U));
633     PetscStackPush("TS user right-hand-side function");
634     PetscCall((*rhsfunction)(ts,t,U,y,ctx));
635     PetscStackPop;
636     PetscCall(VecLockReadPop(U));
637     ts->rhsfuncs++;
638     PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,y,0));
639   } else {
640     PetscCall(VecZeroEntries(y));
641   }
642   PetscFunctionReturn(0);
643 }
644 
645 /*@
646    TSComputeSolutionFunction - Evaluates the solution function.
647 
648    Collective on TS
649 
650    Input Parameters:
651 +  ts - the TS context
652 -  t - current time
653 
654    Output Parameter:
655 .  U - the solution
656 
657    Note:
658    Most users should not need to explicitly call this routine, as it
659    is used internally within the nonlinear solvers.
660 
661    Level: developer
662 
663 .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction()
664 @*/
665 PetscErrorCode TSComputeSolutionFunction(TS ts,PetscReal t,Vec U)
666 {
667   TSSolutionFunction solutionfunction;
668   void               *ctx;
669   DM                 dm;
670 
671   PetscFunctionBegin;
672   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
673   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
674   PetscCall(TSGetDM(ts,&dm));
675   PetscCall(DMTSGetSolutionFunction(dm,&solutionfunction,&ctx));
676 
677   if (solutionfunction) {
678     PetscStackPush("TS user solution function");
679     PetscCall((*solutionfunction)(ts,t,U,ctx));
680     PetscStackPop;
681   }
682   PetscFunctionReturn(0);
683 }
684 /*@
685    TSComputeForcingFunction - Evaluates the forcing function.
686 
687    Collective on TS
688 
689    Input Parameters:
690 +  ts - the TS context
691 -  t - current time
692 
693    Output Parameter:
694 .  U - the function value
695 
696    Note:
697    Most users should not need to explicitly call this routine, as it
698    is used internally within the nonlinear solvers.
699 
700    Level: developer
701 
702 .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction()
703 @*/
704 PetscErrorCode TSComputeForcingFunction(TS ts,PetscReal t,Vec U)
705 {
706   void              *ctx;
707   DM                 dm;
708   TSForcingFunction  forcing;
709 
710   PetscFunctionBegin;
711   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
712   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
713   PetscCall(TSGetDM(ts,&dm));
714   PetscCall(DMTSGetForcingFunction(dm,&forcing,&ctx));
715 
716   if (forcing) {
717     PetscStackPush("TS user forcing function");
718     PetscCall((*forcing)(ts,t,U,ctx));
719     PetscStackPop;
720   }
721   PetscFunctionReturn(0);
722 }
723 
724 static PetscErrorCode TSGetRHSVec_Private(TS ts,Vec *Frhs)
725 {
726   Vec            F;
727 
728   PetscFunctionBegin;
729   *Frhs = NULL;
730   PetscCall(TSGetIFunction(ts,&F,NULL,NULL));
731   if (!ts->Frhs) {
732     PetscCall(VecDuplicate(F,&ts->Frhs));
733   }
734   *Frhs = ts->Frhs;
735   PetscFunctionReturn(0);
736 }
737 
738 PetscErrorCode TSGetRHSMats_Private(TS ts,Mat *Arhs,Mat *Brhs)
739 {
740   Mat            A,B;
741   TSIJacobian    ijacobian;
742 
743   PetscFunctionBegin;
744   if (Arhs) *Arhs = NULL;
745   if (Brhs) *Brhs = NULL;
746   PetscCall(TSGetIJacobian(ts,&A,&B,&ijacobian,NULL));
747   if (Arhs) {
748     if (!ts->Arhs) {
749       if (ijacobian) {
750         PetscCall(MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&ts->Arhs));
751         PetscCall(TSSetMatStructure(ts,SAME_NONZERO_PATTERN));
752       } else {
753         ts->Arhs = A;
754         PetscCall(PetscObjectReference((PetscObject)A));
755       }
756     } else {
757       PetscBool flg;
758       PetscCall(SNESGetUseMatrixFree(ts->snes,NULL,&flg));
759       /* Handle case where user provided only RHSJacobian and used -snes_mf_operator */
760       if (flg && !ijacobian && ts->Arhs == ts->Brhs) {
761         PetscCall(PetscObjectDereference((PetscObject)ts->Arhs));
762         ts->Arhs = A;
763         PetscCall(PetscObjectReference((PetscObject)A));
764       }
765     }
766     *Arhs = ts->Arhs;
767   }
768   if (Brhs) {
769     if (!ts->Brhs) {
770       if (A != B) {
771         if (ijacobian) {
772           PetscCall(MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&ts->Brhs));
773         } else {
774           ts->Brhs = B;
775           PetscCall(PetscObjectReference((PetscObject)B));
776         }
777       } else {
778         PetscCall(PetscObjectReference((PetscObject)ts->Arhs));
779         ts->Brhs = ts->Arhs;
780       }
781     }
782     *Brhs = ts->Brhs;
783   }
784   PetscFunctionReturn(0);
785 }
786 
787 /*@
788    TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,U,Udot)=0
789 
790    Collective on TS
791 
792    Input Parameters:
793 +  ts - the TS context
794 .  t - current time
795 .  U - state vector
796 .  Udot - time derivative of state vector
797 -  imex - flag indicates if the method is IMEX so that the RHSFunction should be kept separate
798 
799    Output Parameter:
800 .  Y - right hand side
801 
802    Note:
803    Most users should not need to explicitly call this routine, as it
804    is used internally within the nonlinear solvers.
805 
806    If the user did did not write their equations in implicit form, this
807    function recasts them in implicit form.
808 
809    Level: developer
810 
811 .seealso: TSSetIFunction(), TSComputeRHSFunction()
812 @*/
813 PetscErrorCode TSComputeIFunction(TS ts,PetscReal t,Vec U,Vec Udot,Vec Y,PetscBool imex)
814 {
815   TSIFunction    ifunction;
816   TSRHSFunction  rhsfunction;
817   void           *ctx;
818   DM             dm;
819 
820   PetscFunctionBegin;
821   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
822   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
823   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
824   PetscValidHeaderSpecific(Y,VEC_CLASSID,5);
825 
826   PetscCall(TSGetDM(ts,&dm));
827   PetscCall(DMTSGetIFunction(dm,&ifunction,&ctx));
828   PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL));
829 
830   PetscCheck(rhsfunction || ifunction,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
831 
832   PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,Udot,Y));
833   if (ifunction) {
834     PetscStackPush("TS user implicit function");
835     PetscCall((*ifunction)(ts,t,U,Udot,Y,ctx));
836     PetscStackPop;
837     ts->ifuncs++;
838   }
839   if (imex) {
840     if (!ifunction) {
841       PetscCall(VecCopy(Udot,Y));
842     }
843   } else if (rhsfunction) {
844     if (ifunction) {
845       Vec Frhs;
846       PetscCall(TSGetRHSVec_Private(ts,&Frhs));
847       PetscCall(TSComputeRHSFunction(ts,t,U,Frhs));
848       PetscCall(VecAXPY(Y,-1,Frhs));
849     } else {
850       PetscCall(TSComputeRHSFunction(ts,t,U,Y));
851       PetscCall(VecAYPX(Y,-1,Udot));
852     }
853   }
854   PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,Udot,Y));
855   PetscFunctionReturn(0);
856 }
857 
858 /*
859    TSRecoverRHSJacobian - Recover the Jacobian matrix so that one can call TSComputeRHSJacobian() on it.
860 
861    Note:
862    This routine is needed when one switches from TSComputeIJacobian() to TSComputeRHSJacobian() because the Jacobian matrix may be shifted or scaled in TSComputeIJacobian().
863 
864 */
865 static PetscErrorCode TSRecoverRHSJacobian(TS ts,Mat A,Mat B)
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
869   PetscCheck(A == ts->Arhs,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Invalid Amat");
870   PetscCheck(B == ts->Brhs,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Invalid Bmat");
871 
872   if (ts->rhsjacobian.shift) {
873     PetscCall(MatShift(A,-ts->rhsjacobian.shift));
874   }
875   if (ts->rhsjacobian.scale == -1.) {
876     PetscCall(MatScale(A,-1));
877   }
878   if (B && B == ts->Brhs && A != B) {
879     if (ts->rhsjacobian.shift) {
880       PetscCall(MatShift(B,-ts->rhsjacobian.shift));
881     }
882     if (ts->rhsjacobian.scale == -1.) {
883       PetscCall(MatScale(B,-1));
884     }
885   }
886   ts->rhsjacobian.shift = 0;
887   ts->rhsjacobian.scale = 1.;
888   PetscFunctionReturn(0);
889 }
890 
891 /*@
892    TSComputeIJacobian - Evaluates the Jacobian of the DAE
893 
894    Collective on TS
895 
896    Input
897       Input Parameters:
898 +  ts - the TS context
899 .  t - current timestep
900 .  U - state vector
901 .  Udot - time derivative of state vector
902 .  shift - shift to apply, see note below
903 -  imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate
904 
905    Output Parameters:
906 +  A - Jacobian matrix
907 -  B - matrix from which the preconditioner is constructed; often the same as A
908 
909    Notes:
910    If F(t,U,Udot)=0 is the DAE, the required Jacobian is
911 
912    dF/dU + shift*dF/dUdot
913 
914    Most users should not need to explicitly call this routine, as it
915    is used internally within the nonlinear solvers.
916 
917    Level: developer
918 
919 .seealso:  TSSetIJacobian()
920 @*/
921 PetscErrorCode TSComputeIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,PetscBool imex)
922 {
923   TSIJacobian    ijacobian;
924   TSRHSJacobian  rhsjacobian;
925   DM             dm;
926   void           *ctx;
927 
928   PetscFunctionBegin;
929   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
930   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
931   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
932   PetscValidPointer(A,6);
933   PetscValidHeaderSpecific(A,MAT_CLASSID,6);
934   PetscValidPointer(B,7);
935   PetscValidHeaderSpecific(B,MAT_CLASSID,7);
936 
937   PetscCall(TSGetDM(ts,&dm));
938   PetscCall(DMTSGetIJacobian(dm,&ijacobian,&ctx));
939   PetscCall(DMTSGetRHSJacobian(dm,&rhsjacobian,NULL));
940 
941   PetscCheck(rhsjacobian || ijacobian,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
942 
943   PetscCall(PetscLogEventBegin(TS_JacobianEval,ts,U,A,B));
944   if (ijacobian) {
945     PetscStackPush("TS user implicit Jacobian");
946     PetscCall((*ijacobian)(ts,t,U,Udot,shift,A,B,ctx));
947     ts->ijacs++;
948     PetscStackPop;
949   }
950   if (imex) {
951     if (!ijacobian) {  /* system was written as Udot = G(t,U) */
952       PetscBool assembled;
953       if (rhsjacobian) {
954         Mat Arhs = NULL;
955         PetscCall(TSGetRHSMats_Private(ts,&Arhs,NULL));
956         if (A == Arhs) {
957           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 */
958           ts->rhsjacobian.time = PETSC_MIN_REAL;
959         }
960       }
961       PetscCall(MatZeroEntries(A));
962       PetscCall(MatAssembled(A,&assembled));
963       if (!assembled) {
964         PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
965         PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
966       }
967       PetscCall(MatShift(A,shift));
968       if (A != B) {
969         PetscCall(MatZeroEntries(B));
970         PetscCall(MatAssembled(B,&assembled));
971         if (!assembled) {
972           PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
973           PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
974         }
975         PetscCall(MatShift(B,shift));
976       }
977     }
978   } else {
979     Mat Arhs = NULL,Brhs = NULL;
980     if (rhsjacobian) { /* RHSJacobian needs to be converted to part of IJacobian if exists */
981       PetscCall(TSGetRHSMats_Private(ts,&Arhs,&Brhs));
982     }
983     if (Arhs == A) { /* No IJacobian matrix, so we only have the RHS matrix */
984       PetscObjectState Ustate;
985       PetscObjectId    Uid;
986       TSRHSFunction    rhsfunction;
987 
988       PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL));
989       PetscCall(PetscObjectStateGet((PetscObject)U,&Ustate));
990       PetscCall(PetscObjectGetId((PetscObject)U,&Uid));
991       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 */
992         PetscCall(MatShift(A,shift-ts->rhsjacobian.shift)); /* revert the old shift and add the new shift with a single call to MatShift */
993         if (A != B) {
994           PetscCall(MatShift(B,shift-ts->rhsjacobian.shift));
995         }
996       } else {
997         PetscBool flg;
998 
999         if (ts->rhsjacobian.reuse) { /* Undo the damage */
1000           /* MatScale has a short path for this case.
1001              However, this code path is taken the first time TSComputeRHSJacobian is called
1002              and the matrices have not been assembled yet */
1003           PetscCall(TSRecoverRHSJacobian(ts,A,B));
1004         }
1005         PetscCall(TSComputeRHSJacobian(ts,t,U,A,B));
1006         PetscCall(SNESGetUseMatrixFree(ts->snes,NULL,&flg));
1007         /* since -snes_mf_operator uses the full SNES function it does not need to be shifted or scaled here */
1008         if (!flg) {
1009           PetscCall(MatScale(A,-1));
1010           PetscCall(MatShift(A,shift));
1011         }
1012         if (A != B) {
1013           PetscCall(MatScale(B,-1));
1014           PetscCall(MatShift(B,shift));
1015         }
1016       }
1017       ts->rhsjacobian.scale = -1;
1018       ts->rhsjacobian.shift = shift;
1019     } else if (Arhs) {          /* Both IJacobian and RHSJacobian */
1020       if (!ijacobian) {         /* No IJacobian provided, but we have a separate RHS matrix */
1021         PetscCall(MatZeroEntries(A));
1022         PetscCall(MatShift(A,shift));
1023         if (A != B) {
1024           PetscCall(MatZeroEntries(B));
1025           PetscCall(MatShift(B,shift));
1026         }
1027       }
1028       PetscCall(TSComputeRHSJacobian(ts,t,U,Arhs,Brhs));
1029       PetscCall(MatAXPY(A,-1,Arhs,ts->axpy_pattern));
1030       if (A != B) {
1031         PetscCall(MatAXPY(B,-1,Brhs,ts->axpy_pattern));
1032       }
1033     }
1034   }
1035   PetscCall(PetscLogEventEnd(TS_JacobianEval,ts,U,A,B));
1036   PetscFunctionReturn(0);
1037 }
1038 
1039 /*@C
1040     TSSetRHSFunction - Sets the routine for evaluating the function,
1041     where U_t = G(t,u).
1042 
1043     Logically Collective on TS
1044 
1045     Input Parameters:
1046 +   ts - the TS context obtained from TSCreate()
1047 .   r - vector to put the computed right hand side (or NULL to have it created)
1048 .   f - routine for evaluating the right-hand-side function
1049 -   ctx - [optional] user-defined context for private data for the
1050           function evaluation routine (may be NULL)
1051 
1052     Calling sequence of f:
1053 $     PetscErrorCode f(TS ts,PetscReal t,Vec u,Vec F,void *ctx);
1054 
1055 +   ts - timestep context
1056 .   t - current timestep
1057 .   u - input vector
1058 .   F - function vector
1059 -   ctx - [optional] user-defined function context
1060 
1061     Level: beginner
1062 
1063     Notes:
1064     You must call this function or TSSetIFunction() to define your ODE. You cannot use this function when solving a DAE.
1065 
1066 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSSetIFunction()
1067 @*/
1068 PetscErrorCode  TSSetRHSFunction(TS ts,Vec r,PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*),void *ctx)
1069 {
1070   SNES           snes;
1071   Vec            ralloc = NULL;
1072   DM             dm;
1073 
1074   PetscFunctionBegin;
1075   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1076   if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2);
1077 
1078   PetscCall(TSGetDM(ts,&dm));
1079   PetscCall(DMTSSetRHSFunction(dm,f,ctx));
1080   PetscCall(TSGetSNES(ts,&snes));
1081   if (!r && !ts->dm && ts->vec_sol) {
1082     PetscCall(VecDuplicate(ts->vec_sol,&ralloc));
1083     r = ralloc;
1084   }
1085   PetscCall(SNESSetFunction(snes,r,SNESTSFormFunction,ts));
1086   PetscCall(VecDestroy(&ralloc));
1087   PetscFunctionReturn(0);
1088 }
1089 
1090 /*@C
1091     TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE
1092 
1093     Logically Collective on TS
1094 
1095     Input Parameters:
1096 +   ts - the TS context obtained from TSCreate()
1097 .   f - routine for evaluating the solution
1098 -   ctx - [optional] user-defined context for private data for the
1099           function evaluation routine (may be NULL)
1100 
1101     Calling sequence of f:
1102 $     PetscErrorCode f(TS ts,PetscReal t,Vec u,void *ctx);
1103 
1104 +   t - current timestep
1105 .   u - output vector
1106 -   ctx - [optional] user-defined function context
1107 
1108     Options Database:
1109 +  -ts_monitor_lg_error - create a graphical monitor of error history, requires user to have provided TSSetSolutionFunction()
1110 -  -ts_monitor_draw_error - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
1111 
1112     Notes:
1113     This routine is used for testing accuracy of time integration schemes when you already know the solution.
1114     If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to
1115     create closed-form solutions with non-physical forcing terms.
1116 
1117     For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history.
1118 
1119     Level: beginner
1120 
1121 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetForcingFunction(), TSSetSolution(), TSGetSolution(), TSMonitorLGError(), TSMonitorDrawError()
1122 @*/
1123 PetscErrorCode  TSSetSolutionFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx)
1124 {
1125   DM             dm;
1126 
1127   PetscFunctionBegin;
1128   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1129   PetscCall(TSGetDM(ts,&dm));
1130   PetscCall(DMTSSetSolutionFunction(dm,f,ctx));
1131   PetscFunctionReturn(0);
1132 }
1133 
1134 /*@C
1135     TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE
1136 
1137     Logically Collective on TS
1138 
1139     Input Parameters:
1140 +   ts - the TS context obtained from TSCreate()
1141 .   func - routine for evaluating the forcing function
1142 -   ctx - [optional] user-defined context for private data for the
1143           function evaluation routine (may be NULL)
1144 
1145     Calling sequence of func:
1146 $     PetscErrorCode func (TS ts,PetscReal t,Vec f,void *ctx);
1147 
1148 +   t - current timestep
1149 .   f - output vector
1150 -   ctx - [optional] user-defined function context
1151 
1152     Notes:
1153     This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to
1154     create closed-form solutions with a non-physical forcing term. It allows you to use the Method of Manufactored Solution without directly editing the
1155     definition of the problem you are solving and hence possibly introducing bugs.
1156 
1157     This replaces the ODE F(u,u_t,t) = 0 the TS is solving with F(u,u_t,t) - func(t) = 0
1158 
1159     This forcing function does not depend on the solution to the equations, it can only depend on spatial location, time, and possibly parameters, the
1160     parameters can be passed in the ctx variable.
1161 
1162     For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history.
1163 
1164     Level: beginner
1165 
1166 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetSolutionFunction()
1167 @*/
1168 PetscErrorCode  TSSetForcingFunction(TS ts,TSForcingFunction func,void *ctx)
1169 {
1170   DM             dm;
1171 
1172   PetscFunctionBegin;
1173   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1174   PetscCall(TSGetDM(ts,&dm));
1175   PetscCall(DMTSSetForcingFunction(dm,func,ctx));
1176   PetscFunctionReturn(0);
1177 }
1178 
1179 /*@C
1180    TSSetRHSJacobian - Sets the function to compute the Jacobian of G,
1181    where U_t = G(U,t), as well as the location to store the matrix.
1182 
1183    Logically Collective on TS
1184 
1185    Input Parameters:
1186 +  ts  - the TS context obtained from TSCreate()
1187 .  Amat - (approximate) Jacobian matrix
1188 .  Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
1189 .  f   - the Jacobian evaluation routine
1190 -  ctx - [optional] user-defined context for private data for the
1191          Jacobian evaluation routine (may be NULL)
1192 
1193    Calling sequence of f:
1194 $     PetscErrorCode f(TS ts,PetscReal t,Vec u,Mat A,Mat B,void *ctx);
1195 
1196 +  t - current timestep
1197 .  u - input vector
1198 .  Amat - (approximate) Jacobian matrix
1199 .  Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
1200 -  ctx - [optional] user-defined context for matrix evaluation routine
1201 
1202    Notes:
1203    You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value
1204 
1205    The TS solver may modify the nonzero structure and the entries of the matrices Amat and Pmat between the calls to f()
1206    You should not assume the values are the same in the next call to f() as you set them in the previous call.
1207 
1208    Level: beginner
1209 
1210 .seealso: SNESComputeJacobianDefaultColor(), TSSetRHSFunction(), TSRHSJacobianSetReuse(), TSSetIJacobian()
1211 
1212 @*/
1213 PetscErrorCode  TSSetRHSJacobian(TS ts,Mat Amat,Mat Pmat,TSRHSJacobian f,void *ctx)
1214 {
1215   SNES           snes;
1216   DM             dm;
1217   TSIJacobian    ijacobian;
1218 
1219   PetscFunctionBegin;
1220   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1221   if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
1222   if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3);
1223   if (Amat) PetscCheckSameComm(ts,1,Amat,2);
1224   if (Pmat) PetscCheckSameComm(ts,1,Pmat,3);
1225 
1226   PetscCall(TSGetDM(ts,&dm));
1227   PetscCall(DMTSSetRHSJacobian(dm,f,ctx));
1228   PetscCall(DMTSGetIJacobian(dm,&ijacobian,NULL));
1229   PetscCall(TSGetSNES(ts,&snes));
1230   if (!ijacobian) {
1231     PetscCall(SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts));
1232   }
1233   if (Amat) {
1234     PetscCall(PetscObjectReference((PetscObject)Amat));
1235     PetscCall(MatDestroy(&ts->Arhs));
1236     ts->Arhs = Amat;
1237   }
1238   if (Pmat) {
1239     PetscCall(PetscObjectReference((PetscObject)Pmat));
1240     PetscCall(MatDestroy(&ts->Brhs));
1241     ts->Brhs = Pmat;
1242   }
1243   PetscFunctionReturn(0);
1244 }
1245 
1246 /*@C
1247    TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved.
1248 
1249    Logically Collective on TS
1250 
1251    Input Parameters:
1252 +  ts  - the TS context obtained from TSCreate()
1253 .  r   - vector to hold the residual (or NULL to have it created internally)
1254 .  f   - the function evaluation routine
1255 -  ctx - user-defined context for private data for the function evaluation routine (may be NULL)
1256 
1257    Calling sequence of f:
1258 $     PetscErrorCode f(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx);
1259 
1260 +  t   - time at step/stage being solved
1261 .  u   - state vector
1262 .  u_t - time derivative of state vector
1263 .  F   - function vector
1264 -  ctx - [optional] user-defined context for matrix evaluation routine
1265 
1266    Important:
1267    The user MUST call either this routine or TSSetRHSFunction() to define the ODE.  When solving DAEs you must use this function.
1268 
1269    Level: beginner
1270 
1271 .seealso: TSSetRHSJacobian(), TSSetRHSFunction(), TSSetIJacobian()
1272 @*/
1273 PetscErrorCode  TSSetIFunction(TS ts,Vec r,TSIFunction f,void *ctx)
1274 {
1275   SNES           snes;
1276   Vec            ralloc = NULL;
1277   DM             dm;
1278 
1279   PetscFunctionBegin;
1280   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1281   if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2);
1282 
1283   PetscCall(TSGetDM(ts,&dm));
1284   PetscCall(DMTSSetIFunction(dm,f,ctx));
1285 
1286   PetscCall(TSGetSNES(ts,&snes));
1287   if (!r && !ts->dm && ts->vec_sol) {
1288     PetscCall(VecDuplicate(ts->vec_sol,&ralloc));
1289     r  = ralloc;
1290   }
1291   PetscCall(SNESSetFunction(snes,r,SNESTSFormFunction,ts));
1292   PetscCall(VecDestroy(&ralloc));
1293   PetscFunctionReturn(0);
1294 }
1295 
1296 /*@C
1297    TSGetIFunction - Returns the vector where the implicit residual is stored and the function/context to compute it.
1298 
1299    Not Collective
1300 
1301    Input Parameter:
1302 .  ts - the TS context
1303 
1304    Output Parameters:
1305 +  r - vector to hold residual (or NULL)
1306 .  func - the function to compute residual (or NULL)
1307 -  ctx - the function context (or NULL)
1308 
1309    Level: advanced
1310 
1311 .seealso: TSSetIFunction(), SNESGetFunction()
1312 @*/
1313 PetscErrorCode TSGetIFunction(TS ts,Vec *r,TSIFunction *func,void **ctx)
1314 {
1315   SNES           snes;
1316   DM             dm;
1317 
1318   PetscFunctionBegin;
1319   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1320   PetscCall(TSGetSNES(ts,&snes));
1321   PetscCall(SNESGetFunction(snes,r,NULL,NULL));
1322   PetscCall(TSGetDM(ts,&dm));
1323   PetscCall(DMTSGetIFunction(dm,func,ctx));
1324   PetscFunctionReturn(0);
1325 }
1326 
1327 /*@C
1328    TSGetRHSFunction - Returns the vector where the right hand side is stored and the function/context to compute it.
1329 
1330    Not Collective
1331 
1332    Input Parameter:
1333 .  ts - the TS context
1334 
1335    Output Parameters:
1336 +  r - vector to hold computed right hand side (or NULL)
1337 .  func - the function to compute right hand side (or NULL)
1338 -  ctx - the function context (or NULL)
1339 
1340    Level: advanced
1341 
1342 .seealso: TSSetRHSFunction(), SNESGetFunction()
1343 @*/
1344 PetscErrorCode TSGetRHSFunction(TS ts,Vec *r,TSRHSFunction *func,void **ctx)
1345 {
1346   SNES           snes;
1347   DM             dm;
1348 
1349   PetscFunctionBegin;
1350   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1351   PetscCall(TSGetSNES(ts,&snes));
1352   PetscCall(SNESGetFunction(snes,r,NULL,NULL));
1353   PetscCall(TSGetDM(ts,&dm));
1354   PetscCall(DMTSGetRHSFunction(dm,func,ctx));
1355   PetscFunctionReturn(0);
1356 }
1357 
1358 /*@C
1359    TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function
1360         provided with TSSetIFunction().
1361 
1362    Logically Collective on TS
1363 
1364    Input Parameters:
1365 +  ts  - the TS context obtained from TSCreate()
1366 .  Amat - (approximate) Jacobian matrix
1367 .  Pmat - matrix used to compute preconditioner (usually the same as Amat)
1368 .  f   - the Jacobian evaluation routine
1369 -  ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL)
1370 
1371    Calling sequence of f:
1372 $    PetscErrorCode f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat Amat,Mat Pmat,void *ctx);
1373 
1374 +  t    - time at step/stage being solved
1375 .  U    - state vector
1376 .  U_t  - time derivative of state vector
1377 .  a    - shift
1378 .  Amat - (approximate) Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
1379 .  Pmat - matrix used for constructing preconditioner, usually the same as Amat
1380 -  ctx  - [optional] user-defined context for matrix evaluation routine
1381 
1382    Notes:
1383    The matrices Amat and Pmat are exactly the matrices that are used by SNES for the nonlinear solve.
1384 
1385    If you know the operator Amat has a null space you can use MatSetNullSpace() and MatSetTransposeNullSpace() to supply the null
1386    space to Amat and the KSP solvers will automatically use that null space as needed during the solution process.
1387 
1388    The matrix dF/dU + a*dF/dU_t you provide turns out to be
1389    the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
1390    The time integrator internally approximates U_t by W+a*U where the positive "shift"
1391    a and vector W depend on the integration method, step size, and past states. For example with
1392    the backward Euler method a = 1/dt and W = -a*U(previous timestep) so
1393    W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt
1394 
1395    You must set all the diagonal entries of the matrices, if they are zero you must still set them with a zero value
1396 
1397    The TS solver may modify the nonzero structure and the entries of the matrices Amat and Pmat between the calls to f()
1398    You should not assume the values are the same in the next call to f() as you set them in the previous call.
1399 
1400    Level: beginner
1401 
1402 .seealso: TSSetIFunction(), TSSetRHSJacobian(), SNESComputeJacobianDefaultColor(), SNESComputeJacobianDefault(), TSSetRHSFunction()
1403 
1404 @*/
1405 PetscErrorCode  TSSetIJacobian(TS ts,Mat Amat,Mat Pmat,TSIJacobian f,void *ctx)
1406 {
1407   SNES           snes;
1408   DM             dm;
1409 
1410   PetscFunctionBegin;
1411   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1412   if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
1413   if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3);
1414   if (Amat) PetscCheckSameComm(ts,1,Amat,2);
1415   if (Pmat) PetscCheckSameComm(ts,1,Pmat,3);
1416 
1417   PetscCall(TSGetDM(ts,&dm));
1418   PetscCall(DMTSSetIJacobian(dm,f,ctx));
1419 
1420   PetscCall(TSGetSNES(ts,&snes));
1421   PetscCall(SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts));
1422   PetscFunctionReturn(0);
1423 }
1424 
1425 /*@
1426    TSRHSJacobianSetReuse - restore RHS Jacobian before re-evaluating.  Without this flag, TS will change the sign and
1427    shift the RHS Jacobian for a finite-time-step implicit solve, in which case the user function will need to recompute
1428    the entire Jacobian.  The reuse flag must be set if the evaluation function will assume that the matrix entries have
1429    not been changed by the TS.
1430 
1431    Logically Collective
1432 
1433    Input Parameters:
1434 +  ts - TS context obtained from TSCreate()
1435 -  reuse - PETSC_TRUE if the RHS Jacobian
1436 
1437    Level: intermediate
1438 
1439 .seealso: TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
1440 @*/
1441 PetscErrorCode TSRHSJacobianSetReuse(TS ts,PetscBool reuse)
1442 {
1443   PetscFunctionBegin;
1444   ts->rhsjacobian.reuse = reuse;
1445   PetscFunctionReturn(0);
1446 }
1447 
1448 /*@C
1449    TSSetI2Function - Set the function to compute F(t,U,U_t,U_tt) where F = 0 is the DAE to be solved.
1450 
1451    Logically Collective on TS
1452 
1453    Input Parameters:
1454 +  ts  - the TS context obtained from TSCreate()
1455 .  F   - vector to hold the residual (or NULL to have it created internally)
1456 .  fun - the function evaluation routine
1457 -  ctx - user-defined context for private data for the function evaluation routine (may be NULL)
1458 
1459    Calling sequence of fun:
1460 $     PetscErrorCode fun(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,Vec F,ctx);
1461 
1462 +  t    - time at step/stage being solved
1463 .  U    - state vector
1464 .  U_t  - time derivative of state vector
1465 .  U_tt - second time derivative of state vector
1466 .  F    - function vector
1467 -  ctx  - [optional] user-defined context for matrix evaluation routine (may be NULL)
1468 
1469    Level: beginner
1470 
1471 .seealso: TSSetI2Jacobian(), TSSetIFunction(), TSCreate(), TSSetRHSFunction()
1472 @*/
1473 PetscErrorCode TSSetI2Function(TS ts,Vec F,TSI2Function fun,void *ctx)
1474 {
1475   DM             dm;
1476 
1477   PetscFunctionBegin;
1478   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1479   if (F) PetscValidHeaderSpecific(F,VEC_CLASSID,2);
1480   PetscCall(TSSetIFunction(ts,F,NULL,NULL));
1481   PetscCall(TSGetDM(ts,&dm));
1482   PetscCall(DMTSSetI2Function(dm,fun,ctx));
1483   PetscFunctionReturn(0);
1484 }
1485 
1486 /*@C
1487   TSGetI2Function - Returns the vector where the implicit residual is stored and the function/context to compute it.
1488 
1489   Not Collective
1490 
1491   Input Parameter:
1492 . ts - the TS context
1493 
1494   Output Parameters:
1495 + r - vector to hold residual (or NULL)
1496 . fun - the function to compute residual (or NULL)
1497 - ctx - the function context (or NULL)
1498 
1499   Level: advanced
1500 
1501 .seealso: TSSetIFunction(), SNESGetFunction(), TSCreate()
1502 @*/
1503 PetscErrorCode TSGetI2Function(TS ts,Vec *r,TSI2Function *fun,void **ctx)
1504 {
1505   SNES           snes;
1506   DM             dm;
1507 
1508   PetscFunctionBegin;
1509   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1510   PetscCall(TSGetSNES(ts,&snes));
1511   PetscCall(SNESGetFunction(snes,r,NULL,NULL));
1512   PetscCall(TSGetDM(ts,&dm));
1513   PetscCall(DMTSGetI2Function(dm,fun,ctx));
1514   PetscFunctionReturn(0);
1515 }
1516 
1517 /*@C
1518    TSSetI2Jacobian - Set the function to compute the matrix dF/dU + v*dF/dU_t  + a*dF/dU_tt
1519         where F(t,U,U_t,U_tt) is the function you provided with TSSetI2Function().
1520 
1521    Logically Collective on TS
1522 
1523    Input Parameters:
1524 +  ts  - the TS context obtained from TSCreate()
1525 .  J   - Jacobian matrix
1526 .  P   - preconditioning matrix for J (may be same as J)
1527 .  jac - the Jacobian evaluation routine
1528 -  ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL)
1529 
1530    Calling sequence of jac:
1531 $    PetscErrorCode jac(TS ts,PetscReal t,Vec U,Vec U_t,Vec U_tt,PetscReal v,PetscReal a,Mat J,Mat P,void *ctx);
1532 
1533 +  t    - time at step/stage being solved
1534 .  U    - state vector
1535 .  U_t  - time derivative of state vector
1536 .  U_tt - second time derivative of state vector
1537 .  v    - shift for U_t
1538 .  a    - shift for U_tt
1539 .  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
1540 .  P    - preconditioning matrix for J, may be same as J
1541 -  ctx  - [optional] user-defined context for matrix evaluation routine
1542 
1543    Notes:
1544    The matrices J and P are exactly the matrices that are used by SNES for the nonlinear solve.
1545 
1546    The matrix dF/dU + v*dF/dU_t + a*dF/dU_tt you provide turns out to be
1547    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.
1548    The time integrator internally approximates U_t by W+v*U and U_tt by W'+a*U  where the positive "shift"
1549    parameters 'v' and 'a' and vectors W, W' depend on the integration method, step size, and past states.
1550 
1551    Level: beginner
1552 
1553 .seealso: TSSetI2Function(), TSGetI2Jacobian()
1554 @*/
1555 PetscErrorCode TSSetI2Jacobian(TS ts,Mat J,Mat P,TSI2Jacobian jac,void *ctx)
1556 {
1557   DM             dm;
1558 
1559   PetscFunctionBegin;
1560   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1561   if (J) PetscValidHeaderSpecific(J,MAT_CLASSID,2);
1562   if (P) PetscValidHeaderSpecific(P,MAT_CLASSID,3);
1563   PetscCall(TSSetIJacobian(ts,J,P,NULL,NULL));
1564   PetscCall(TSGetDM(ts,&dm));
1565   PetscCall(DMTSSetI2Jacobian(dm,jac,ctx));
1566   PetscFunctionReturn(0);
1567 }
1568 
1569 /*@C
1570   TSGetI2Jacobian - Returns the implicit Jacobian at the present timestep.
1571 
1572   Not Collective, but parallel objects are returned if TS is parallel
1573 
1574   Input Parameter:
1575 . ts  - The TS context obtained from TSCreate()
1576 
1577   Output Parameters:
1578 + J  - The (approximate) Jacobian of F(t,U,U_t,U_tt)
1579 . P - The matrix from which the preconditioner is constructed, often the same as J
1580 . jac - The function to compute the Jacobian matrices
1581 - ctx - User-defined context for Jacobian evaluation routine
1582 
1583   Notes:
1584     You can pass in NULL for any return argument you do not need.
1585 
1586   Level: advanced
1587 
1588 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetStepNumber(), TSSetI2Jacobian(), TSGetI2Function(), TSCreate()
1589 
1590 @*/
1591 PetscErrorCode  TSGetI2Jacobian(TS ts,Mat *J,Mat *P,TSI2Jacobian *jac,void **ctx)
1592 {
1593   SNES           snes;
1594   DM             dm;
1595 
1596   PetscFunctionBegin;
1597   PetscCall(TSGetSNES(ts,&snes));
1598   PetscCall(SNESSetUpMatrices(snes));
1599   PetscCall(SNESGetJacobian(snes,J,P,NULL,NULL));
1600   PetscCall(TSGetDM(ts,&dm));
1601   PetscCall(DMTSGetI2Jacobian(dm,jac,ctx));
1602   PetscFunctionReturn(0);
1603 }
1604 
1605 /*@
1606   TSComputeI2Function - Evaluates the DAE residual written in implicit form F(t,U,U_t,U_tt) = 0
1607 
1608   Collective on TS
1609 
1610   Input Parameters:
1611 + ts - the TS context
1612 . t - current time
1613 . U - state vector
1614 . V - time derivative of state vector (U_t)
1615 - A - second time derivative of state vector (U_tt)
1616 
1617   Output Parameter:
1618 . F - the residual vector
1619 
1620   Note:
1621   Most users should not need to explicitly call this routine, as it
1622   is used internally within the nonlinear solvers.
1623 
1624   Level: developer
1625 
1626 .seealso: TSSetI2Function(), TSGetI2Function()
1627 @*/
1628 PetscErrorCode TSComputeI2Function(TS ts,PetscReal t,Vec U,Vec V,Vec A,Vec F)
1629 {
1630   DM             dm;
1631   TSI2Function   I2Function;
1632   void           *ctx;
1633   TSRHSFunction  rhsfunction;
1634 
1635   PetscFunctionBegin;
1636   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1637   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1638   PetscValidHeaderSpecific(V,VEC_CLASSID,4);
1639   PetscValidHeaderSpecific(A,VEC_CLASSID,5);
1640   PetscValidHeaderSpecific(F,VEC_CLASSID,6);
1641 
1642   PetscCall(TSGetDM(ts,&dm));
1643   PetscCall(DMTSGetI2Function(dm,&I2Function,&ctx));
1644   PetscCall(DMTSGetRHSFunction(dm,&rhsfunction,NULL));
1645 
1646   if (!I2Function) {
1647     PetscCall(TSComputeIFunction(ts,t,U,A,F,PETSC_FALSE));
1648     PetscFunctionReturn(0);
1649   }
1650 
1651   PetscCall(PetscLogEventBegin(TS_FunctionEval,ts,U,V,F));
1652 
1653   PetscStackPush("TS user implicit function");
1654   PetscCall(I2Function(ts,t,U,V,A,F,ctx));
1655   PetscStackPop;
1656 
1657   if (rhsfunction) {
1658     Vec Frhs;
1659     PetscCall(TSGetRHSVec_Private(ts,&Frhs));
1660     PetscCall(TSComputeRHSFunction(ts,t,U,Frhs));
1661     PetscCall(VecAXPY(F,-1,Frhs));
1662   }
1663 
1664   PetscCall(PetscLogEventEnd(TS_FunctionEval,ts,U,V,F));
1665   PetscFunctionReturn(0);
1666 }
1667 
1668 /*@
1669   TSComputeI2Jacobian - Evaluates the Jacobian of the DAE
1670 
1671   Collective on TS
1672 
1673   Input Parameters:
1674 + ts - the TS context
1675 . t - current timestep
1676 . U - state vector
1677 . V - time derivative of state vector
1678 . A - second time derivative of state vector
1679 . shiftV - shift to apply, see note below
1680 - shiftA - shift to apply, see note below
1681 
1682   Output Parameters:
1683 + J - Jacobian matrix
1684 - P - optional preconditioning matrix
1685 
1686   Notes:
1687   If F(t,U,V,A)=0 is the DAE, the required Jacobian is
1688 
1689   dF/dU + shiftV*dF/dV + shiftA*dF/dA
1690 
1691   Most users should not need to explicitly call this routine, as it
1692   is used internally within the nonlinear solvers.
1693 
1694   Level: developer
1695 
1696 .seealso:  TSSetI2Jacobian()
1697 @*/
1698 PetscErrorCode TSComputeI2Jacobian(TS ts,PetscReal t,Vec U,Vec V,Vec A,PetscReal shiftV,PetscReal shiftA,Mat J,Mat P)
1699 {
1700   DM             dm;
1701   TSI2Jacobian   I2Jacobian;
1702   void           *ctx;
1703   TSRHSJacobian  rhsjacobian;
1704 
1705   PetscFunctionBegin;
1706   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1707   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
1708   PetscValidHeaderSpecific(V,VEC_CLASSID,4);
1709   PetscValidHeaderSpecific(A,VEC_CLASSID,5);
1710   PetscValidHeaderSpecific(J,MAT_CLASSID,8);
1711   PetscValidHeaderSpecific(P,MAT_CLASSID,9);
1712 
1713   PetscCall(TSGetDM(ts,&dm));
1714   PetscCall(DMTSGetI2Jacobian(dm,&I2Jacobian,&ctx));
1715   PetscCall(DMTSGetRHSJacobian(dm,&rhsjacobian,NULL));
1716 
1717   if (!I2Jacobian) {
1718     PetscCall(TSComputeIJacobian(ts,t,U,A,shiftA,J,P,PETSC_FALSE));
1719     PetscFunctionReturn(0);
1720   }
1721 
1722   PetscCall(PetscLogEventBegin(TS_JacobianEval,ts,U,J,P));
1723 
1724   PetscStackPush("TS user implicit Jacobian");
1725   PetscCall(I2Jacobian(ts,t,U,V,A,shiftV,shiftA,J,P,ctx));
1726   PetscStackPop;
1727 
1728   if (rhsjacobian) {
1729     Mat Jrhs,Prhs;
1730     PetscCall(TSGetRHSMats_Private(ts,&Jrhs,&Prhs));
1731     PetscCall(TSComputeRHSJacobian(ts,t,U,Jrhs,Prhs));
1732     PetscCall(MatAXPY(J,-1,Jrhs,ts->axpy_pattern));
1733     if (P != J) PetscCall(MatAXPY(P,-1,Prhs,ts->axpy_pattern));
1734   }
1735 
1736   PetscCall(PetscLogEventEnd(TS_JacobianEval,ts,U,J,P));
1737   PetscFunctionReturn(0);
1738 }
1739 
1740 /*@C
1741    TSSetTransientVariable - sets function to transform from state to transient variables
1742 
1743    Logically Collective
1744 
1745    Input Parameters:
1746 +  ts - time stepping context on which to change the transient variable
1747 .  tvar - a function that transforms to transient variables
1748 -  ctx - a context for tvar
1749 
1750     Calling sequence of tvar:
1751 $     PetscErrorCode tvar(TS ts,Vec p,Vec c,void *ctx);
1752 
1753 +   ts - timestep context
1754 .   p - input vector (primative form)
1755 .   c - output vector, transient variables (conservative form)
1756 -   ctx - [optional] user-defined function context
1757 
1758    Level: advanced
1759 
1760    Notes:
1761    This is typically used to transform from primitive to conservative variables so that a time integrator (e.g., TSBDF)
1762    can be conservative.  In this context, primitive variables P are used to model the state (e.g., because they lead to
1763    well-conditioned formulations even in limiting cases such as low-Mach or zero porosity).  The transient variable is
1764    C(P), specified by calling this function.  An IFunction thus receives arguments (P, Cdot) and the IJacobian must be
1765    evaluated via the chain rule, as in
1766 
1767      dF/dP + shift * dF/dCdot dC/dP.
1768 
1769 .seealso: DMTSSetTransientVariable(), DMTSGetTransientVariable(), TSSetIFunction(), TSSetIJacobian()
1770 @*/
1771 PetscErrorCode TSSetTransientVariable(TS ts,TSTransientVariable tvar,void *ctx)
1772 {
1773   DM             dm;
1774 
1775   PetscFunctionBegin;
1776   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1777   PetscCall(TSGetDM(ts,&dm));
1778   PetscCall(DMTSSetTransientVariable(dm,tvar,ctx));
1779   PetscFunctionReturn(0);
1780 }
1781 
1782 /*@
1783    TSComputeTransientVariable - transforms state (primitive) variables to transient (conservative) variables
1784 
1785    Logically Collective
1786 
1787    Input Parameters:
1788 +  ts - TS on which to compute
1789 -  U - state vector to be transformed to transient variables
1790 
1791    Output Parameters:
1792 .  C - transient (conservative) variable
1793 
1794    Developer Notes:
1795    If DMTSSetTransientVariable() has not been called, then C is not modified in this routine and C=NULL is allowed.
1796    This makes it safe to call without a guard.  One can use TSHasTransientVariable() to check if transient variables are
1797    being used.
1798 
1799    Level: developer
1800 
1801 .seealso: DMTSSetTransientVariable(), TSComputeIFunction(), TSComputeIJacobian()
1802 @*/
1803 PetscErrorCode TSComputeTransientVariable(TS ts,Vec U,Vec C)
1804 {
1805   DM             dm;
1806   DMTS           dmts;
1807 
1808   PetscFunctionBegin;
1809   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1810   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
1811   PetscCall(TSGetDM(ts,&dm));
1812   PetscCall(DMGetDMTS(dm,&dmts));
1813   if (dmts->ops->transientvar) {
1814     PetscValidHeaderSpecific(C,VEC_CLASSID,3);
1815     PetscCall((*dmts->ops->transientvar)(ts,U,C,dmts->transientvarctx));
1816   }
1817   PetscFunctionReturn(0);
1818 }
1819 
1820 /*@
1821    TSHasTransientVariable - determine whether transient variables have been set
1822 
1823    Logically Collective
1824 
1825    Input Parameters:
1826 .  ts - TS on which to compute
1827 
1828    Output Parameters:
1829 .  has - PETSC_TRUE if transient variables have been set
1830 
1831    Level: developer
1832 
1833 .seealso: DMTSSetTransientVariable(), TSComputeTransientVariable()
1834 @*/
1835 PetscErrorCode TSHasTransientVariable(TS ts,PetscBool *has)
1836 {
1837   DM             dm;
1838   DMTS           dmts;
1839 
1840   PetscFunctionBegin;
1841   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1842   PetscCall(TSGetDM(ts,&dm));
1843   PetscCall(DMGetDMTS(dm,&dmts));
1844   *has = dmts->ops->transientvar ? PETSC_TRUE : PETSC_FALSE;
1845   PetscFunctionReturn(0);
1846 }
1847 
1848 /*@
1849    TS2SetSolution - Sets the initial solution and time derivative vectors
1850    for use by the TS routines handling second order equations.
1851 
1852    Logically Collective on TS
1853 
1854    Input Parameters:
1855 +  ts - the TS context obtained from TSCreate()
1856 .  u - the solution vector
1857 -  v - the time derivative vector
1858 
1859    Level: beginner
1860 
1861 @*/
1862 PetscErrorCode  TS2SetSolution(TS ts,Vec u,Vec v)
1863 {
1864   PetscFunctionBegin;
1865   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1866   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
1867   PetscValidHeaderSpecific(v,VEC_CLASSID,3);
1868   PetscCall(TSSetSolution(ts,u));
1869   PetscCall(PetscObjectReference((PetscObject)v));
1870   PetscCall(VecDestroy(&ts->vec_dot));
1871   ts->vec_dot = v;
1872   PetscFunctionReturn(0);
1873 }
1874 
1875 /*@
1876    TS2GetSolution - Returns the solution and time derivative at the present timestep
1877    for second order equations. It is valid to call this routine inside the function
1878    that you are evaluating in order to move to the new timestep. This vector not
1879    changed until the solution at the next timestep has been calculated.
1880 
1881    Not Collective, but Vec returned is parallel if TS is parallel
1882 
1883    Input Parameter:
1884 .  ts - the TS context obtained from TSCreate()
1885 
1886    Output Parameters:
1887 +  u - the vector containing the solution
1888 -  v - the vector containing the time derivative
1889 
1890    Level: intermediate
1891 
1892 .seealso: TS2SetSolution(), TSGetTimeStep(), TSGetTime()
1893 
1894 @*/
1895 PetscErrorCode  TS2GetSolution(TS ts,Vec *u,Vec *v)
1896 {
1897   PetscFunctionBegin;
1898   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1899   if (u) PetscValidPointer(u,2);
1900   if (v) PetscValidPointer(v,3);
1901   if (u) *u = ts->vec_sol;
1902   if (v) *v = ts->vec_dot;
1903   PetscFunctionReturn(0);
1904 }
1905 
1906 /*@C
1907   TSLoad - Loads a KSP that has been stored in binary  with KSPView().
1908 
1909   Collective on PetscViewer
1910 
1911   Input Parameters:
1912 + newdm - the newly loaded TS, this needs to have been created with TSCreate() or
1913            some related function before a call to TSLoad().
1914 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen()
1915 
1916    Level: intermediate
1917 
1918   Notes:
1919    The type is determined by the data in the file, any type set into the TS before this call is ignored.
1920 
1921   Notes for advanced users:
1922   Most users should not need to know the details of the binary storage
1923   format, since TSLoad() and TSView() completely hide these details.
1924   But for anyone who's interested, the standard binary matrix storage
1925   format is
1926 .vb
1927      has not yet been determined
1928 .ve
1929 
1930 .seealso: PetscViewerBinaryOpen(), TSView(), MatLoad(), VecLoad()
1931 @*/
1932 PetscErrorCode  TSLoad(TS ts, PetscViewer viewer)
1933 {
1934   PetscBool      isbinary;
1935   PetscInt       classid;
1936   char           type[256];
1937   DMTS           sdm;
1938   DM             dm;
1939 
1940   PetscFunctionBegin;
1941   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1942   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1943   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
1944   PetscCheck(isbinary,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
1945 
1946   PetscCall(PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT));
1947   PetscCheck(classid == TS_FILE_CLASSID,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Not TS next in file");
1948   PetscCall(PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR));
1949   PetscCall(TSSetType(ts, type));
1950   if (ts->ops->load) {
1951     PetscCall((*ts->ops->load)(ts,viewer));
1952   }
1953   PetscCall(DMCreate(PetscObjectComm((PetscObject)ts),&dm));
1954   PetscCall(DMLoad(dm,viewer));
1955   PetscCall(TSSetDM(ts,dm));
1956   PetscCall(DMCreateGlobalVector(ts->dm,&ts->vec_sol));
1957   PetscCall(VecLoad(ts->vec_sol,viewer));
1958   PetscCall(DMGetDMTS(ts->dm,&sdm));
1959   PetscCall(DMTSLoad(sdm,viewer));
1960   PetscFunctionReturn(0);
1961 }
1962 
1963 #include <petscdraw.h>
1964 #if defined(PETSC_HAVE_SAWS)
1965 #include <petscviewersaws.h>
1966 #endif
1967 
1968 /*@C
1969    TSViewFromOptions - View from Options
1970 
1971    Collective on TS
1972 
1973    Input Parameters:
1974 +  A - the application ordering context
1975 .  obj - Optional object
1976 -  name - command line option
1977 
1978    Level: intermediate
1979 .seealso:  TS, TSView, PetscObjectViewFromOptions(), TSCreate()
1980 @*/
1981 PetscErrorCode  TSViewFromOptions(TS A,PetscObject obj,const char name[])
1982 {
1983   PetscFunctionBegin;
1984   PetscValidHeaderSpecific(A,TS_CLASSID,1);
1985   PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name));
1986   PetscFunctionReturn(0);
1987 }
1988 
1989 /*@C
1990     TSView - Prints the TS data structure.
1991 
1992     Collective on TS
1993 
1994     Input Parameters:
1995 +   ts - the TS context obtained from TSCreate()
1996 -   viewer - visualization context
1997 
1998     Options Database Key:
1999 .   -ts_view - calls TSView() at end of TSStep()
2000 
2001     Notes:
2002     The available visualization contexts include
2003 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
2004 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
2005          output where only the first processor opens
2006          the file.  All other processors send their
2007          data to the first processor to print.
2008 
2009     The user can open an alternative visualization context with
2010     PetscViewerASCIIOpen() - output to a specified file.
2011 
2012     In the debugger you can do "call TSView(ts,0)" to display the TS solver. (The same holds for any PETSc object viewer).
2013 
2014     Level: beginner
2015 
2016 .seealso: PetscViewerASCIIOpen()
2017 @*/
2018 PetscErrorCode  TSView(TS ts,PetscViewer viewer)
2019 {
2020   TSType         type;
2021   PetscBool      iascii,isstring,isundials,isbinary,isdraw;
2022   DMTS           sdm;
2023 #if defined(PETSC_HAVE_SAWS)
2024   PetscBool      issaws;
2025 #endif
2026 
2027   PetscFunctionBegin;
2028   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2029   if (!viewer) {
2030     PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts),&viewer));
2031   }
2032   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
2033   PetscCheckSameComm(ts,1,viewer,2);
2034 
2035   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
2036   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
2037   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
2038   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
2039 #if defined(PETSC_HAVE_SAWS)
2040   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws));
2041 #endif
2042   if (iascii) {
2043     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer));
2044     if (ts->ops->view) {
2045       PetscCall(PetscViewerASCIIPushTab(viewer));
2046       PetscCall((*ts->ops->view)(ts,viewer));
2047       PetscCall(PetscViewerASCIIPopTab(viewer));
2048     }
2049     if (ts->max_steps < PETSC_MAX_INT) {
2050       PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum steps=%D\n",ts->max_steps));
2051     }
2052     if (ts->max_time < PETSC_MAX_REAL) {
2053       PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum time=%g\n",(double)ts->max_time));
2054     }
2055     if (ts->ifuncs) {
2056       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of I function evaluations=%D\n",ts->ifuncs));
2057     }
2058     if (ts->ijacs) {
2059       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of I Jacobian evaluations=%D\n",ts->ijacs));
2060     }
2061     if (ts->rhsfuncs) {
2062       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of RHS function evaluations=%D\n",ts->rhsfuncs));
2063     }
2064     if (ts->rhsjacs) {
2065       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of RHS Jacobian evaluations=%D\n",ts->rhsjacs));
2066     }
2067     if (ts->usessnes) {
2068       PetscBool lin;
2069       if (ts->problem_type == TS_NONLINEAR) {
2070         PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of nonlinear solver iterations=%D\n",ts->snes_its));
2071       }
2072       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of linear solver iterations=%D\n",ts->ksp_its));
2073       PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes,&lin,SNESKSPONLY,SNESKSPTRANSPOSEONLY,""));
2074       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of %slinear solve failures=%D\n",lin ? "" : "non",ts->num_snes_failures));
2075     }
2076     PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of rejected steps=%D\n",ts->reject));
2077     if (ts->vrtol) {
2078       PetscCall(PetscViewerASCIIPrintf(viewer,"  using vector of relative error tolerances, "));
2079     } else {
2080       PetscCall(PetscViewerASCIIPrintf(viewer,"  using relative error tolerance of %g, ",(double)ts->rtol));
2081     }
2082     if (ts->vatol) {
2083       PetscCall(PetscViewerASCIIPrintf(viewer,"  using vector of absolute error tolerances\n"));
2084     } else {
2085       PetscCall(PetscViewerASCIIPrintf(viewer,"  using absolute error tolerance of %g\n",(double)ts->atol));
2086     }
2087     PetscCall(PetscViewerASCIIPushTab(viewer));
2088     PetscCall(TSAdaptView(ts->adapt,viewer));
2089     PetscCall(PetscViewerASCIIPopTab(viewer));
2090   } else if (isstring) {
2091     PetscCall(TSGetType(ts,&type));
2092     PetscCall(PetscViewerStringSPrintf(viewer," TSType: %-7.7s",type));
2093     if (ts->ops->view) PetscCall((*ts->ops->view)(ts,viewer));
2094   } else if (isbinary) {
2095     PetscInt    classid = TS_FILE_CLASSID;
2096     MPI_Comm    comm;
2097     PetscMPIInt rank;
2098     char        type[256];
2099 
2100     PetscCall(PetscObjectGetComm((PetscObject)ts,&comm));
2101     PetscCallMPI(MPI_Comm_rank(comm,&rank));
2102     if (rank == 0) {
2103       PetscCall(PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT));
2104       PetscCall(PetscStrncpy(type,((PetscObject)ts)->type_name,256));
2105       PetscCall(PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR));
2106     }
2107     if (ts->ops->view) {
2108       PetscCall((*ts->ops->view)(ts,viewer));
2109     }
2110     if (ts->adapt) PetscCall(TSAdaptView(ts->adapt,viewer));
2111     PetscCall(DMView(ts->dm,viewer));
2112     PetscCall(VecView(ts->vec_sol,viewer));
2113     PetscCall(DMGetDMTS(ts->dm,&sdm));
2114     PetscCall(DMTSView(sdm,viewer));
2115   } else if (isdraw) {
2116     PetscDraw draw;
2117     char      str[36];
2118     PetscReal x,y,bottom,h;
2119 
2120     PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw));
2121     PetscCall(PetscDrawGetCurrentPoint(draw,&x,&y));
2122     PetscCall(PetscStrcpy(str,"TS: "));
2123     PetscCall(PetscStrcat(str,((PetscObject)ts)->type_name));
2124     PetscCall(PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_BLACK,PETSC_DRAW_BLACK,str,NULL,&h));
2125     bottom = y - h;
2126     PetscCall(PetscDrawPushCurrentPoint(draw,x,bottom));
2127     if (ts->ops->view) {
2128       PetscCall((*ts->ops->view)(ts,viewer));
2129     }
2130     if (ts->adapt) PetscCall(TSAdaptView(ts->adapt,viewer));
2131     if (ts->snes)  PetscCall(SNESView(ts->snes,viewer));
2132     PetscCall(PetscDrawPopCurrentPoint(draw));
2133 #if defined(PETSC_HAVE_SAWS)
2134   } else if (issaws) {
2135     PetscMPIInt rank;
2136     const char  *name;
2137 
2138     PetscCall(PetscObjectGetName((PetscObject)ts,&name));
2139     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
2140     if (!((PetscObject)ts)->amsmem && rank == 0) {
2141       char       dir[1024];
2142 
2143       PetscCall(PetscObjectViewSAWs((PetscObject)ts,viewer));
2144       PetscCall(PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time_step",name));
2145       PetscStackCallSAWs(SAWs_Register,(dir,&ts->steps,1,SAWs_READ,SAWs_INT));
2146       PetscCall(PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time",name));
2147       PetscStackCallSAWs(SAWs_Register,(dir,&ts->ptime,1,SAWs_READ,SAWs_DOUBLE));
2148     }
2149     if (ts->ops->view) {
2150       PetscCall((*ts->ops->view)(ts,viewer));
2151     }
2152 #endif
2153   }
2154   if (ts->snes && ts->usessnes)  {
2155     PetscCall(PetscViewerASCIIPushTab(viewer));
2156     PetscCall(SNESView(ts->snes,viewer));
2157     PetscCall(PetscViewerASCIIPopTab(viewer));
2158   }
2159   PetscCall(DMGetDMTS(ts->dm,&sdm));
2160   PetscCall(DMTSView(sdm,viewer));
2161 
2162   PetscCall(PetscViewerASCIIPushTab(viewer));
2163   PetscCall(PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials));
2164   PetscCall(PetscViewerASCIIPopTab(viewer));
2165   PetscFunctionReturn(0);
2166 }
2167 
2168 /*@
2169    TSSetApplicationContext - Sets an optional user-defined context for
2170    the timesteppers.
2171 
2172    Logically Collective on TS
2173 
2174    Input Parameters:
2175 +  ts - the TS context obtained from TSCreate()
2176 -  usrP - optional user context
2177 
2178    Fortran Notes:
2179     To use this from Fortran you must write a Fortran interface definition for this
2180     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2181 
2182    Level: intermediate
2183 
2184 .seealso: TSGetApplicationContext()
2185 @*/
2186 PetscErrorCode  TSSetApplicationContext(TS ts,void *usrP)
2187 {
2188   PetscFunctionBegin;
2189   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2190   ts->user = usrP;
2191   PetscFunctionReturn(0);
2192 }
2193 
2194 /*@
2195     TSGetApplicationContext - Gets the user-defined context for the
2196     timestepper.
2197 
2198     Not Collective
2199 
2200     Input Parameter:
2201 .   ts - the TS context obtained from TSCreate()
2202 
2203     Output Parameter:
2204 .   usrP - user context
2205 
2206    Fortran Notes:
2207     To use this from Fortran you must write a Fortran interface definition for this
2208     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2209 
2210     Level: intermediate
2211 
2212 .seealso: TSSetApplicationContext()
2213 @*/
2214 PetscErrorCode  TSGetApplicationContext(TS ts,void *usrP)
2215 {
2216   PetscFunctionBegin;
2217   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2218   *(void**)usrP = ts->user;
2219   PetscFunctionReturn(0);
2220 }
2221 
2222 /*@
2223    TSGetStepNumber - Gets the number of steps completed.
2224 
2225    Not Collective
2226 
2227    Input Parameter:
2228 .  ts - the TS context obtained from TSCreate()
2229 
2230    Output Parameter:
2231 .  steps - number of steps completed so far
2232 
2233    Level: intermediate
2234 
2235 .seealso: TSGetTime(), TSGetTimeStep(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSSetPostStep()
2236 @*/
2237 PetscErrorCode TSGetStepNumber(TS ts,PetscInt *steps)
2238 {
2239   PetscFunctionBegin;
2240   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2241   PetscValidIntPointer(steps,2);
2242   *steps = ts->steps;
2243   PetscFunctionReturn(0);
2244 }
2245 
2246 /*@
2247    TSSetStepNumber - Sets the number of steps completed.
2248 
2249    Logically Collective on TS
2250 
2251    Input Parameters:
2252 +  ts - the TS context
2253 -  steps - number of steps completed so far
2254 
2255    Notes:
2256    For most uses of the TS solvers the user need not explicitly call
2257    TSSetStepNumber(), as the step counter is appropriately updated in
2258    TSSolve()/TSStep()/TSRollBack(). Power users may call this routine to
2259    reinitialize timestepping by setting the step counter to zero (and time
2260    to the initial time) to solve a similar problem with different initial
2261    conditions or parameters. Other possible use case is to continue
2262    timestepping from a previously interrupted run in such a way that TS
2263    monitors will be called with a initial nonzero step counter.
2264 
2265    Level: advanced
2266 
2267 .seealso: TSGetStepNumber(), TSSetTime(), TSSetTimeStep(), TSSetSolution()
2268 @*/
2269 PetscErrorCode TSSetStepNumber(TS ts,PetscInt steps)
2270 {
2271   PetscFunctionBegin;
2272   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2273   PetscValidLogicalCollectiveInt(ts,steps,2);
2274   PetscCheck(steps >= 0,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Step number must be non-negative");
2275   ts->steps = steps;
2276   PetscFunctionReturn(0);
2277 }
2278 
2279 /*@
2280    TSSetTimeStep - Allows one to reset the timestep at any time,
2281    useful for simple pseudo-timestepping codes.
2282 
2283    Logically Collective on TS
2284 
2285    Input Parameters:
2286 +  ts - the TS context obtained from TSCreate()
2287 -  time_step - the size of the timestep
2288 
2289    Level: intermediate
2290 
2291 .seealso: TSGetTimeStep(), TSSetTime()
2292 
2293 @*/
2294 PetscErrorCode  TSSetTimeStep(TS ts,PetscReal time_step)
2295 {
2296   PetscFunctionBegin;
2297   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2298   PetscValidLogicalCollectiveReal(ts,time_step,2);
2299   ts->time_step = time_step;
2300   PetscFunctionReturn(0);
2301 }
2302 
2303 /*@
2304    TSSetExactFinalTime - Determines whether to adapt the final time step to
2305      match the exact final time, interpolate solution to the exact final time,
2306      or just return at the final time TS computed.
2307 
2308   Logically Collective on TS
2309 
2310    Input Parameters:
2311 +   ts - the time-step context
2312 -   eftopt - exact final time option
2313 
2314 $  TS_EXACTFINALTIME_STEPOVER    - Don't do anything if final time is exceeded
2315 $  TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time
2316 $  TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to match the final time
2317 
2318    Options Database:
2319 .   -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step at runtime
2320 
2321    Warning: If you use the option TS_EXACTFINALTIME_STEPOVER the solution may be at a very different time
2322     then the final time you selected.
2323 
2324    Level: beginner
2325 
2326 .seealso: TSExactFinalTimeOption, TSGetExactFinalTime()
2327 @*/
2328 PetscErrorCode TSSetExactFinalTime(TS ts,TSExactFinalTimeOption eftopt)
2329 {
2330   PetscFunctionBegin;
2331   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2332   PetscValidLogicalCollectiveEnum(ts,eftopt,2);
2333   ts->exact_final_time = eftopt;
2334   PetscFunctionReturn(0);
2335 }
2336 
2337 /*@
2338    TSGetExactFinalTime - Gets the exact final time option.
2339 
2340    Not Collective
2341 
2342    Input Parameter:
2343 .  ts - the TS context
2344 
2345    Output Parameter:
2346 .  eftopt - exact final time option
2347 
2348    Level: beginner
2349 
2350 .seealso: TSExactFinalTimeOption, TSSetExactFinalTime()
2351 @*/
2352 PetscErrorCode TSGetExactFinalTime(TS ts,TSExactFinalTimeOption *eftopt)
2353 {
2354   PetscFunctionBegin;
2355   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2356   PetscValidPointer(eftopt,2);
2357   *eftopt = ts->exact_final_time;
2358   PetscFunctionReturn(0);
2359 }
2360 
2361 /*@
2362    TSGetTimeStep - Gets the current timestep size.
2363 
2364    Not Collective
2365 
2366    Input Parameter:
2367 .  ts - the TS context obtained from TSCreate()
2368 
2369    Output Parameter:
2370 .  dt - the current timestep size
2371 
2372    Level: intermediate
2373 
2374 .seealso: TSSetTimeStep(), TSGetTime()
2375 
2376 @*/
2377 PetscErrorCode  TSGetTimeStep(TS ts,PetscReal *dt)
2378 {
2379   PetscFunctionBegin;
2380   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2381   PetscValidRealPointer(dt,2);
2382   *dt = ts->time_step;
2383   PetscFunctionReturn(0);
2384 }
2385 
2386 /*@
2387    TSGetSolution - Returns the solution at the present timestep. It
2388    is valid to call this routine inside the function that you are evaluating
2389    in order to move to the new timestep. This vector not changed until
2390    the solution at the next timestep has been calculated.
2391 
2392    Not Collective, but Vec returned is parallel if TS is parallel
2393 
2394    Input Parameter:
2395 .  ts - the TS context obtained from TSCreate()
2396 
2397    Output Parameter:
2398 .  v - the vector containing the solution
2399 
2400    Note: If you used TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP); this does not return the solution at the requested
2401    final time. It returns the solution at the next timestep.
2402 
2403    Level: intermediate
2404 
2405 .seealso: TSGetTimeStep(), TSGetTime(), TSGetSolveTime(), TSGetSolutionComponents(), TSSetSolutionFunction()
2406 
2407 @*/
2408 PetscErrorCode  TSGetSolution(TS ts,Vec *v)
2409 {
2410   PetscFunctionBegin;
2411   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2412   PetscValidPointer(v,2);
2413   *v = ts->vec_sol;
2414   PetscFunctionReturn(0);
2415 }
2416 
2417 /*@
2418    TSGetSolutionComponents - Returns any solution components at the present
2419    timestep, if available for the time integration method being used.
2420    Solution components are quantities that share the same size and
2421    structure as the solution vector.
2422 
2423    Not Collective, but Vec returned is parallel if TS is parallel
2424 
2425    Parameters :
2426 +  ts - the TS context obtained from TSCreate() (input parameter).
2427 .  n - If v is PETSC_NULL, then the number of solution components is
2428        returned through n, else the n-th solution component is
2429        returned in v.
2430 -  v - the vector containing the n-th solution component
2431        (may be PETSC_NULL to use this function to find out
2432         the number of solutions components).
2433 
2434    Level: advanced
2435 
2436 .seealso: TSGetSolution()
2437 
2438 @*/
2439 PetscErrorCode  TSGetSolutionComponents(TS ts,PetscInt *n,Vec *v)
2440 {
2441   PetscFunctionBegin;
2442   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2443   if (!ts->ops->getsolutioncomponents) *n = 0;
2444   else {
2445     PetscCall((*ts->ops->getsolutioncomponents)(ts,n,v));
2446   }
2447   PetscFunctionReturn(0);
2448 }
2449 
2450 /*@
2451    TSGetAuxSolution - Returns an auxiliary solution at the present
2452    timestep, if available for the time integration method being used.
2453 
2454    Not Collective, but Vec returned is parallel if TS is parallel
2455 
2456    Parameters :
2457 +  ts - the TS context obtained from TSCreate() (input parameter).
2458 -  v - the vector containing the auxiliary solution
2459 
2460    Level: intermediate
2461 
2462 .seealso: TSGetSolution()
2463 
2464 @*/
2465 PetscErrorCode  TSGetAuxSolution(TS ts,Vec *v)
2466 {
2467   PetscFunctionBegin;
2468   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2469   if (ts->ops->getauxsolution) {
2470     PetscCall((*ts->ops->getauxsolution)(ts,v));
2471   } else {
2472     PetscCall(VecZeroEntries(*v));
2473   }
2474   PetscFunctionReturn(0);
2475 }
2476 
2477 /*@
2478    TSGetTimeError - Returns the estimated error vector, if the chosen
2479    TSType has an error estimation functionality.
2480 
2481    Not Collective, but Vec returned is parallel if TS is parallel
2482 
2483    Note: MUST call after TSSetUp()
2484 
2485    Parameters :
2486 +  ts - the TS context obtained from TSCreate() (input parameter).
2487 .  n - current estimate (n=0) or previous one (n=-1)
2488 -  v - the vector containing the error (same size as the solution).
2489 
2490    Level: intermediate
2491 
2492 .seealso: TSGetSolution(), TSSetTimeError()
2493 
2494 @*/
2495 PetscErrorCode  TSGetTimeError(TS ts,PetscInt n,Vec *v)
2496 {
2497   PetscFunctionBegin;
2498   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2499   if (ts->ops->gettimeerror) {
2500     PetscCall((*ts->ops->gettimeerror)(ts,n,v));
2501   } else {
2502     PetscCall(VecZeroEntries(*v));
2503   }
2504   PetscFunctionReturn(0);
2505 }
2506 
2507 /*@
2508    TSSetTimeError - Sets the estimated error vector, if the chosen
2509    TSType has an error estimation functionality. This can be used
2510    to restart such a time integrator with a given error vector.
2511 
2512    Not Collective, but Vec returned is parallel if TS is parallel
2513 
2514    Parameters :
2515 +  ts - the TS context obtained from TSCreate() (input parameter).
2516 -  v - the vector containing the error (same size as the solution).
2517 
2518    Level: intermediate
2519 
2520 .seealso: TSSetSolution(), TSGetTimeError)
2521 
2522 @*/
2523 PetscErrorCode  TSSetTimeError(TS ts,Vec v)
2524 {
2525   PetscFunctionBegin;
2526   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2527   PetscCheck(ts->setupcalled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetUp() first");
2528   if (ts->ops->settimeerror) {
2529     PetscCall((*ts->ops->settimeerror)(ts,v));
2530   }
2531   PetscFunctionReturn(0);
2532 }
2533 
2534 /* ----- Routines to initialize and destroy a timestepper ---- */
2535 /*@
2536   TSSetProblemType - Sets the type of problem to be solved.
2537 
2538   Not collective
2539 
2540   Input Parameters:
2541 + ts   - The TS
2542 - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
2543 .vb
2544          U_t - A U = 0      (linear)
2545          U_t - A(t) U = 0   (linear)
2546          F(t,U,U_t) = 0     (nonlinear)
2547 .ve
2548 
2549    Level: beginner
2550 
2551 .seealso: TSSetUp(), TSProblemType, TS
2552 @*/
2553 PetscErrorCode  TSSetProblemType(TS ts, TSProblemType type)
2554 {
2555   PetscFunctionBegin;
2556   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2557   ts->problem_type = type;
2558   if (type == TS_LINEAR) {
2559     SNES snes;
2560     PetscCall(TSGetSNES(ts,&snes));
2561     PetscCall(SNESSetType(snes,SNESKSPONLY));
2562   }
2563   PetscFunctionReturn(0);
2564 }
2565 
2566 /*@C
2567   TSGetProblemType - Gets the type of problem to be solved.
2568 
2569   Not collective
2570 
2571   Input Parameter:
2572 . ts   - The TS
2573 
2574   Output Parameter:
2575 . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
2576 .vb
2577          M U_t = A U
2578          M(t) U_t = A(t) U
2579          F(t,U,U_t)
2580 .ve
2581 
2582    Level: beginner
2583 
2584 .seealso: TSSetUp(), TSProblemType, TS
2585 @*/
2586 PetscErrorCode  TSGetProblemType(TS ts, TSProblemType *type)
2587 {
2588   PetscFunctionBegin;
2589   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2590   PetscValidIntPointer(type,2);
2591   *type = ts->problem_type;
2592   PetscFunctionReturn(0);
2593 }
2594 
2595 /*
2596     Attempt to check/preset a default value for the exact final time option. This is needed at the beginning of TSSolve() and in TSSetUp()
2597 */
2598 static PetscErrorCode TSSetExactFinalTimeDefault(TS ts)
2599 {
2600   PetscBool      isnone;
2601 
2602   PetscFunctionBegin;
2603   PetscCall(TSGetAdapt(ts,&ts->adapt));
2604   PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type));
2605 
2606   PetscCall(PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&isnone));
2607   if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) {
2608     ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP;
2609   } else if (ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED) {
2610     ts->exact_final_time = TS_EXACTFINALTIME_INTERPOLATE;
2611   }
2612   PetscFunctionReturn(0);
2613 }
2614 
2615 /*@
2616    TSSetUp - Sets up the internal data structures for the later use of a timestepper.
2617 
2618    Collective on TS
2619 
2620    Input Parameter:
2621 .  ts - the TS context obtained from TSCreate()
2622 
2623    Notes:
2624    For basic use of the TS solvers the user need not explicitly call
2625    TSSetUp(), since these actions will automatically occur during
2626    the call to TSStep() or TSSolve().  However, if one wishes to control this
2627    phase separately, TSSetUp() should be called after TSCreate()
2628    and optional routines of the form TSSetXXX(), but before TSStep() and TSSolve().
2629 
2630    Level: advanced
2631 
2632 .seealso: TSCreate(), TSStep(), TSDestroy(), TSSolve()
2633 @*/
2634 PetscErrorCode  TSSetUp(TS ts)
2635 {
2636   DM             dm;
2637   PetscErrorCode (*func)(SNES,Vec,Vec,void*);
2638   PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*);
2639   TSIFunction    ifun;
2640   TSIJacobian    ijac;
2641   TSI2Jacobian   i2jac;
2642   TSRHSJacobian  rhsjac;
2643 
2644   PetscFunctionBegin;
2645   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2646   if (ts->setupcalled) PetscFunctionReturn(0);
2647 
2648   if (!((PetscObject)ts)->type_name) {
2649     PetscCall(TSGetIFunction(ts,NULL,&ifun,NULL));
2650     PetscCall(TSSetType(ts,ifun ? TSBEULER : TSEULER));
2651   }
2652 
2653   if (!ts->vec_sol) {
2654     if (ts->dm) {
2655       PetscCall(DMCreateGlobalVector(ts->dm,&ts->vec_sol));
2656     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first");
2657   }
2658 
2659   if (ts->tspan) {
2660     if (!ts->tspan->vecs_sol) {
2661       PetscCall(VecDuplicateVecs(ts->vec_sol,ts->tspan->num_span_times,&ts->tspan->vecs_sol));
2662     }
2663   }
2664   if (!ts->Jacp && ts->Jacprhs) { /* IJacobianP shares the same matrix with RHSJacobianP if only RHSJacobianP is provided */
2665     PetscCall(PetscObjectReference((PetscObject)ts->Jacprhs));
2666     ts->Jacp = ts->Jacprhs;
2667   }
2668 
2669   if (ts->quadraturets) {
2670     PetscCall(TSSetUp(ts->quadraturets));
2671     PetscCall(VecDestroy(&ts->vec_costintegrand));
2672     PetscCall(VecDuplicate(ts->quadraturets->vec_sol,&ts->vec_costintegrand));
2673   }
2674 
2675   PetscCall(TSGetRHSJacobian(ts,NULL,NULL,&rhsjac,NULL));
2676   if (rhsjac == TSComputeRHSJacobianConstant) {
2677     Mat Amat,Pmat;
2678     SNES snes;
2679     PetscCall(TSGetSNES(ts,&snes));
2680     PetscCall(SNESGetJacobian(snes,&Amat,&Pmat,NULL,NULL));
2681     /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
2682      * have displaced the RHS matrix */
2683     if (Amat && Amat == ts->Arhs) {
2684       /* 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 */
2685       PetscCall(MatDuplicate(ts->Arhs,MAT_COPY_VALUES,&Amat));
2686       PetscCall(SNESSetJacobian(snes,Amat,NULL,NULL,NULL));
2687       PetscCall(MatDestroy(&Amat));
2688     }
2689     if (Pmat && Pmat == ts->Brhs) {
2690       PetscCall(MatDuplicate(ts->Brhs,MAT_COPY_VALUES,&Pmat));
2691       PetscCall(SNESSetJacobian(snes,NULL,Pmat,NULL,NULL));
2692       PetscCall(MatDestroy(&Pmat));
2693     }
2694   }
2695 
2696   PetscCall(TSGetAdapt(ts,&ts->adapt));
2697   PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type));
2698 
2699   if (ts->ops->setup) {
2700     PetscCall((*ts->ops->setup)(ts));
2701   }
2702 
2703   PetscCall(TSSetExactFinalTimeDefault(ts));
2704 
2705   /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
2706      to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
2707    */
2708   PetscCall(TSGetDM(ts,&dm));
2709   PetscCall(DMSNESGetFunction(dm,&func,NULL));
2710   if (!func) {
2711     PetscCall(DMSNESSetFunction(dm,SNESTSFormFunction,ts));
2712   }
2713   /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
2714      Otherwise, the SNES will use coloring internally to form the Jacobian.
2715    */
2716   PetscCall(DMSNESGetJacobian(dm,&jac,NULL));
2717   PetscCall(DMTSGetIJacobian(dm,&ijac,NULL));
2718   PetscCall(DMTSGetI2Jacobian(dm,&i2jac,NULL));
2719   PetscCall(DMTSGetRHSJacobian(dm,&rhsjac,NULL));
2720   if (!jac && (ijac || i2jac || rhsjac)) {
2721     PetscCall(DMSNESSetJacobian(dm,SNESTSFormJacobian,ts));
2722   }
2723 
2724   /* if time integration scheme has a starting method, call it */
2725   if (ts->ops->startingmethod) {
2726     PetscCall((*ts->ops->startingmethod)(ts));
2727   }
2728 
2729   ts->setupcalled = PETSC_TRUE;
2730   PetscFunctionReturn(0);
2731 }
2732 
2733 /*@
2734    TSReset - Resets a TS context and removes any allocated Vecs and Mats.
2735 
2736    Collective on TS
2737 
2738    Input Parameter:
2739 .  ts - the TS context obtained from TSCreate()
2740 
2741    Level: beginner
2742 
2743 .seealso: TSCreate(), TSSetup(), TSDestroy()
2744 @*/
2745 PetscErrorCode  TSReset(TS ts)
2746 {
2747   TS_RHSSplitLink ilink = ts->tsrhssplit,next;
2748 
2749   PetscFunctionBegin;
2750   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2751 
2752   if (ts->ops->reset) {
2753     PetscCall((*ts->ops->reset)(ts));
2754   }
2755   if (ts->snes) PetscCall(SNESReset(ts->snes));
2756   if (ts->adapt) PetscCall(TSAdaptReset(ts->adapt));
2757 
2758   PetscCall(MatDestroy(&ts->Arhs));
2759   PetscCall(MatDestroy(&ts->Brhs));
2760   PetscCall(VecDestroy(&ts->Frhs));
2761   PetscCall(VecDestroy(&ts->vec_sol));
2762   PetscCall(VecDestroy(&ts->vec_dot));
2763   PetscCall(VecDestroy(&ts->vatol));
2764   PetscCall(VecDestroy(&ts->vrtol));
2765   PetscCall(VecDestroyVecs(ts->nwork,&ts->work));
2766 
2767   PetscCall(MatDestroy(&ts->Jacprhs));
2768   PetscCall(MatDestroy(&ts->Jacp));
2769   if (ts->forward_solve) {
2770     PetscCall(TSForwardReset(ts));
2771   }
2772   if (ts->quadraturets) {
2773     PetscCall(TSReset(ts->quadraturets));
2774     PetscCall(VecDestroy(&ts->vec_costintegrand));
2775   }
2776   while (ilink) {
2777     next = ilink->next;
2778     PetscCall(TSDestroy(&ilink->ts));
2779     PetscCall(PetscFree(ilink->splitname));
2780     PetscCall(ISDestroy(&ilink->is));
2781     PetscCall(PetscFree(ilink));
2782     ilink = next;
2783   }
2784   ts->tsrhssplit = NULL;
2785   ts->num_rhs_splits = 0;
2786   if (ts->tspan) {
2787     PetscCall(PetscFree(ts->tspan->span_times));
2788     PetscCall(VecDestroyVecs(ts->tspan->num_span_times,&ts->tspan->vecs_sol));
2789     PetscCall(PetscFree(ts->tspan));
2790   }
2791   ts->setupcalled = PETSC_FALSE;
2792   PetscFunctionReturn(0);
2793 }
2794 
2795 /*@C
2796    TSDestroy - Destroys the timestepper context that was created
2797    with TSCreate().
2798 
2799    Collective on TS
2800 
2801    Input Parameter:
2802 .  ts - the TS context obtained from TSCreate()
2803 
2804    Level: beginner
2805 
2806 .seealso: TSCreate(), TSSetUp(), TSSolve()
2807 @*/
2808 PetscErrorCode  TSDestroy(TS *ts)
2809 {
2810   PetscFunctionBegin;
2811   if (!*ts) PetscFunctionReturn(0);
2812   PetscValidHeaderSpecific(*ts,TS_CLASSID,1);
2813   if (--((PetscObject)(*ts))->refct > 0) {*ts = NULL; PetscFunctionReturn(0);}
2814 
2815   PetscCall(TSReset(*ts));
2816   PetscCall(TSAdjointReset(*ts));
2817   if ((*ts)->forward_solve) {
2818     PetscCall(TSForwardReset(*ts));
2819   }
2820   /* if memory was published with SAWs then destroy it */
2821   PetscCall(PetscObjectSAWsViewOff((PetscObject)*ts));
2822   if ((*ts)->ops->destroy) PetscCall((*(*ts)->ops->destroy)((*ts)));
2823 
2824   PetscCall(TSTrajectoryDestroy(&(*ts)->trajectory));
2825 
2826   PetscCall(TSAdaptDestroy(&(*ts)->adapt));
2827   PetscCall(TSEventDestroy(&(*ts)->event));
2828 
2829   PetscCall(SNESDestroy(&(*ts)->snes));
2830   PetscCall(DMDestroy(&(*ts)->dm));
2831   PetscCall(TSMonitorCancel((*ts)));
2832   PetscCall(TSAdjointMonitorCancel((*ts)));
2833 
2834   PetscCall(TSDestroy(&(*ts)->quadraturets));
2835   PetscCall(PetscHeaderDestroy(ts));
2836   PetscFunctionReturn(0);
2837 }
2838 
2839 /*@
2840    TSGetSNES - Returns the SNES (nonlinear solver) associated with
2841    a TS (timestepper) context. Valid only for nonlinear problems.
2842 
2843    Not Collective, but SNES is parallel if TS is parallel
2844 
2845    Input Parameter:
2846 .  ts - the TS context obtained from TSCreate()
2847 
2848    Output Parameter:
2849 .  snes - the nonlinear solver context
2850 
2851    Notes:
2852    The user can then directly manipulate the SNES context to set various
2853    options, etc.  Likewise, the user can then extract and manipulate the
2854    KSP, KSP, and PC contexts as well.
2855 
2856    TSGetSNES() does not work for integrators that do not use SNES; in
2857    this case TSGetSNES() returns NULL in snes.
2858 
2859    Level: beginner
2860 
2861 @*/
2862 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
2863 {
2864   PetscFunctionBegin;
2865   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2866   PetscValidPointer(snes,2);
2867   if (!ts->snes) {
2868     PetscCall(SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes));
2869     PetscCall(PetscObjectSetOptions((PetscObject)ts->snes,((PetscObject)ts)->options));
2870     PetscCall(SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts));
2871     PetscCall(PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->snes));
2872     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1));
2873     if (ts->dm) PetscCall(SNESSetDM(ts->snes,ts->dm));
2874     if (ts->problem_type == TS_LINEAR) {
2875       PetscCall(SNESSetType(ts->snes,SNESKSPONLY));
2876     }
2877   }
2878   *snes = ts->snes;
2879   PetscFunctionReturn(0);
2880 }
2881 
2882 /*@
2883    TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
2884 
2885    Collective
2886 
2887    Input Parameters:
2888 +  ts - the TS context obtained from TSCreate()
2889 -  snes - the nonlinear solver context
2890 
2891    Notes:
2892    Most users should have the TS created by calling TSGetSNES()
2893 
2894    Level: developer
2895 
2896 @*/
2897 PetscErrorCode TSSetSNES(TS ts,SNES snes)
2898 {
2899   PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*);
2900 
2901   PetscFunctionBegin;
2902   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2903   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
2904   PetscCall(PetscObjectReference((PetscObject)snes));
2905   PetscCall(SNESDestroy(&ts->snes));
2906 
2907   ts->snes = snes;
2908 
2909   PetscCall(SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts));
2910   PetscCall(SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL));
2911   if (func == SNESTSFormJacobian) {
2912     PetscCall(SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts));
2913   }
2914   PetscFunctionReturn(0);
2915 }
2916 
2917 /*@
2918    TSGetKSP - Returns the KSP (linear solver) associated with
2919    a TS (timestepper) context.
2920 
2921    Not Collective, but KSP is parallel if TS is parallel
2922 
2923    Input Parameter:
2924 .  ts - the TS context obtained from TSCreate()
2925 
2926    Output Parameter:
2927 .  ksp - the nonlinear solver context
2928 
2929    Notes:
2930    The user can then directly manipulate the KSP context to set various
2931    options, etc.  Likewise, the user can then extract and manipulate the
2932    KSP and PC contexts as well.
2933 
2934    TSGetKSP() does not work for integrators that do not use KSP;
2935    in this case TSGetKSP() returns NULL in ksp.
2936 
2937    Level: beginner
2938 
2939 @*/
2940 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
2941 {
2942   SNES           snes;
2943 
2944   PetscFunctionBegin;
2945   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2946   PetscValidPointer(ksp,2);
2947   PetscCheck(((PetscObject)ts)->type_name,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
2948   PetscCheck(ts->problem_type == TS_LINEAR,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
2949   PetscCall(TSGetSNES(ts,&snes));
2950   PetscCall(SNESGetKSP(snes,ksp));
2951   PetscFunctionReturn(0);
2952 }
2953 
2954 /* ----------- Routines to set solver parameters ---------- */
2955 
2956 /*@
2957    TSSetMaxSteps - Sets the maximum number of steps to use.
2958 
2959    Logically Collective on TS
2960 
2961    Input Parameters:
2962 +  ts - the TS context obtained from TSCreate()
2963 -  maxsteps - maximum number of steps to use
2964 
2965    Options Database Keys:
2966 .  -ts_max_steps <maxsteps> - Sets maxsteps
2967 
2968    Notes:
2969    The default maximum number of steps is 5000
2970 
2971    Level: intermediate
2972 
2973 .seealso: TSGetMaxSteps(), TSSetMaxTime(), TSSetExactFinalTime()
2974 @*/
2975 PetscErrorCode TSSetMaxSteps(TS ts,PetscInt maxsteps)
2976 {
2977   PetscFunctionBegin;
2978   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2979   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
2980   PetscCheck(maxsteps >= 0,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of steps must be non-negative");
2981   ts->max_steps = maxsteps;
2982   PetscFunctionReturn(0);
2983 }
2984 
2985 /*@
2986    TSGetMaxSteps - Gets the maximum number of steps to use.
2987 
2988    Not Collective
2989 
2990    Input Parameters:
2991 .  ts - the TS context obtained from TSCreate()
2992 
2993    Output Parameter:
2994 .  maxsteps - maximum number of steps to use
2995 
2996    Level: advanced
2997 
2998 .seealso: TSSetMaxSteps(), TSGetMaxTime(), TSSetMaxTime()
2999 @*/
3000 PetscErrorCode TSGetMaxSteps(TS ts,PetscInt *maxsteps)
3001 {
3002   PetscFunctionBegin;
3003   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3004   PetscValidIntPointer(maxsteps,2);
3005   *maxsteps = ts->max_steps;
3006   PetscFunctionReturn(0);
3007 }
3008 
3009 /*@
3010    TSSetMaxTime - Sets the maximum (or final) time for timestepping.
3011 
3012    Logically Collective on TS
3013 
3014    Input Parameters:
3015 +  ts - the TS context obtained from TSCreate()
3016 -  maxtime - final time to step to
3017 
3018    Options Database Keys:
3019 .  -ts_max_time <maxtime> - Sets maxtime
3020 
3021    Notes:
3022    The default maximum time is 5.0
3023 
3024    Level: intermediate
3025 
3026 .seealso: TSGetMaxTime(), TSSetMaxSteps(), TSSetExactFinalTime()
3027 @*/
3028 PetscErrorCode TSSetMaxTime(TS ts,PetscReal maxtime)
3029 {
3030   PetscFunctionBegin;
3031   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3032   PetscValidLogicalCollectiveReal(ts,maxtime,2);
3033   ts->max_time = maxtime;
3034   PetscFunctionReturn(0);
3035 }
3036 
3037 /*@
3038    TSGetMaxTime - Gets the maximum (or final) time for timestepping.
3039 
3040    Not Collective
3041 
3042    Input Parameters:
3043 .  ts - the TS context obtained from TSCreate()
3044 
3045    Output Parameter:
3046 .  maxtime - final time to step to
3047 
3048    Level: advanced
3049 
3050 .seealso: TSSetMaxTime(), TSGetMaxSteps(), TSSetMaxSteps()
3051 @*/
3052 PetscErrorCode TSGetMaxTime(TS ts,PetscReal *maxtime)
3053 {
3054   PetscFunctionBegin;
3055   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3056   PetscValidRealPointer(maxtime,2);
3057   *maxtime = ts->max_time;
3058   PetscFunctionReturn(0);
3059 }
3060 
3061 /*@
3062    TSSetInitialTimeStep - Deprecated, use TSSetTime() and TSSetTimeStep().
3063 
3064    Level: deprecated
3065 
3066 @*/
3067 PetscErrorCode  TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step)
3068 {
3069   PetscFunctionBegin;
3070   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3071   PetscCall(TSSetTime(ts,initial_time));
3072   PetscCall(TSSetTimeStep(ts,time_step));
3073   PetscFunctionReturn(0);
3074 }
3075 
3076 /*@
3077    TSGetDuration - Deprecated, use TSGetMaxSteps() and TSGetMaxTime().
3078 
3079    Level: deprecated
3080 
3081 @*/
3082 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
3083 {
3084   PetscFunctionBegin;
3085   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3086   if (maxsteps) {
3087     PetscValidIntPointer(maxsteps,2);
3088     *maxsteps = ts->max_steps;
3089   }
3090   if (maxtime) {
3091     PetscValidRealPointer(maxtime,3);
3092     *maxtime = ts->max_time;
3093   }
3094   PetscFunctionReturn(0);
3095 }
3096 
3097 /*@
3098    TSSetDuration - Deprecated, use TSSetMaxSteps() and TSSetMaxTime().
3099 
3100    Level: deprecated
3101 
3102 @*/
3103 PetscErrorCode TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
3104 {
3105   PetscFunctionBegin;
3106   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3107   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
3108   PetscValidLogicalCollectiveReal(ts,maxtime,3);
3109   if (maxsteps >= 0) ts->max_steps = maxsteps;
3110   if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
3111   PetscFunctionReturn(0);
3112 }
3113 
3114 /*@
3115    TSGetTimeStepNumber - Deprecated, use TSGetStepNumber().
3116 
3117    Level: deprecated
3118 
3119 @*/
3120 PetscErrorCode TSGetTimeStepNumber(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); }
3121 
3122 /*@
3123    TSGetTotalSteps - Deprecated, use TSGetStepNumber().
3124 
3125    Level: deprecated
3126 
3127 @*/
3128 PetscErrorCode TSGetTotalSteps(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); }
3129 
3130 /*@
3131    TSSetSolution - Sets the initial solution vector
3132    for use by the TS routines.
3133 
3134    Logically Collective on TS
3135 
3136    Input Parameters:
3137 +  ts - the TS context obtained from TSCreate()
3138 -  u - the solution vector
3139 
3140    Level: beginner
3141 
3142 .seealso: TSSetSolutionFunction(), TSGetSolution(), TSCreate()
3143 @*/
3144 PetscErrorCode  TSSetSolution(TS ts,Vec u)
3145 {
3146   DM             dm;
3147 
3148   PetscFunctionBegin;
3149   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3150   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3151   PetscCall(PetscObjectReference((PetscObject)u));
3152   PetscCall(VecDestroy(&ts->vec_sol));
3153   ts->vec_sol = u;
3154 
3155   PetscCall(TSGetDM(ts,&dm));
3156   PetscCall(DMShellSetGlobalVector(dm,u));
3157   PetscFunctionReturn(0);
3158 }
3159 
3160 /*@C
3161   TSSetPreStep - Sets the general-purpose function
3162   called once at the beginning of each time step.
3163 
3164   Logically Collective on TS
3165 
3166   Input Parameters:
3167 + ts   - The TS context obtained from TSCreate()
3168 - func - The function
3169 
3170   Calling sequence of func:
3171 .vb
3172   PetscErrorCode func (TS ts);
3173 .ve
3174 
3175   Level: intermediate
3176 
3177 .seealso: TSSetPreStage(), TSSetPostStage(), TSSetPostStep(), TSStep(), TSRestartStep()
3178 @*/
3179 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
3180 {
3181   PetscFunctionBegin;
3182   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3183   ts->prestep = func;
3184   PetscFunctionReturn(0);
3185 }
3186 
3187 /*@
3188   TSPreStep - Runs the user-defined pre-step function.
3189 
3190   Collective on TS
3191 
3192   Input Parameters:
3193 . ts   - The TS context obtained from TSCreate()
3194 
3195   Notes:
3196   TSPreStep() is typically used within time stepping implementations,
3197   so most users would not generally call this routine themselves.
3198 
3199   Level: developer
3200 
3201 .seealso: TSSetPreStep(), TSPreStage(), TSPostStage(), TSPostStep()
3202 @*/
3203 PetscErrorCode  TSPreStep(TS ts)
3204 {
3205   PetscFunctionBegin;
3206   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3207   if (ts->prestep) {
3208     Vec              U;
3209     PetscObjectId    idprev;
3210     PetscBool        sameObject;
3211     PetscObjectState sprev,spost;
3212 
3213     PetscCall(TSGetSolution(ts,&U));
3214     PetscCall(PetscObjectGetId((PetscObject)U,&idprev));
3215     PetscCall(PetscObjectStateGet((PetscObject)U,&sprev));
3216     PetscStackCallStandard((*ts->prestep),ts);
3217     PetscCall(TSGetSolution(ts,&U));
3218     PetscCall(PetscObjectCompareId((PetscObject)U,idprev,&sameObject));
3219     PetscCall(PetscObjectStateGet((PetscObject)U,&spost));
3220     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3221   }
3222   PetscFunctionReturn(0);
3223 }
3224 
3225 /*@C
3226   TSSetPreStage - Sets the general-purpose function
3227   called once at the beginning of each stage.
3228 
3229   Logically Collective on TS
3230 
3231   Input Parameters:
3232 + ts   - The TS context obtained from TSCreate()
3233 - func - The function
3234 
3235   Calling sequence of func:
3236 .vb
3237   PetscErrorCode func(TS ts, PetscReal stagetime);
3238 .ve
3239 
3240   Level: intermediate
3241 
3242   Note:
3243   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3244   The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being
3245   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3246 
3247 .seealso: TSSetPostStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3248 @*/
3249 PetscErrorCode  TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
3250 {
3251   PetscFunctionBegin;
3252   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3253   ts->prestage = func;
3254   PetscFunctionReturn(0);
3255 }
3256 
3257 /*@C
3258   TSSetPostStage - Sets the general-purpose function
3259   called once at the end of each stage.
3260 
3261   Logically Collective on TS
3262 
3263   Input Parameters:
3264 + ts   - The TS context obtained from TSCreate()
3265 - func - The function
3266 
3267   Calling sequence of func:
3268 .vb
3269   PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y);
3270 .ve
3271 
3272   Level: intermediate
3273 
3274   Note:
3275   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3276   The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being
3277   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3278 
3279 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3280 @*/
3281 PetscErrorCode  TSSetPostStage(TS ts, PetscErrorCode (*func)(TS,PetscReal,PetscInt,Vec*))
3282 {
3283   PetscFunctionBegin;
3284   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3285   ts->poststage = func;
3286   PetscFunctionReturn(0);
3287 }
3288 
3289 /*@C
3290   TSSetPostEvaluate - Sets the general-purpose function
3291   called once at the end of each step evaluation.
3292 
3293   Logically Collective on TS
3294 
3295   Input Parameters:
3296 + ts   - The TS context obtained from TSCreate()
3297 - func - The function
3298 
3299   Calling sequence of func:
3300 .vb
3301   PetscErrorCode func(TS ts);
3302 .ve
3303 
3304   Level: intermediate
3305 
3306   Note:
3307   Semantically, TSSetPostEvaluate() differs from TSSetPostStep() since the function it sets is called before event-handling
3308   thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, TSPostStep()
3309   may be passed a different solution, possibly changed by the event handler. TSPostEvaluate() is called after the next step
3310   solution is evaluated allowing to modify it, if need be. The solution can be obtained with TSGetSolution(), the time step
3311   with TSGetTimeStep(), and the time at the start of the step is available via TSGetTime()
3312 
3313 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3314 @*/
3315 PetscErrorCode  TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS))
3316 {
3317   PetscFunctionBegin;
3318   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3319   ts->postevaluate = func;
3320   PetscFunctionReturn(0);
3321 }
3322 
3323 /*@
3324   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
3325 
3326   Collective on TS
3327 
3328   Input Parameters:
3329 . ts          - The TS context obtained from TSCreate()
3330   stagetime   - The absolute time of the current stage
3331 
3332   Notes:
3333   TSPreStage() is typically used within time stepping implementations,
3334   most users would not generally call this routine themselves.
3335 
3336   Level: developer
3337 
3338 .seealso: TSPostStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
3339 @*/
3340 PetscErrorCode  TSPreStage(TS ts, PetscReal stagetime)
3341 {
3342   PetscFunctionBegin;
3343   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3344   if (ts->prestage) {
3345     PetscStackCallStandard((*ts->prestage),ts,stagetime);
3346   }
3347   PetscFunctionReturn(0);
3348 }
3349 
3350 /*@
3351   TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage()
3352 
3353   Collective on TS
3354 
3355   Input Parameters:
3356 . ts          - The TS context obtained from TSCreate()
3357   stagetime   - The absolute time of the current stage
3358   stageindex  - Stage number
3359   Y           - Array of vectors (of size = total number
3360                 of stages) with the stage solutions
3361 
3362   Notes:
3363   TSPostStage() is typically used within time stepping implementations,
3364   most users would not generally call this routine themselves.
3365 
3366   Level: developer
3367 
3368 .seealso: TSPreStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
3369 @*/
3370 PetscErrorCode  TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
3371 {
3372   PetscFunctionBegin;
3373   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3374   if (ts->poststage) {
3375     PetscStackCallStandard((*ts->poststage),ts,stagetime,stageindex,Y);
3376   }
3377   PetscFunctionReturn(0);
3378 }
3379 
3380 /*@
3381   TSPostEvaluate - Runs the user-defined post-evaluate function set using TSSetPostEvaluate()
3382 
3383   Collective on TS
3384 
3385   Input Parameters:
3386 . ts          - The TS context obtained from TSCreate()
3387 
3388   Notes:
3389   TSPostEvaluate() is typically used within time stepping implementations,
3390   most users would not generally call this routine themselves.
3391 
3392   Level: developer
3393 
3394 .seealso: TSSetPostEvaluate(), TSSetPreStep(), TSPreStep(), TSPostStep()
3395 @*/
3396 PetscErrorCode  TSPostEvaluate(TS ts)
3397 {
3398   PetscFunctionBegin;
3399   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3400   if (ts->postevaluate) {
3401     Vec              U;
3402     PetscObjectState sprev,spost;
3403 
3404     PetscCall(TSGetSolution(ts,&U));
3405     PetscCall(PetscObjectStateGet((PetscObject)U,&sprev));
3406     PetscStackCallStandard((*ts->postevaluate),ts);
3407     PetscCall(PetscObjectStateGet((PetscObject)U,&spost));
3408     if (sprev != spost) PetscCall(TSRestartStep(ts));
3409   }
3410   PetscFunctionReturn(0);
3411 }
3412 
3413 /*@C
3414   TSSetPostStep - Sets the general-purpose function
3415   called once at the end of each time step.
3416 
3417   Logically Collective on TS
3418 
3419   Input Parameters:
3420 + ts   - The TS context obtained from TSCreate()
3421 - func - The function
3422 
3423   Calling sequence of func:
3424 $ func (TS ts);
3425 
3426   Notes:
3427   The function set by TSSetPostStep() is called after each successful step. The solution vector X
3428   obtained by TSGetSolution() may be different than that computed at the step end if the event handler
3429   locates an event and TSPostEvent() modifies it. Use TSSetPostEvaluate() if an unmodified solution is needed instead.
3430 
3431   Level: intermediate
3432 
3433 .seealso: TSSetPreStep(), TSSetPreStage(), TSSetPostEvaluate(), TSGetTimeStep(), TSGetStepNumber(), TSGetTime(), TSRestartStep()
3434 @*/
3435 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
3436 {
3437   PetscFunctionBegin;
3438   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3439   ts->poststep = func;
3440   PetscFunctionReturn(0);
3441 }
3442 
3443 /*@
3444   TSPostStep - Runs the user-defined post-step function.
3445 
3446   Collective on TS
3447 
3448   Input Parameters:
3449 . ts   - The TS context obtained from TSCreate()
3450 
3451   Notes:
3452   TSPostStep() is typically used within time stepping implementations,
3453   so most users would not generally call this routine themselves.
3454 
3455   Level: developer
3456 
3457 @*/
3458 PetscErrorCode  TSPostStep(TS ts)
3459 {
3460   PetscFunctionBegin;
3461   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3462   if (ts->poststep) {
3463     Vec              U;
3464     PetscObjectId    idprev;
3465     PetscBool        sameObject;
3466     PetscObjectState sprev,spost;
3467 
3468     PetscCall(TSGetSolution(ts,&U));
3469     PetscCall(PetscObjectGetId((PetscObject)U,&idprev));
3470     PetscCall(PetscObjectStateGet((PetscObject)U,&sprev));
3471     PetscStackCallStandard((*ts->poststep),ts);
3472     PetscCall(TSGetSolution(ts,&U));
3473     PetscCall(PetscObjectCompareId((PetscObject)U,idprev,&sameObject));
3474     PetscCall(PetscObjectStateGet((PetscObject)U,&spost));
3475     if (!sameObject || sprev != spost) PetscCall(TSRestartStep(ts));
3476   }
3477   PetscFunctionReturn(0);
3478 }
3479 
3480 /*@
3481    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
3482 
3483    Collective on TS
3484 
3485    Input Parameters:
3486 +  ts - time stepping context
3487 -  t - time to interpolate to
3488 
3489    Output Parameter:
3490 .  U - state at given time
3491 
3492    Level: intermediate
3493 
3494    Developer Notes:
3495    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
3496 
3497 .seealso: TSSetExactFinalTime(), TSSolve()
3498 @*/
3499 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
3500 {
3501   PetscFunctionBegin;
3502   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3503   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3504   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);
3505   PetscCheck(ts->ops->interpolate,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
3506   PetscCall((*ts->ops->interpolate)(ts,t,U));
3507   PetscFunctionReturn(0);
3508 }
3509 
3510 /*@
3511    TSStep - Steps one time step
3512 
3513    Collective on TS
3514 
3515    Input Parameter:
3516 .  ts - the TS context obtained from TSCreate()
3517 
3518    Level: developer
3519 
3520    Notes:
3521    The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine.
3522 
3523    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
3524    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3525 
3526    This may over-step the final time provided in TSSetMaxTime() depending on the time-step used. TSSolve() interpolates to exactly the
3527    time provided in TSSetMaxTime(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
3528 
3529 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate()
3530 @*/
3531 PetscErrorCode  TSStep(TS ts)
3532 {
3533   PetscErrorCode   ierr;
3534   static PetscBool cite = PETSC_FALSE;
3535   PetscReal        ptime;
3536 
3537   PetscFunctionBegin;
3538   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3539   ierr = PetscCitationsRegister("@article{tspaper,\n"
3540                                 "  title         = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3541                                 "  author        = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n"
3542                                 "  journal       = {arXiv e-preprints},\n"
3543                                 "  eprint        = {1806.01437},\n"
3544                                 "  archivePrefix = {arXiv},\n"
3545                                 "  year          = {2018}\n}\n",&cite);PetscCall(ierr);
3546 
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