xref: /petsc/src/ts/interface/ts.c (revision f5a72eb34e1dc21bf8593cf383cc1fa498006d28)
1 #include <petsc/private/tsimpl.h>        /*I "petscts.h"  I*/
2 #include <petscdmshell.h>
3 #include <petscdmda.h>
4 #include <petscviewer.h>
5 #include <petscdraw.h>
6 #include <petscconvest.h>
7 
8 #define SkipSmallValue(a,b,tol) if (PetscAbsScalar(a)< tol || PetscAbsScalar(b)< tol) continue;
9 
10 /* Logging support */
11 PetscClassId  TS_CLASSID, DMTS_CLASSID;
12 PetscLogEvent TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;
13 
14 const char *const TSExactFinalTimeOptions[] = {"UNSPECIFIED","STEPOVER","INTERPOLATE","MATCHSTEP","TSExactFinalTimeOption","TS_EXACTFINALTIME_",NULL};
15 
16 static PetscErrorCode TSAdaptSetDefaultType(TSAdapt adapt,TSAdaptType default_type)
17 {
18   PetscFunctionBegin;
19   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
20   PetscValidCharPointer(default_type,2);
21   if (!((PetscObject)adapt)->type_name) {
22     PetscCall(TSAdaptSetType(adapt,default_type));
23   }
24   PetscFunctionReturn(0);
25 }
26 
27 /*@
28    TSSetFromOptions - Sets various TS parameters from user options.
29 
30    Collective on TS
31 
32    Input Parameter:
33 .  ts - the TS context obtained from TSCreate()
34 
35    Options Database Keys:
36 +  -ts_type <type> - TSEULER, TSBEULER, TSSUNDIALS, TSPSEUDO, TSCN, TSRK, TSTHETA, TSALPHA, TSGLLE, TSSSP, TSGLEE, TSBSYMP, TSIRK
37 .  -ts_save_trajectory - checkpoint the solution at each time-step
38 .  -ts_max_time <time> - maximum time to compute to
39 .  -ts_time_span <t0,...tf> - sets the time span, solutions are computed and stored for each indicated time
40 .  -ts_max_steps <steps> - maximum number of time-steps to take
41 .  -ts_init_time <time> - initial time to start computation
42 .  -ts_final_time <time> - final time to compute to (deprecated: use -ts_max_time)
43 .  -ts_dt <dt> - initial time step
44 .  -ts_exact_final_time <stepover,interpolate,matchstep> - whether to stop at the exact given final time and how to compute the solution at that time
45 .  -ts_max_snes_failures <maxfailures> - Maximum number of nonlinear solve failures allowed
46 .  -ts_max_reject <maxrejects> - Maximum number of step rejections before step fails
47 .  -ts_error_if_step_fails <true,false> - Error if no step succeeds
48 .  -ts_rtol <rtol> - relative tolerance for local truncation error
49 .  -ts_atol <atol> - Absolute tolerance for local truncation error
50 .  -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - test the Jacobian at each iteration against finite difference with RHS function
51 .  -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - test the Jacobian at each iteration against finite difference with RHS function
52 .  -ts_adjoint_solve <yes,no> - After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory)
53 .  -ts_fd_color - Use finite differences with coloring to compute IJacobian
54 .  -ts_monitor - print information at each timestep
55 .  -ts_monitor_cancel - Cancel all monitors
56 .  -ts_monitor_lg_solution - Monitor solution graphically
57 .  -ts_monitor_lg_error - Monitor error graphically
58 .  -ts_monitor_error - Monitors norm of error
59 .  -ts_monitor_lg_timestep - Monitor timestep size graphically
60 .  -ts_monitor_lg_timestep_log - Monitor log timestep size graphically
61 .  -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically
62 .  -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically
63 .  -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically
64 .  -ts_monitor_draw_solution - Monitor solution graphically
65 .  -ts_monitor_draw_solution_phase  <xleft,yleft,xright,yright> - Monitor solution graphically with phase diagram, requires problem with exactly 2 degrees of freedom
66 .  -ts_monitor_draw_error - Monitor error graphically, requires use to have provided TSSetSolutionFunction()
67 .  -ts_monitor_solution [ascii binary draw][:filename][:viewerformat] - monitors the solution at each timestep
68 .  -ts_monitor_solution_vtk <filename.vts,filename.vtu> - Save each time step to a binary file, use filename-%%03" PetscInt_FMT ".vts (filename-%%03" PetscInt_FMT ".vtu)
69 -  -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
70 
71    Notes:
72      See SNESSetFromOptions() and KSPSetFromOptions() for how to control the nonlinear and linear solves used by the time-stepper.
73 
74      Certain SNES options get reset for each new nonlinear solver, for example -snes_lag_jacobian <its> and -snes_lag_preconditioner <its>, in order
75      to retain them over the multiple nonlinear solves that TS uses you mush also provide -snes_lag_jacobian_persists true and
76      -snes_lag_preconditioner_persists true
77 
78    Developer Note:
79      We should unify all the -ts_monitor options in the way that -xxx_view has been unified
80 
81    Level: beginner
82 
83 .seealso: `TSGetType()`
84 @*/
85 PetscErrorCode  TSSetFromOptions(TS ts)
86 {
87   PetscBool              opt,flg,tflg;
88   char                   monfilename[PETSC_MAX_PATH_LEN];
89   PetscReal              time_step,tspan[100];
90   PetscInt               nt = PETSC_STATIC_ARRAY_LENGTH(tspan);
91   TSExactFinalTimeOption eftopt;
92   char                   dir[16];
93   TSIFunction            ifun;
94   const char             *defaultType;
95   char                   typeName[256];
96 
97   PetscFunctionBegin;
98   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
99 
100   PetscCall(TSRegisterAll());
101   PetscCall(TSGetIFunction(ts,NULL,&ifun,NULL));
102 
103   PetscObjectOptionsBegin((PetscObject)ts);
104   if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name;
105   else defaultType = ifun ? TSBEULER : TSEULER;
106   PetscCall(PetscOptionsFList("-ts_type","TS method","TSSetType",TSList,defaultType,typeName,256,&opt));
107   if (opt) {
108     PetscCall(TSSetType(ts,typeName));
109   } else {
110     PetscCall(TSSetType(ts,defaultType));
111   }
112 
113   /* Handle generic TS options */
114   PetscCall(PetscOptionsDeprecated("-ts_final_time","-ts_max_time","3.10",NULL));
115   PetscCall(PetscOptionsReal("-ts_max_time","Maximum time to run to","TSSetMaxTime",ts->max_time,&ts->max_time,NULL));
116   PetscCall(PetscOptionsRealArray("-ts_time_span","Time span","TSSetTimeSpan",tspan,&nt,&flg));
117   if (flg) PetscCall(TSSetTimeSpan(ts,nt,tspan));
118   PetscCall(PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetMaxSteps",ts->max_steps,&ts->max_steps,NULL));
119   PetscCall(PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,NULL));
120   PetscCall(PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&time_step,&flg));
121   if (flg) PetscCall(TSSetTimeStep(ts,time_step));
122   PetscCall(PetscOptionsEnum("-ts_exact_final_time","Option for handling of final time step","TSSetExactFinalTime",TSExactFinalTimeOptions,(PetscEnum)ts->exact_final_time,(PetscEnum*)&eftopt,&flg));
123   if (flg) PetscCall(TSSetExactFinalTime(ts,eftopt));
124   PetscCall(PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","TSSetMaxSNESFailures",ts->max_snes_failures,&ts->max_snes_failures,NULL));
125   PetscCall(PetscOptionsInt("-ts_max_reject","Maximum number of step rejections before step fails","TSSetMaxStepRejections",ts->max_reject,&ts->max_reject,NULL));
126   PetscCall(PetscOptionsBool("-ts_error_if_step_fails","Error if no step succeeds","TSSetErrorIfStepFails",ts->errorifstepfailed,&ts->errorifstepfailed,NULL));
127   PetscCall(PetscOptionsReal("-ts_rtol","Relative tolerance for local truncation error","TSSetTolerances",ts->rtol,&ts->rtol,NULL));
128   PetscCall(PetscOptionsReal("-ts_atol","Absolute tolerance for local truncation error","TSSetTolerances",ts->atol,&ts->atol,NULL));
129 
130   PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult","Test the RHS Jacobian for consistency with RHS at each solve ","None",ts->testjacobian,&ts->testjacobian,NULL));
131   PetscCall(PetscOptionsBool("-ts_rhs_jacobian_test_mult_transpose","Test the RHS Jacobian transpose for consistency with RHS at each solve ","None",ts->testjacobiantranspose,&ts->testjacobiantranspose,NULL));
132   PetscCall(PetscOptionsBool("-ts_use_splitrhsfunction","Use the split RHS function for multirate solvers ","TSSetUseSplitRHSFunction",ts->use_splitrhsfunction,&ts->use_splitrhsfunction,NULL));
133 #if defined(PETSC_HAVE_SAWS)
134   {
135     PetscBool set;
136     flg  = PETSC_FALSE;
137     PetscCall(PetscOptionsBool("-ts_saws_block","Block for SAWs memory snooper at end of TSSolve","PetscObjectSAWsBlock",((PetscObject)ts)->amspublishblock,&flg,&set));
138     if (set) {
139       PetscCall(PetscObjectSAWsSetBlock((PetscObject)ts,flg));
140     }
141   }
142 #endif
143 
144   /* Monitor options */
145   PetscCall(PetscOptionsInt("-ts_monitor_frequency", "Number of time steps between monitor output", "TSMonitorSetFrequency", ts->monitorFrequency, &ts->monitorFrequency, NULL));
146   PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor","Monitor time and timestep size","TSMonitorDefault",TSMonitorDefault,NULL));
147   PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_extreme","Monitor extreme values of the solution","TSMonitorExtreme",TSMonitorExtreme,NULL));
148   PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_solution","View the solution at each timestep","TSMonitorSolution",TSMonitorSolution,NULL));
149   PetscCall(TSMonitorSetFromOptions(ts,"-ts_dmswarm_monitor_moments","Monitor moments of particle distribution","TSDMSwarmMonitorMoments",TSDMSwarmMonitorMoments,NULL));
150 
151   PetscCall(PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",NULL,monfilename,sizeof(monfilename),&flg));
152   if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ts,monfilename));
153 
154   PetscCall(PetscOptionsName("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",&opt));
155   if (opt) {
156     PetscInt       howoften = 1;
157     DM             dm;
158     PetscBool      net;
159 
160     PetscCall(PetscOptionsInt("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",howoften,&howoften,NULL));
161     PetscCall(TSGetDM(ts,&dm));
162     PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMNETWORK,&net));
163     if (net) {
164       TSMonitorLGCtxNetwork ctx;
165       PetscCall(TSMonitorLGCtxNetworkCreate(ts,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx));
166       PetscCall(TSMonitorSet(ts,TSMonitorLGCtxNetworkSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxNetworkDestroy));
167       PetscCall(PetscOptionsBool("-ts_monitor_lg_solution_semilogy","Plot the solution with a semi-log axis","",ctx->semilogy,&ctx->semilogy,NULL));
168     } else {
169       TSMonitorLGCtx ctx;
170       PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
171       PetscCall(TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
172     }
173   }
174 
175   PetscCall(PetscOptionsName("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",&opt));
176   if (opt) {
177     TSMonitorLGCtx ctx;
178     PetscInt       howoften = 1;
179 
180     PetscCall(PetscOptionsInt("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",howoften,&howoften,NULL));
181     PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
182     PetscCall(TSMonitorSet(ts,TSMonitorLGError,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
183   }
184   PetscCall(TSMonitorSetFromOptions(ts,"-ts_monitor_error","View the error at each timestep","TSMonitorError",TSMonitorError,NULL));
185 
186   PetscCall(PetscOptionsName("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",&opt));
187   if (opt) {
188     TSMonitorLGCtx ctx;
189     PetscInt       howoften = 1;
190 
191     PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL));
192     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
193     PetscCall(TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
194   }
195   PetscCall(PetscOptionsName("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",&opt));
196   if (opt) {
197     TSMonitorLGCtx ctx;
198     PetscInt       howoften = 1;
199 
200     PetscCall(PetscOptionsInt("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL));
201     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
202     PetscCall(TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
203     ctx->semilogy = PETSC_TRUE;
204   }
205 
206   PetscCall(PetscOptionsName("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",&opt));
207   if (opt) {
208     TSMonitorLGCtx ctx;
209     PetscInt       howoften = 1;
210 
211     PetscCall(PetscOptionsInt("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",howoften,&howoften,NULL));
212     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
213     PetscCall(TSMonitorSet(ts,TSMonitorLGSNESIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
214   }
215   PetscCall(PetscOptionsName("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",&opt));
216   if (opt) {
217     TSMonitorLGCtx ctx;
218     PetscInt       howoften = 1;
219 
220     PetscCall(PetscOptionsInt("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",howoften,&howoften,NULL));
221     PetscCall(TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx));
222     PetscCall(TSMonitorSet(ts,TSMonitorLGKSPIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy));
223   }
224   PetscCall(PetscOptionsName("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",&opt));
225   if (opt) {
226     TSMonitorSPEigCtx ctx;
227     PetscInt          howoften = 1;
228 
229     PetscCall(PetscOptionsInt("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",howoften,&howoften,NULL));
230     PetscCall(TSMonitorSPEigCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx));
231     PetscCall(TSMonitorSet(ts,TSMonitorSPEig,ctx,(PetscErrorCode (*)(void**))TSMonitorSPEigCtxDestroy));
232   }
233   PetscCall(PetscOptionsName("-ts_monitor_sp_swarm","Display particle phase from the DMSwarm","TSMonitorSPSwarm",&opt));
234   if (opt) {
235     TSMonitorSPCtx  ctx;
236     PetscInt        howoften = 1, retain = 0;
237     PetscBool       phase = PETSC_TRUE, create = PETSC_TRUE;
238 
239     for (PetscInt i = 0; i < ts->numbermonitors; ++i) if (ts->monitor[i] == TSMonitorSPSwarmSolution) {create = PETSC_FALSE;break;}
240     if (create) {
241       PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm","Display particles phase from the DMSwarm", "TSMonitorSPSwarm", howoften, &howoften, NULL));
242       PetscCall(PetscOptionsInt("-ts_monitor_sp_swarm_retain", "Retain n points plotted to show trajectory, -1 for all points", "TSMonitorSPSwarm", retain, &retain, NULL));
243       PetscCall(PetscOptionsBool("-ts_monitor_sp_swarm_phase", "Plot in phase space rather than coordinate space", "TSMonitorSPSwarm", phase, &phase, NULL));
244       PetscCall(TSMonitorSPCtxCreate(PetscObjectComm((PetscObject) ts), NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, retain, phase, &ctx));
245       PetscCall(TSMonitorSet(ts, TSMonitorSPSwarmSolution, ctx, (PetscErrorCode (*)(void**))TSMonitorSPCtxDestroy));
246     }
247   }
248   opt  = PETSC_FALSE;
249   PetscCall(PetscOptionsName("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",&opt));
250   if (opt) {
251     TSMonitorDrawCtx ctx;
252     PetscInt         howoften = 1;
253 
254     PetscCall(PetscOptionsInt("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",howoften,&howoften,NULL));
255     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Computed Solution",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx));
256     PetscCall(TSMonitorSet(ts,TSMonitorDrawSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy));
257   }
258   opt  = PETSC_FALSE;
259   PetscCall(PetscOptionsName("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",&opt));
260   if (opt) {
261     TSMonitorDrawCtx ctx;
262     PetscReal        bounds[4];
263     PetscInt         n = 4;
264     PetscDraw        draw;
265     PetscDrawAxis    axis;
266 
267     PetscCall(PetscOptionsRealArray("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",bounds,&n,NULL));
268     PetscCheck(n == 4,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Must provide bounding box of phase field");
269     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,1,&ctx));
270     PetscCall(PetscViewerDrawGetDraw(ctx->viewer,0,&draw));
271     PetscCall(PetscViewerDrawGetDrawAxis(ctx->viewer,0,&axis));
272     PetscCall(PetscDrawAxisSetLimits(axis,bounds[0],bounds[2],bounds[1],bounds[3]));
273     PetscCall(PetscDrawAxisSetLabels(axis,"Phase Diagram","Variable 1","Variable 2"));
274     PetscCall(TSMonitorSet(ts,TSMonitorDrawSolutionPhase,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy));
275   }
276   opt  = PETSC_FALSE;
277   PetscCall(PetscOptionsName("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",&opt));
278   if (opt) {
279     TSMonitorDrawCtx ctx;
280     PetscInt         howoften = 1;
281 
282     PetscCall(PetscOptionsInt("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",howoften,&howoften,NULL));
283     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Error",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx));
284     PetscCall(TSMonitorSet(ts,TSMonitorDrawError,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy));
285   }
286   opt  = PETSC_FALSE;
287   PetscCall(PetscOptionsName("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",&opt));
288   if (opt) {
289     TSMonitorDrawCtx ctx;
290     PetscInt         howoften = 1;
291 
292     PetscCall(PetscOptionsInt("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",howoften,&howoften,NULL));
293     PetscCall(TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),NULL,"Solution provided by user function",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx));
294     PetscCall(TSMonitorSet(ts,TSMonitorDrawSolutionFunction,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy));
295   }
296 
297   opt  = PETSC_FALSE;
298   PetscCall(PetscOptionsString("-ts_monitor_solution_vtk","Save each time step to a binary file, use filename-%%03" PetscInt_FMT ".vts","TSMonitorSolutionVTK",NULL,monfilename,sizeof(monfilename),&flg));
299   if (flg) {
300     const char *ptr,*ptr2;
301     char       *filetemplate;
302     PetscCheck(monfilename[0],PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03" PetscInt_FMT ".vts");
303     /* Do some cursory validation of the input. */
304     PetscCall(PetscStrstr(monfilename,"%",(char**)&ptr));
305     PetscCheck(ptr,PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03" PetscInt_FMT ".vts");
306     for (ptr++; ptr && *ptr; ptr++) {
307       PetscCall(PetscStrchr("DdiouxX",*ptr,(char**)&ptr2));
308       PetscCheck(ptr2 || (*ptr >= '0' && *ptr <= '9'),PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03" PetscInt_FMT ".vts");
309       if (ptr2) break;
310     }
311     PetscCall(PetscStrallocpy(monfilename,&filetemplate));
312     PetscCall(TSMonitorSet(ts,TSMonitorSolutionVTK,filetemplate,(PetscErrorCode (*)(void**))TSMonitorSolutionVTKDestroy));
313   }
314 
315   PetscCall(PetscOptionsString("-ts_monitor_dmda_ray","Display a ray of the solution","None","y=0",dir,sizeof(dir),&flg));
316   if (flg) {
317     TSMonitorDMDARayCtx *rayctx;
318     int                  ray = 0;
319     DMDirection          ddir;
320     DM                   da;
321     PetscMPIInt          rank;
322 
323     PetscCheck(dir[1] == '=',PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
324     if (dir[0] == 'x') ddir = DM_X;
325     else if (dir[0] == 'y') ddir = DM_Y;
326     else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
327     sscanf(dir+2,"%d",&ray);
328 
329     PetscCall(PetscInfo(((PetscObject)ts),"Displaying DMDA ray %c = %d\n",dir[0],ray));
330     PetscCall(PetscNew(&rayctx));
331     PetscCall(TSGetDM(ts,&da));
332     PetscCall(DMDAGetRay(da,ddir,ray,&rayctx->ray,&rayctx->scatter));
333     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)ts),&rank));
334     if (rank == 0) {
335       PetscCall(PetscViewerDrawOpen(PETSC_COMM_SELF,NULL,NULL,0,0,600,300,&rayctx->viewer));
336     }
337     rayctx->lgctx = NULL;
338     PetscCall(TSMonitorSet(ts,TSMonitorDMDARay,rayctx,TSMonitorDMDARayDestroy));
339   }
340   PetscCall(PetscOptionsString("-ts_monitor_lg_dmda_ray","Display a ray of the solution","None","x=0",dir,sizeof(dir),&flg));
341   if (flg) {
342     TSMonitorDMDARayCtx *rayctx;
343     int                 ray = 0;
344     DMDirection         ddir;
345     DM                  da;
346     PetscInt            howoften = 1;
347 
348     PetscCheck(dir[1] == '=',PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir);
349     if      (dir[0] == 'x') ddir = DM_X;
350     else if (dir[0] == 'y') ddir = DM_Y;
351     else SETERRQ(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir);
352     sscanf(dir+2, "%d", &ray);
353 
354     PetscCall(PetscInfo(((PetscObject) ts),"Displaying LG DMDA ray %c = %d\n", dir[0], ray));
355     PetscCall(PetscNew(&rayctx));
356     PetscCall(TSGetDM(ts, &da));
357     PetscCall(DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter));
358     PetscCall(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&rayctx->lgctx));
359     PetscCall(TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy));
360   }
361 
362   PetscCall(PetscOptionsName("-ts_monitor_envelope","Monitor maximum and minimum value of each component of the solution","TSMonitorEnvelope",&opt));
363   if (opt) {
364     TSMonitorEnvelopeCtx ctx;
365 
366     PetscCall(TSMonitorEnvelopeCtxCreate(ts,&ctx));
367     PetscCall(TSMonitorSet(ts,TSMonitorEnvelope,ctx,(PetscErrorCode (*)(void**))TSMonitorEnvelopeCtxDestroy));
368   }
369   flg  = PETSC_FALSE;
370   PetscCall(PetscOptionsBool("-ts_monitor_cancel","Remove all monitors","TSMonitorCancel",flg,&flg,&opt));
371   if (opt && flg) PetscCall(TSMonitorCancel(ts));
372 
373   flg  = PETSC_FALSE;
374   PetscCall(PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeJacobianDefaultColor", flg, &flg, NULL));
375   if (flg) {
376     DM   dm;
377     DMTS tdm;
378 
379     PetscCall(TSGetDM(ts, &dm));
380     PetscCall(DMGetDMTS(dm, &tdm));
381     tdm->ijacobianctx = NULL;
382     PetscCall(TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, NULL));
383     PetscCall(PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n"));
384   }
385 
386   /* Handle specific TS options */
387   if (ts->ops->setfromoptions) {
388     PetscCall((*ts->ops->setfromoptions)(PetscOptionsObject,ts));
389   }
390 
391   /* Handle TSAdapt options */
392   PetscCall(TSGetAdapt(ts,&ts->adapt));
393   PetscCall(TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type));
394   PetscCall(TSAdaptSetFromOptions(PetscOptionsObject,ts->adapt));
395 
396   /* TS trajectory must be set after TS, since it may use some TS options above */
397   tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE;
398   PetscCall(PetscOptionsBool("-ts_save_trajectory","Save the solution at each timestep","TSSetSaveTrajectory",tflg,&tflg,NULL));
399   if (tflg) {
400     PetscCall(TSSetSaveTrajectory(ts));
401   }
402 
403   PetscCall(TSAdjointSetFromOptions(PetscOptionsObject,ts));
404 
405   /* process any options handlers added with PetscObjectAddOptionsHandler() */
406   PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)ts));
407   PetscOptionsEnd();
408 
409   if (ts->trajectory) {
410     PetscCall(TSTrajectorySetFromOptions(ts->trajectory,ts));
411   }
412 
413   /* why do we have to do this here and not during TSSetUp? */
414   PetscCall(TSGetSNES(ts,&ts->snes));
415   if (ts->problem_type == TS_LINEAR) {
416     PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes,&flg,SNESKSPONLY,SNESKSPTRANSPOSEONLY,""));
417     if (!flg) PetscCall(SNESSetType(ts->snes,SNESKSPONLY));
418   }
419   PetscCall(SNESSetFromOptions(ts->snes));
420   PetscFunctionReturn(0);
421 }
422 
423 /*@
424    TSGetTrajectory - Gets the trajectory from a TS if it exists
425 
426    Collective on TS
427 
428    Input Parameters:
429 .  ts - the TS context obtained from TSCreate()
430 
431    Output Parameters:
432 .  tr - the TSTrajectory object, if it exists
433 
434    Note: This routine should be called after all TS options have been set
435 
436    Level: advanced
437 
438 .seealso: `TSGetTrajectory()`, `TSAdjointSolve()`, `TSTrajectory`, `TSTrajectoryCreate()`
439 
440 @*/
441 PetscErrorCode  TSGetTrajectory(TS ts,TSTrajectory *tr)
442 {
443   PetscFunctionBegin;
444   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
445   *tr = ts->trajectory;
446   PetscFunctionReturn(0);
447 }
448 
449 /*@
450    TSSetSaveTrajectory - Causes the TS to save its solutions as it iterates forward in time in a TSTrajectory object
451 
452    Collective on TS
453 
454    Input Parameter:
455 .  ts - the TS context obtained from TSCreate()
456 
457    Options Database:
458 +  -ts_save_trajectory - saves the trajectory to a file
459 -  -ts_trajectory_type type - set trajectory type
460 
461 Note: This routine should be called after all TS options have been set
462 
463     The TSTRAJECTORYVISUALIZATION files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and
464    MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m
465 
466    Level: intermediate
467 
468 .seealso: `TSGetTrajectory()`, `TSAdjointSolve()`
469 
470 @*/
471 PetscErrorCode  TSSetSaveTrajectory(TS ts)
472 {
473   PetscFunctionBegin;
474   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
475   if (!ts->trajectory) PetscCall(TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory));
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.",(double)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 (primitive 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=%" PetscInt_FMT "\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=%" PetscInt_FMT "\n",ts->ifuncs));
2057     }
2058     if (ts->ijacs) {
2059       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of I Jacobian evaluations=%" PetscInt_FMT "\n",ts->ijacs));
2060     }
2061     if (ts->rhsfuncs) {
2062       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of RHS function evaluations=%" PetscInt_FMT "\n",ts->rhsfuncs));
2063     }
2064     if (ts->rhsjacs) {
2065       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of RHS Jacobian evaluations=%" PetscInt_FMT "\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=%" PetscInt_FMT "\n",ts->snes_its));
2071       }
2072       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of linear solver iterations=%" PetscInt_FMT "\n",ts->ksp_its));
2073       PetscCall(PetscObjectTypeCompareAny((PetscObject)ts->snes,&lin,SNESKSPONLY,SNESKSPTRANSPOSEONLY,""));
2074       PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of %slinear solve failures=%" PetscInt_FMT "\n",lin ? "" : "non",ts->num_snes_failures));
2075     }
2076     PetscCall(PetscViewerASCIIPrintf(viewer,"  total number of rejected steps=%" PetscInt_FMT "\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]",(double)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   static PetscBool cite = PETSC_FALSE;
3534   PetscReal        ptime;
3535 
3536   PetscFunctionBegin;
3537   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3538   PetscCall(PetscCitationsRegister("@article{tspaper,\n"
3539                                    "  title         = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3540                                    "  author        = {Abhyankar, Shrirang and Brown, Jed and Constantinescu, Emil and Ghosh, Debojyoti and Smith, Barry F. and Zhang, Hong},\n"
3541                                    "  journal       = {arXiv e-preprints},\n"
3542                                    "  eprint        = {1806.01437},\n"
3543                                    "  archivePrefix = {arXiv},\n"
3544                                    "  year          = {2018}\n}\n",&cite));
3545   PetscCall(TSSetUp(ts));
3546   PetscCall(TSTrajectorySetUp(ts->trajectory,ts));
3547 
3548   PetscCheck(ts->ops->step,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3549   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>");
3550   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()");
3551   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");
3552 
3553   if (!ts->steps) ts->ptime_prev = ts->ptime;
3554   ptime = ts->ptime; ts->ptime_prev_rollback = ts->ptime_prev;
3555   ts->reason = TS_CONVERGED_ITERATING;
3556 
3557   PetscCall(PetscLogEventBegin(TS_Step,ts,0,0,0));
3558   PetscCall((*ts->ops->step)(ts));
3559   PetscCall(PetscLogEventEnd(TS_Step,ts,0,0,0));
3560 
3561   if (ts->reason >= 0) {
3562     ts->ptime_prev = ptime;
3563     ts->steps++;
3564     ts->steprollback = PETSC_FALSE;
3565     ts->steprestart  = PETSC_FALSE;
3566     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++]));
3567   }
3568 
3569   if (!ts->reason) {
3570     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
3571     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3572   }
3573 
3574   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]);
3575   PetscCheck(ts->reason >= 0 || !ts->errorifstepfailed,PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
3576   PetscFunctionReturn(0);
3577 }
3578 
3579 /*@
3580    TSEvaluateWLTE - Evaluate the weighted local truncation error norm
3581    at the end of a time step with a given order of accuracy.
3582 
3583    Collective on TS
3584 
3585    Input Parameters:
3586 +  ts - time stepping context
3587 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
3588 
3589    Input/Output Parameter:
3590 .  order - optional, desired order for the error evaluation or PETSC_DECIDE;
3591            on output, the actual order of the error evaluation
3592 
3593    Output Parameter:
3594 .  wlte - the weighted local truncation error norm
3595 
3596    Level: advanced
3597 
3598    Notes:
3599    If the timestepper cannot evaluate the error in a particular step
3600    (eg. in the first step or restart steps after event handling),
3601    this routine returns wlte=-1.0 .
3602 
3603 .seealso: `TSStep()`, `TSAdapt`, `TSErrorWeightedNorm()`
3604 @*/
3605 PetscErrorCode TSEvaluateWLTE(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte)
3606 {
3607   PetscFunctionBegin;
3608   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3609   PetscValidType(ts,1);
3610   PetscValidLogicalCollectiveEnum(ts,wnormtype,2);
3611   if (order) PetscValidIntPointer(order,3);
3612   if (order) PetscValidLogicalCollectiveInt(ts,*order,3);
3613   PetscValidRealPointer(wlte,4);
3614   PetscCheck(wnormtype == NORM_2 || wnormtype == NORM_INFINITY,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
3615   PetscCheck(ts->ops->evaluatewlte,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateWLTE not implemented for type '%s'",((PetscObject)ts)->type_name);
3616   PetscCall((*ts->ops->evaluatewlte)(ts,wnormtype,order,wlte));
3617   PetscFunctionReturn(0);
3618 }
3619 
3620 /*@
3621    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
3622 
3623    Collective on TS
3624 
3625    Input Parameters:
3626 +  ts - time stepping context
3627 .  order - desired order of accuracy
3628 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
3629 
3630    Output Parameter:
3631 .  U - state at the end of the current step
3632 
3633    Level: advanced
3634 
3635    Notes:
3636    This function cannot be called until all stages have been evaluated.
3637    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.
3638 
3639 .seealso: `TSStep()`, `TSAdapt`
3640 @*/
3641 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
3642 {
3643   PetscFunctionBegin;
3644   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3645   PetscValidType(ts,1);
3646   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3647   PetscCheck(ts->ops->evaluatestep,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3648   PetscCall((*ts->ops->evaluatestep)(ts,order,U,done));
3649   PetscFunctionReturn(0);
3650 }
3651 
3652 /*@C
3653   TSGetComputeInitialCondition - Get the function used to automatically compute an initial condition for the timestepping.
3654 
3655   Not collective
3656 
3657   Input Parameter:
3658 . ts        - time stepping context
3659 
3660   Output Parameter:
3661 . initConditions - The function which computes an initial condition
3662 
3663    Level: advanced
3664 
3665    Notes:
3666    The calling sequence for the function is
3667 $ initCondition(TS ts, Vec u)
3668 $ ts - The timestepping context
3669 $ u  - The input vector in which the initial condition is stored
3670 
3671 .seealso: `TSSetComputeInitialCondition()`, `TSComputeInitialCondition()`
3672 @*/
3673 PetscErrorCode TSGetComputeInitialCondition(TS ts, PetscErrorCode (**initCondition)(TS, Vec))
3674 {
3675   PetscFunctionBegin;
3676   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3677   PetscValidPointer(initCondition, 2);
3678   *initCondition = ts->ops->initcondition;
3679   PetscFunctionReturn(0);
3680 }
3681 
3682 /*@C
3683   TSSetComputeInitialCondition - Set the function used to automatically compute an initial condition for the timestepping.
3684 
3685   Logically collective on ts
3686 
3687   Input Parameters:
3688 + ts        - time stepping context
3689 - initCondition - The function which computes an initial condition
3690 
3691   Level: advanced
3692 
3693   Calling sequence for initCondition:
3694 $ PetscErrorCode initCondition(TS ts, Vec u)
3695 
3696 + ts - The timestepping context
3697 - u  - The input vector in which the initial condition is to be stored
3698 
3699 .seealso: `TSGetComputeInitialCondition()`, `TSComputeInitialCondition()`
3700 @*/
3701 PetscErrorCode TSSetComputeInitialCondition(TS ts, PetscErrorCode (*initCondition)(TS, Vec))
3702 {
3703   PetscFunctionBegin;
3704   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3705   PetscValidFunction(initCondition, 2);
3706   ts->ops->initcondition = initCondition;
3707   PetscFunctionReturn(0);
3708 }
3709 
3710 /*@
3711   TSComputeInitialCondition - Compute an initial condition for the timestepping using the function previously set.
3712 
3713   Collective on ts
3714 
3715   Input Parameters:
3716 + ts - time stepping context
3717 - u  - The Vec to store the condition in which will be used in TSSolve()
3718 
3719   Level: advanced
3720 
3721 .seealso: `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3722 @*/
3723 PetscErrorCode TSComputeInitialCondition(TS ts, Vec u)
3724 {
3725   PetscFunctionBegin;
3726   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3727   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
3728   if (ts->ops->initcondition) PetscCall((*ts->ops->initcondition)(ts, u));
3729   PetscFunctionReturn(0);
3730 }
3731 
3732 /*@C
3733   TSGetComputeExactError - Get the function used to automatically compute the exact error for the timestepping.
3734 
3735   Not collective
3736 
3737   Input Parameter:
3738 . ts         - time stepping context
3739 
3740   Output Parameter:
3741 . exactError - The function which computes the solution error
3742 
3743   Level: advanced
3744 
3745   Calling sequence for exactError:
3746 $ PetscErrorCode exactError(TS ts, Vec u)
3747 
3748 + ts - The timestepping context
3749 . u  - The approximate solution vector
3750 - e  - The input vector in which the error is stored
3751 
3752 .seealso: `TSGetComputeExactError()`, `TSComputeExactError()`
3753 @*/
3754 PetscErrorCode TSGetComputeExactError(TS ts, PetscErrorCode (**exactError)(TS, Vec, Vec))
3755 {
3756   PetscFunctionBegin;
3757   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3758   PetscValidPointer(exactError, 2);
3759   *exactError = ts->ops->exacterror;
3760   PetscFunctionReturn(0);
3761 }
3762 
3763 /*@C
3764   TSSetComputeExactError - Set the function used to automatically compute the exact error for the timestepping.
3765 
3766   Logically collective on ts
3767 
3768   Input Parameters:
3769 + ts         - time stepping context
3770 - exactError - The function which computes the solution error
3771 
3772   Level: advanced
3773 
3774   Calling sequence for exactError:
3775 $ PetscErrorCode exactError(TS ts, Vec u)
3776 
3777 + ts - The timestepping context
3778 . u  - The approximate solution vector
3779 - e  - The input vector in which the error is stored
3780 
3781 .seealso: `TSGetComputeExactError()`, `TSComputeExactError()`
3782 @*/
3783 PetscErrorCode TSSetComputeExactError(TS ts, PetscErrorCode (*exactError)(TS, Vec, Vec))
3784 {
3785   PetscFunctionBegin;
3786   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3787   PetscValidFunction(exactError, 2);
3788   ts->ops->exacterror = exactError;
3789   PetscFunctionReturn(0);
3790 }
3791 
3792 /*@
3793   TSComputeExactError - Compute the solution error for the timestepping using the function previously set.
3794 
3795   Collective on ts
3796 
3797   Input Parameters:
3798 + ts - time stepping context
3799 . u  - The approximate solution
3800 - e  - The Vec used to store the error
3801 
3802   Level: advanced
3803 
3804 .seealso: `TSGetComputeInitialCondition()`, `TSSetComputeInitialCondition()`, `TSSolve()`
3805 @*/
3806 PetscErrorCode TSComputeExactError(TS ts, Vec u, Vec e)
3807 {
3808   PetscFunctionBegin;
3809   PetscValidHeaderSpecific(ts, TS_CLASSID, 1);
3810   PetscValidHeaderSpecific(u, VEC_CLASSID, 2);
3811   PetscValidHeaderSpecific(e, VEC_CLASSID, 3);
3812   if (ts->ops->exacterror) PetscCall((*ts->ops->exacterror)(ts, u, e));
3813   PetscFunctionReturn(0);
3814 }
3815 
3816 /*@
3817    TSSolve - Steps the requested number of timesteps.
3818 
3819    Collective on TS
3820 
3821    Input Parameters:
3822 +  ts - the TS context obtained from TSCreate()
3823 -  u - the solution vector  (can be null if TSSetSolution() was used and TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP) was not used,
3824                              otherwise must contain the initial conditions and will contain the solution at the final requested time
3825 
3826    Level: beginner
3827 
3828    Notes:
3829    The final time returned by this function may be different from the time of the internally
3830    held state accessible by TSGetSolution() and TSGetTime() because the method may have
3831    stepped over the final time.
3832 
3833 .seealso: `TSCreate()`, `TSSetSolution()`, `TSStep()`, `TSGetTime()`, `TSGetSolveTime()`
3834 @*/
3835 PetscErrorCode TSSolve(TS ts,Vec u)
3836 {
3837   Vec               solution;
3838 
3839   PetscFunctionBegin;
3840   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3841   if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3842 
3843   PetscCall(TSSetExactFinalTimeDefault(ts));
3844   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 */
3845     if (!ts->vec_sol || u == ts->vec_sol) {
3846       PetscCall(VecDuplicate(u,&solution));
3847       PetscCall(TSSetSolution(ts,solution));
3848       PetscCall(VecDestroy(&solution)); /* grant ownership */
3849     }
3850     PetscCall(VecCopy(u,ts->vec_sol));
3851     PetscCheck(!ts->forward_solve,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
3852   } else if (u) {
3853     PetscCall(TSSetSolution(ts,u));
3854   }
3855   PetscCall(TSSetUp(ts));
3856   PetscCall(TSTrajectorySetUp(ts->trajectory,ts));
3857 
3858   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>");
3859   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()");
3860   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");
3861   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");
3862 
3863   if (ts->tspan && PetscIsCloseAtTol(ts->ptime,ts->tspan->span_times[0],10*PETSC_MACHINE_EPSILON,0)) { /* starting point in time span */
3864     PetscCall(VecCopy(ts->vec_sol,ts->tspan->vecs_sol[0]));
3865     ts->tspan->spanctr = 1;
3866   }
3867 
3868   if (ts->forward_solve) {
3869     PetscCall(TSForwardSetUp(ts));
3870   }
3871 
3872   /* reset number of steps only when the step is not restarted. ARKIMEX
3873      restarts the step after an event. Resetting these counters in such case causes
3874      TSTrajectory to incorrectly save the output files
3875   */
3876   /* reset time step and iteration counters */
3877   if (!ts->steps) {
3878     ts->ksp_its           = 0;
3879     ts->snes_its          = 0;
3880     ts->num_snes_failures = 0;
3881     ts->reject            = 0;
3882     ts->steprestart       = PETSC_TRUE;
3883     ts->steprollback      = PETSC_FALSE;
3884     ts->rhsjacobian.time  = PETSC_MIN_REAL;
3885   }
3886 
3887   /* make sure initial time step does not overshoot final time or the next point in tspan */
3888   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
3889     PetscReal maxdt;
3890     PetscReal dt = ts->time_step;
3891 
3892     if (ts->tspan) maxdt = ts->tspan->span_times[ts->tspan->spanctr] - ts->ptime;
3893     else maxdt = ts->max_time - ts->ptime;
3894     ts->time_step = dt >= maxdt ? maxdt : (PetscIsCloseAtTol(dt,maxdt,10*PETSC_MACHINE_EPSILON,0) ? maxdt : dt);
3895   }
3896   ts->reason = TS_CONVERGED_ITERATING;
3897 
3898   {
3899     PetscViewer       viewer;
3900     PetscViewerFormat format;
3901     PetscBool         flg;
3902     static PetscBool  incall = PETSC_FALSE;
3903 
3904     if (!incall) {
3905       /* Estimate the convergence rate of the time discretization */
3906       PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject) ts),((PetscObject)ts)->options, ((PetscObject) ts)->prefix, "-ts_convergence_estimate", &viewer, &format, &flg));
3907       if (flg) {
3908         PetscConvEst conv;
3909         DM           dm;
3910         PetscReal   *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */
3911         PetscInt     Nf;
3912         PetscBool    checkTemporal = PETSC_TRUE;
3913 
3914         incall = PETSC_TRUE;
3915         PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject) ts)->prefix, "-ts_convergence_temporal", &checkTemporal, &flg));
3916         PetscCall(TSGetDM(ts, &dm));
3917         PetscCall(DMGetNumFields(dm, &Nf));
3918         PetscCall(PetscCalloc1(PetscMax(Nf, 1), &alpha));
3919         PetscCall(PetscConvEstCreate(PetscObjectComm((PetscObject) ts), &conv));
3920         PetscCall(PetscConvEstUseTS(conv, checkTemporal));
3921         PetscCall(PetscConvEstSetSolver(conv, (PetscObject) ts));
3922         PetscCall(PetscConvEstSetFromOptions(conv));
3923         PetscCall(PetscConvEstSetUp(conv));
3924         PetscCall(PetscConvEstGetConvRate(conv, alpha));
3925         PetscCall(PetscViewerPushFormat(viewer, format));
3926         PetscCall(PetscConvEstRateView(conv, alpha, viewer));
3927         PetscCall(PetscViewerPopFormat(viewer));
3928         PetscCall(PetscViewerDestroy(&viewer));
3929         PetscCall(PetscConvEstDestroy(&conv));
3930         PetscCall(PetscFree(alpha));
3931         incall = PETSC_FALSE;
3932       }
3933     }
3934   }
3935 
3936   PetscCall(TSViewFromOptions(ts,NULL,"-ts_view_pre"));
3937 
3938   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
3939     PetscCall((*ts->ops->solve)(ts));
3940     if (u) PetscCall(VecCopy(ts->vec_sol,u));
3941     ts->solvetime = ts->ptime;
3942     solution = ts->vec_sol;
3943   } else { /* Step the requested number of timesteps. */
3944     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
3945     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3946 
3947     if (!ts->steps) {
3948       PetscCall(TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol));
3949       PetscCall(TSEventInitialize(ts->event,ts,ts->ptime,ts->vec_sol));
3950     }
3951 
3952     while (!ts->reason) {
3953       PetscCall(TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol));
3954       if (!ts->steprollback) {
3955         PetscCall(TSPreStep(ts));
3956       }
3957       PetscCall(TSStep(ts));
3958       if (ts->testjacobian) {
3959         PetscCall(TSRHSJacobianTest(ts,NULL));
3960       }
3961       if (ts->testjacobiantranspose) {
3962         PetscCall(TSRHSJacobianTestTranspose(ts,NULL));
3963       }
3964       if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
3965         if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
3966         PetscCall(TSForwardCostIntegral(ts));
3967         if (ts->reason >= 0) ts->steps++;
3968       }
3969       if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
3970         if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
3971         PetscCall(TSForwardStep(ts));
3972         if (ts->reason >= 0) ts->steps++;
3973       }
3974       PetscCall(TSPostEvaluate(ts));
3975       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. */
3976       if (ts->steprollback) {
3977         PetscCall(TSPostEvaluate(ts));
3978       }
3979       if (!ts->steprollback) {
3980         PetscCall(TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol));
3981         PetscCall(TSPostStep(ts));
3982       }
3983     }
3984     PetscCall(TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol));
3985 
3986     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
3987       PetscCall(TSInterpolate(ts,ts->max_time,u));
3988       ts->solvetime = ts->max_time;
3989       solution = u;
3990       PetscCall(TSMonitor(ts,-1,ts->solvetime,solution));
3991     } else {
3992       if (u) PetscCall(VecCopy(ts->vec_sol,u));
3993       ts->solvetime = ts->ptime;
3994       solution = ts->vec_sol;
3995     }
3996   }
3997 
3998   PetscCall(TSViewFromOptions(ts,NULL,"-ts_view"));
3999   PetscCall(VecViewFromOptions(solution,(PetscObject)ts,"-ts_view_solution"));
4000   PetscCall(PetscObjectSAWsBlock((PetscObject)ts));
4001   if (ts->adjoint_solve) {
4002     PetscCall(TSAdjointSolve(ts));
4003   }
4004   PetscFunctionReturn(0);
4005 }
4006 
4007 /*@
4008    TSGetTime - Gets the time of the most recently completed step.
4009 
4010    Not Collective
4011 
4012    Input Parameter:
4013 .  ts - the TS context obtained from TSCreate()
4014 
4015    Output Parameter:
4016 .  t  - the current time. This time may not corresponds to the final time set with TSSetMaxTime(), use TSGetSolveTime().
4017 
4018    Level: beginner
4019 
4020    Note:
4021    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
4022    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
4023 
4024 .seealso: `TSGetSolveTime()`, `TSSetTime()`, `TSGetTimeStep()`, `TSGetStepNumber()`
4025 
4026 @*/
4027 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
4028 {
4029   PetscFunctionBegin;
4030   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4031   PetscValidRealPointer(t,2);
4032   *t = ts->ptime;
4033   PetscFunctionReturn(0);
4034 }
4035 
4036 /*@
4037    TSGetPrevTime - Gets the starting time of the previously completed step.
4038 
4039    Not Collective
4040 
4041    Input Parameter:
4042 .  ts - the TS context obtained from TSCreate()
4043 
4044    Output Parameter:
4045 .  t  - the previous time
4046 
4047    Level: beginner
4048 
4049 .seealso: `TSGetTime()`, `TSGetSolveTime()`, `TSGetTimeStep()`
4050 
4051 @*/
4052 PetscErrorCode  TSGetPrevTime(TS ts,PetscReal *t)
4053 {
4054   PetscFunctionBegin;
4055   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4056   PetscValidRealPointer(t,2);
4057   *t = ts->ptime_prev;
4058   PetscFunctionReturn(0);
4059 }
4060 
4061 /*@
4062    TSSetTime - Allows one to reset the time.
4063 
4064    Logically Collective on TS
4065 
4066    Input Parameters:
4067 +  ts - the TS context obtained from TSCreate()
4068 -  time - the time
4069 
4070    Level: intermediate
4071 
4072 .seealso: `TSGetTime()`, `TSSetMaxSteps()`
4073 
4074 @*/
4075 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
4076 {
4077   PetscFunctionBegin;
4078   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4079   PetscValidLogicalCollectiveReal(ts,t,2);
4080   ts->ptime = t;
4081   PetscFunctionReturn(0);
4082 }
4083 
4084 /*@C
4085    TSSetOptionsPrefix - Sets the prefix used for searching for all
4086    TS options in the database.
4087 
4088    Logically Collective on TS
4089 
4090    Input Parameters:
4091 +  ts     - The TS context
4092 -  prefix - The prefix to prepend to all option names
4093 
4094    Notes:
4095    A hyphen (-) must NOT be given at the beginning of the prefix name.
4096    The first character of all runtime options is AUTOMATICALLY the
4097    hyphen.
4098 
4099    Level: advanced
4100 
4101 .seealso: `TSSetFromOptions()`
4102 
4103 @*/
4104 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
4105 {
4106   SNES           snes;
4107 
4108   PetscFunctionBegin;
4109   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4110   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ts,prefix));
4111   PetscCall(TSGetSNES(ts,&snes));
4112   PetscCall(SNESSetOptionsPrefix(snes,prefix));
4113   PetscFunctionReturn(0);
4114 }
4115 
4116 /*@C
4117    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4118    TS options in the database.
4119 
4120    Logically Collective on TS
4121 
4122    Input Parameters:
4123 +  ts     - The TS context
4124 -  prefix - The prefix to prepend to all option names
4125 
4126    Notes:
4127    A hyphen (-) must NOT be given at the beginning of the prefix name.
4128    The first character of all runtime options is AUTOMATICALLY the
4129    hyphen.
4130 
4131    Level: advanced
4132 
4133 .seealso: `TSGetOptionsPrefix()`
4134 
4135 @*/
4136 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
4137 {
4138   SNES           snes;
4139 
4140   PetscFunctionBegin;
4141   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4142   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix));
4143   PetscCall(TSGetSNES(ts,&snes));
4144   PetscCall(SNESAppendOptionsPrefix(snes,prefix));
4145   PetscFunctionReturn(0);
4146 }
4147 
4148 /*@C
4149    TSGetOptionsPrefix - Sets the prefix used for searching for all
4150    TS options in the database.
4151 
4152    Not Collective
4153 
4154    Input Parameter:
4155 .  ts - The TS context
4156 
4157    Output Parameter:
4158 .  prefix - A pointer to the prefix string used
4159 
4160    Notes:
4161     On the fortran side, the user should pass in a string 'prifix' of
4162    sufficient length to hold the prefix.
4163 
4164    Level: intermediate
4165 
4166 .seealso: `TSAppendOptionsPrefix()`
4167 @*/
4168 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
4169 {
4170   PetscFunctionBegin;
4171   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4172   PetscValidPointer(prefix,2);
4173   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ts,prefix));
4174   PetscFunctionReturn(0);
4175 }
4176 
4177 /*@C
4178    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4179 
4180    Not Collective, but parallel objects are returned if TS is parallel
4181 
4182    Input Parameter:
4183 .  ts  - The TS context obtained from TSCreate()
4184 
4185    Output Parameters:
4186 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
4187 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
4188 .  func - Function to compute the Jacobian of the RHS  (or NULL)
4189 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
4190 
4191    Notes:
4192     You can pass in NULL for any return argument you do not need.
4193 
4194    Level: intermediate
4195 
4196 .seealso: `TSGetTimeStep()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4197 
4198 @*/
4199 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
4200 {
4201   DM             dm;
4202 
4203   PetscFunctionBegin;
4204   if (Amat || Pmat) {
4205     SNES snes;
4206     PetscCall(TSGetSNES(ts,&snes));
4207     PetscCall(SNESSetUpMatrices(snes));
4208     PetscCall(SNESGetJacobian(snes,Amat,Pmat,NULL,NULL));
4209   }
4210   PetscCall(TSGetDM(ts,&dm));
4211   PetscCall(DMTSGetRHSJacobian(dm,func,ctx));
4212   PetscFunctionReturn(0);
4213 }
4214 
4215 /*@C
4216    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4217 
4218    Not Collective, but parallel objects are returned if TS is parallel
4219 
4220    Input Parameter:
4221 .  ts  - The TS context obtained from TSCreate()
4222 
4223    Output Parameters:
4224 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
4225 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
4226 .  f   - The function to compute the matrices
4227 - ctx - User-defined context for Jacobian evaluation routine
4228 
4229    Notes:
4230     You can pass in NULL for any return argument you do not need.
4231 
4232    Level: advanced
4233 
4234 .seealso: `TSGetTimeStep()`, `TSGetRHSJacobian()`, `TSGetMatrices()`, `TSGetTime()`, `TSGetStepNumber()`
4235 
4236 @*/
4237 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
4238 {
4239   DM             dm;
4240 
4241   PetscFunctionBegin;
4242   if (Amat || Pmat) {
4243     SNES snes;
4244     PetscCall(TSGetSNES(ts,&snes));
4245     PetscCall(SNESSetUpMatrices(snes));
4246     PetscCall(SNESGetJacobian(snes,Amat,Pmat,NULL,NULL));
4247   }
4248   PetscCall(TSGetDM(ts,&dm));
4249   PetscCall(DMTSGetIJacobian(dm,f,ctx));
4250   PetscFunctionReturn(0);
4251 }
4252 
4253 #include <petsc/private/dmimpl.h>
4254 /*@
4255    TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS
4256 
4257    Logically Collective on ts
4258 
4259    Input Parameters:
4260 +  ts - the ODE integrator object
4261 -  dm - the dm, cannot be NULL
4262 
4263    Notes:
4264    A DM can only be used for solving one problem at a time because information about the problem is stored on the DM,
4265    even when not using interfaces like DMTSSetIFunction().  Use DMClone() to get a distinct DM when solving
4266    different problems using the same function space.
4267 
4268    Level: intermediate
4269 
4270 .seealso: `TSGetDM()`, `SNESSetDM()`, `SNESGetDM()`
4271 @*/
4272 PetscErrorCode  TSSetDM(TS ts,DM dm)
4273 {
4274   SNES           snes;
4275   DMTS           tsdm;
4276 
4277   PetscFunctionBegin;
4278   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4279   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
4280   PetscCall(PetscObjectReference((PetscObject)dm));
4281   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
4282     if (ts->dm->dmts && !dm->dmts) {
4283       PetscCall(DMCopyDMTS(ts->dm,dm));
4284       PetscCall(DMGetDMTS(ts->dm,&tsdm));
4285       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
4286         tsdm->originaldm = dm;
4287       }
4288     }
4289     PetscCall(DMDestroy(&ts->dm));
4290   }
4291   ts->dm = dm;
4292 
4293   PetscCall(TSGetSNES(ts,&snes));
4294   PetscCall(SNESSetDM(snes,dm));
4295   PetscFunctionReturn(0);
4296 }
4297 
4298 /*@
4299    TSGetDM - Gets the DM that may be used by some preconditioners
4300 
4301    Not Collective
4302 
4303    Input Parameter:
4304 . ts - the preconditioner context
4305 
4306    Output Parameter:
4307 .  dm - the dm
4308 
4309    Level: intermediate
4310 
4311 .seealso: `TSSetDM()`, `SNESSetDM()`, `SNESGetDM()`
4312 @*/
4313 PetscErrorCode  TSGetDM(TS ts,DM *dm)
4314 {
4315   PetscFunctionBegin;
4316   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4317   if (!ts->dm) {
4318     PetscCall(DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm));
4319     if (ts->snes) PetscCall(SNESSetDM(ts->snes,ts->dm));
4320   }
4321   *dm = ts->dm;
4322   PetscFunctionReturn(0);
4323 }
4324 
4325 /*@
4326    SNESTSFormFunction - Function to evaluate nonlinear residual
4327 
4328    Logically Collective on SNES
4329 
4330    Input Parameters:
4331 + snes - nonlinear solver
4332 . U - the current state at which to evaluate the residual
4333 - ctx - user context, must be a TS
4334 
4335    Output Parameter:
4336 . F - the nonlinear residual
4337 
4338    Notes:
4339    This function is not normally called by users and is automatically registered with the SNES used by TS.
4340    It is most frequently passed to MatFDColoringSetFunction().
4341 
4342    Level: advanced
4343 
4344 .seealso: `SNESSetFunction()`, `MatFDColoringSetFunction()`
4345 @*/
4346 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
4347 {
4348   TS             ts = (TS)ctx;
4349 
4350   PetscFunctionBegin;
4351   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4352   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4353   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
4354   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
4355   PetscCall((ts->ops->snesfunction)(snes,U,F,ts));
4356   PetscFunctionReturn(0);
4357 }
4358 
4359 /*@
4360    SNESTSFormJacobian - Function to evaluate the Jacobian
4361 
4362    Collective on SNES
4363 
4364    Input Parameters:
4365 + snes - nonlinear solver
4366 . U - the current state at which to evaluate the residual
4367 - ctx - user context, must be a TS
4368 
4369    Output Parameters:
4370 + A - the Jacobian
4371 - B - the preconditioning matrix (may be the same as A)
4372 
4373    Notes:
4374    This function is not normally called by users and is automatically registered with the SNES used by TS.
4375 
4376    Level: developer
4377 
4378 .seealso: `SNESSetJacobian()`
4379 @*/
4380 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
4381 {
4382   TS             ts = (TS)ctx;
4383 
4384   PetscFunctionBegin;
4385   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4386   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4387   PetscValidPointer(A,3);
4388   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
4389   PetscValidPointer(B,4);
4390   PetscValidHeaderSpecific(B,MAT_CLASSID,4);
4391   PetscValidHeaderSpecific(ts,TS_CLASSID,5);
4392   PetscCall((ts->ops->snesjacobian)(snes,U,A,B,ts));
4393   PetscFunctionReturn(0);
4394 }
4395 
4396 /*@C
4397    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only
4398 
4399    Collective on TS
4400 
4401    Input Parameters:
4402 +  ts - time stepping context
4403 .  t - time at which to evaluate
4404 .  U - state at which to evaluate
4405 -  ctx - context
4406 
4407    Output Parameter:
4408 .  F - right hand side
4409 
4410    Level: intermediate
4411 
4412    Notes:
4413    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
4414    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
4415 
4416 .seealso: `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSJacobianConstant()`
4417 @*/
4418 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
4419 {
4420   Mat            Arhs,Brhs;
4421 
4422   PetscFunctionBegin;
4423   PetscCall(TSGetRHSMats_Private(ts,&Arhs,&Brhs));
4424   /* undo the damage caused by shifting */
4425   PetscCall(TSRecoverRHSJacobian(ts,Arhs,Brhs));
4426   PetscCall(TSComputeRHSJacobian(ts,t,U,Arhs,Brhs));
4427   PetscCall(MatMult(Arhs,U,F));
4428   PetscFunctionReturn(0);
4429 }
4430 
4431 /*@C
4432    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
4433 
4434    Collective on TS
4435 
4436    Input Parameters:
4437 +  ts - time stepping context
4438 .  t - time at which to evaluate
4439 .  U - state at which to evaluate
4440 -  ctx - context
4441 
4442    Output Parameters:
4443 +  A - pointer to operator
4444 -  B - pointer to preconditioning matrix
4445 
4446    Level: intermediate
4447 
4448    Notes:
4449    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
4450 
4451 .seealso: `TSSetRHSFunction()`, `TSSetRHSJacobian()`, `TSComputeRHSFunctionLinear()`
4452 @*/
4453 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
4454 {
4455   PetscFunctionBegin;
4456   PetscFunctionReturn(0);
4457 }
4458 
4459 /*@C
4460    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
4461 
4462    Collective on TS
4463 
4464    Input Parameters:
4465 +  ts - time stepping context
4466 .  t - time at which to evaluate
4467 .  U - state at which to evaluate
4468 .  Udot - time derivative of state vector
4469 -  ctx - context
4470 
4471    Output Parameter:
4472 .  F - left hand side
4473 
4474    Level: intermediate
4475 
4476    Notes:
4477    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
4478    user is required to write their own TSComputeIFunction.
4479    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
4480    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
4481 
4482    Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U
4483 
4484 .seealso: `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIJacobianConstant()`, `TSComputeRHSFunctionLinear()`
4485 @*/
4486 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
4487 {
4488   Mat            A,B;
4489 
4490   PetscFunctionBegin;
4491   PetscCall(TSGetIJacobian(ts,&A,&B,NULL,NULL));
4492   PetscCall(TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE));
4493   PetscCall(MatMult(A,Udot,F));
4494   PetscFunctionReturn(0);
4495 }
4496 
4497 /*@C
4498    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
4499 
4500    Collective on TS
4501 
4502    Input Parameters:
4503 +  ts - time stepping context
4504 .  t - time at which to evaluate
4505 .  U - state at which to evaluate
4506 .  Udot - time derivative of state vector
4507 .  shift - shift to apply
4508 -  ctx - context
4509 
4510    Output Parameters:
4511 +  A - pointer to operator
4512 -  B - pointer to preconditioning matrix
4513 
4514    Level: advanced
4515 
4516    Notes:
4517    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
4518 
4519    It is only appropriate for problems of the form
4520 
4521 $     M Udot = F(U,t)
4522 
4523   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
4524   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
4525   an implicit operator of the form
4526 
4527 $    shift*M + J
4528 
4529   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
4530   a copy of M or reassemble it when requested.
4531 
4532 .seealso: `TSSetIFunction()`, `TSSetIJacobian()`, `TSComputeIFunctionLinear()`
4533 @*/
4534 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
4535 {
4536   PetscFunctionBegin;
4537   PetscCall(MatScale(A, shift / ts->ijacobian.shift));
4538   ts->ijacobian.shift = shift;
4539   PetscFunctionReturn(0);
4540 }
4541 
4542 /*@
4543    TSGetEquationType - Gets the type of the equation that TS is solving.
4544 
4545    Not Collective
4546 
4547    Input Parameter:
4548 .  ts - the TS context
4549 
4550    Output Parameter:
4551 .  equation_type - see TSEquationType
4552 
4553    Level: beginner
4554 
4555 .seealso: `TSSetEquationType()`, `TSEquationType`
4556 @*/
4557 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
4558 {
4559   PetscFunctionBegin;
4560   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4561   PetscValidPointer(equation_type,2);
4562   *equation_type = ts->equation_type;
4563   PetscFunctionReturn(0);
4564 }
4565 
4566 /*@
4567    TSSetEquationType - Sets the type of the equation that TS is solving.
4568 
4569    Not Collective
4570 
4571    Input Parameters:
4572 +  ts - the TS context
4573 -  equation_type - see TSEquationType
4574 
4575    Level: advanced
4576 
4577 .seealso: `TSGetEquationType()`, `TSEquationType`
4578 @*/
4579 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
4580 {
4581   PetscFunctionBegin;
4582   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4583   ts->equation_type = equation_type;
4584   PetscFunctionReturn(0);
4585 }
4586 
4587 /*@
4588    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
4589 
4590    Not Collective
4591 
4592    Input Parameter:
4593 .  ts - the TS context
4594 
4595    Output Parameter:
4596 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4597             manual pages for the individual convergence tests for complete lists
4598 
4599    Level: beginner
4600 
4601    Notes:
4602    Can only be called after the call to TSSolve() is complete.
4603 
4604 .seealso: `TSSetConvergenceTest()`, `TSConvergedReason`
4605 @*/
4606 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
4607 {
4608   PetscFunctionBegin;
4609   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4610   PetscValidPointer(reason,2);
4611   *reason = ts->reason;
4612   PetscFunctionReturn(0);
4613 }
4614 
4615 /*@
4616    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
4617 
4618    Logically Collective; reason must contain common value
4619 
4620    Input Parameters:
4621 +  ts - the TS context
4622 -  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4623             manual pages for the individual convergence tests for complete lists
4624 
4625    Level: advanced
4626 
4627    Notes:
4628    Can only be called while TSSolve() is active.
4629 
4630 .seealso: `TSConvergedReason`
4631 @*/
4632 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
4633 {
4634   PetscFunctionBegin;
4635   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4636   ts->reason = reason;
4637   PetscFunctionReturn(0);
4638 }
4639 
4640 /*@
4641    TSGetSolveTime - Gets the time after a call to TSSolve()
4642 
4643    Not Collective
4644 
4645    Input Parameter:
4646 .  ts - the TS context
4647 
4648    Output Parameter:
4649 .  ftime - the final time. This time corresponds to the final time set with TSSetMaxTime()
4650 
4651    Level: beginner
4652 
4653    Notes:
4654    Can only be called after the call to TSSolve() is complete.
4655 
4656 .seealso: `TSSetConvergenceTest()`, `TSConvergedReason`
4657 @*/
4658 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
4659 {
4660   PetscFunctionBegin;
4661   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4662   PetscValidRealPointer(ftime,2);
4663   *ftime = ts->solvetime;
4664   PetscFunctionReturn(0);
4665 }
4666 
4667 /*@
4668    TSGetSNESIterations - Gets the total number of nonlinear iterations
4669    used by the time integrator.
4670 
4671    Not Collective
4672 
4673    Input Parameter:
4674 .  ts - TS context
4675 
4676    Output Parameter:
4677 .  nits - number of nonlinear iterations
4678 
4679    Notes:
4680    This counter is reset to zero for each successive call to TSSolve().
4681 
4682    Level: intermediate
4683 
4684 .seealso: `TSGetKSPIterations()`
4685 @*/
4686 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
4687 {
4688   PetscFunctionBegin;
4689   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4690   PetscValidIntPointer(nits,2);
4691   *nits = ts->snes_its;
4692   PetscFunctionReturn(0);
4693 }
4694 
4695 /*@
4696    TSGetKSPIterations - Gets the total number of linear iterations
4697    used by the time integrator.
4698 
4699    Not Collective
4700 
4701    Input Parameter:
4702 .  ts - TS context
4703 
4704    Output Parameter:
4705 .  lits - number of linear iterations
4706 
4707    Notes:
4708    This counter is reset to zero for each successive call to TSSolve().
4709 
4710    Level: intermediate
4711 
4712 .seealso: `TSGetSNESIterations()`, `SNESGetKSPIterations()`
4713 @*/
4714 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
4715 {
4716   PetscFunctionBegin;
4717   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4718   PetscValidIntPointer(lits,2);
4719   *lits = ts->ksp_its;
4720   PetscFunctionReturn(0);
4721 }
4722 
4723 /*@
4724    TSGetStepRejections - Gets the total number of rejected steps.
4725 
4726    Not Collective
4727 
4728    Input Parameter:
4729 .  ts - TS context
4730 
4731    Output Parameter:
4732 .  rejects - number of steps rejected
4733 
4734    Notes:
4735    This counter is reset to zero for each successive call to TSSolve().
4736 
4737    Level: intermediate
4738 
4739 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetSNESFailures()`, `TSSetMaxSNESFailures()`, `TSSetErrorIfStepFails()`
4740 @*/
4741 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
4742 {
4743   PetscFunctionBegin;
4744   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4745   PetscValidIntPointer(rejects,2);
4746   *rejects = ts->reject;
4747   PetscFunctionReturn(0);
4748 }
4749 
4750 /*@
4751    TSGetSNESFailures - Gets the total number of failed SNES solves
4752 
4753    Not Collective
4754 
4755    Input Parameter:
4756 .  ts - TS context
4757 
4758    Output Parameter:
4759 .  fails - number of failed nonlinear solves
4760 
4761    Notes:
4762    This counter is reset to zero for each successive call to TSSolve().
4763 
4764    Level: intermediate
4765 
4766 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSSetMaxSNESFailures()`
4767 @*/
4768 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
4769 {
4770   PetscFunctionBegin;
4771   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4772   PetscValidIntPointer(fails,2);
4773   *fails = ts->num_snes_failures;
4774   PetscFunctionReturn(0);
4775 }
4776 
4777 /*@
4778    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
4779 
4780    Not Collective
4781 
4782    Input Parameters:
4783 +  ts - TS context
4784 -  rejects - maximum number of rejected steps, pass -1 for unlimited
4785 
4786    Notes:
4787    The counter is reset to zero for each step
4788 
4789    Options Database Key:
4790 .  -ts_max_reject - Maximum number of step rejections before a step fails
4791 
4792    Level: intermediate
4793 
4794 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxSNESFailures()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()`
4795 @*/
4796 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
4797 {
4798   PetscFunctionBegin;
4799   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4800   ts->max_reject = rejects;
4801   PetscFunctionReturn(0);
4802 }
4803 
4804 /*@
4805    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
4806 
4807    Not Collective
4808 
4809    Input Parameters:
4810 +  ts - TS context
4811 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
4812 
4813    Notes:
4814    The counter is reset to zero for each successive call to TSSolve().
4815 
4816    Options Database Key:
4817 .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
4818 
4819    Level: intermediate
4820 
4821 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `SNESGetConvergedReason()`, `TSGetConvergedReason()`
4822 @*/
4823 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
4824 {
4825   PetscFunctionBegin;
4826   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4827   ts->max_snes_failures = fails;
4828   PetscFunctionReturn(0);
4829 }
4830 
4831 /*@
4832    TSSetErrorIfStepFails - Error if no step succeeds
4833 
4834    Not Collective
4835 
4836    Input Parameters:
4837 +  ts - TS context
4838 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
4839 
4840    Options Database Key:
4841 .  -ts_error_if_step_fails - Error if no step succeeds
4842 
4843    Level: intermediate
4844 
4845 .seealso: `TSGetSNESIterations()`, `TSGetKSPIterations()`, `TSSetMaxStepRejections()`, `TSGetStepRejections()`, `TSGetSNESFailures()`, `TSSetErrorIfStepFails()`, `TSGetConvergedReason()`
4846 @*/
4847 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
4848 {
4849   PetscFunctionBegin;
4850   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4851   ts->errorifstepfailed = err;
4852   PetscFunctionReturn(0);
4853 }
4854 
4855 /*@
4856    TSGetAdapt - Get the adaptive controller context for the current method
4857 
4858    Collective on TS if controller has not been created yet
4859 
4860    Input Parameter:
4861 .  ts - time stepping context
4862 
4863    Output Parameter:
4864 .  adapt - adaptive controller
4865 
4866    Level: intermediate
4867 
4868 .seealso: `TSAdapt`, `TSAdaptSetType()`, `TSAdaptChoose()`
4869 @*/
4870 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
4871 {
4872   PetscFunctionBegin;
4873   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4874   PetscValidPointer(adapt,2);
4875   if (!ts->adapt) {
4876     PetscCall(TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt));
4877     PetscCall(PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt));
4878     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1));
4879   }
4880   *adapt = ts->adapt;
4881   PetscFunctionReturn(0);
4882 }
4883 
4884 /*@
4885    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
4886 
4887    Logically Collective
4888 
4889    Input Parameters:
4890 +  ts - time integration context
4891 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
4892 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
4893 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
4894 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
4895 
4896    Options Database keys:
4897 +  -ts_rtol <rtol> - relative tolerance for local truncation error
4898 -  -ts_atol <atol> - Absolute tolerance for local truncation error
4899 
4900    Notes:
4901    With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
4902    (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
4903    computed only for the differential or the algebraic part then this can be done using the vector of
4904    tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
4905    differential part and infinity for the algebraic part, the LTE calculation will include only the
4906    differential variables.
4907 
4908    Level: beginner
4909 
4910 .seealso: `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSGetTolerances()`
4911 @*/
4912 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
4913 {
4914   PetscFunctionBegin;
4915   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
4916   if (vatol) {
4917     PetscCall(PetscObjectReference((PetscObject)vatol));
4918     PetscCall(VecDestroy(&ts->vatol));
4919     ts->vatol = vatol;
4920   }
4921   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
4922   if (vrtol) {
4923     PetscCall(PetscObjectReference((PetscObject)vrtol));
4924     PetscCall(VecDestroy(&ts->vrtol));
4925     ts->vrtol = vrtol;
4926   }
4927   PetscFunctionReturn(0);
4928 }
4929 
4930 /*@
4931    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
4932 
4933    Logically Collective
4934 
4935    Input Parameter:
4936 .  ts - time integration context
4937 
4938    Output Parameters:
4939 +  atol - scalar absolute tolerances, NULL to ignore
4940 .  vatol - vector of absolute tolerances, NULL to ignore
4941 .  rtol - scalar relative tolerances, NULL to ignore
4942 -  vrtol - vector of relative tolerances, NULL to ignore
4943 
4944    Level: beginner
4945 
4946 .seealso: `TS`, `TSAdapt`, `TSErrorWeightedNorm()`, `TSSetTolerances()`
4947 @*/
4948 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
4949 {
4950   PetscFunctionBegin;
4951   if (atol)  *atol  = ts->atol;
4952   if (vatol) *vatol = ts->vatol;
4953   if (rtol)  *rtol  = ts->rtol;
4954   if (vrtol) *vrtol = ts->vrtol;
4955   PetscFunctionReturn(0);
4956 }
4957 
4958 /*@
4959    TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors
4960 
4961    Collective on TS
4962 
4963    Input Parameters:
4964 +  ts - time stepping context
4965 .  U - state vector, usually ts->vec_sol
4966 -  Y - state vector to be compared to U
4967 
4968    Output Parameters:
4969 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
4970 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
4971 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
4972 
4973    Level: developer
4974 
4975 .seealso: `TSErrorWeightedNorm()`, `TSErrorWeightedNormInfinity()`
4976 @*/
4977 PetscErrorCode TSErrorWeightedNorm2(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
4978 {
4979   PetscInt          i,n,N,rstart;
4980   PetscInt          n_loc,na_loc,nr_loc;
4981   PetscReal         n_glb,na_glb,nr_glb;
4982   const PetscScalar *u,*y;
4983   PetscReal         sum,suma,sumr,gsum,gsuma,gsumr,diff;
4984   PetscReal         tol,tola,tolr;
4985   PetscReal         err_loc[6],err_glb[6];
4986 
4987   PetscFunctionBegin;
4988   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4989   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4990   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
4991   PetscValidType(U,2);
4992   PetscValidType(Y,3);
4993   PetscCheckSameComm(U,2,Y,3);
4994   PetscValidRealPointer(norm,4);
4995   PetscValidRealPointer(norma,5);
4996   PetscValidRealPointer(normr,6);
4997   PetscCheck(U != Y,PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
4998 
4999   PetscCall(VecGetSize(U,&N));
5000   PetscCall(VecGetLocalSize(U,&n));
5001   PetscCall(VecGetOwnershipRange(U,&rstart,NULL));
5002   PetscCall(VecGetArrayRead(U,&u));
5003   PetscCall(VecGetArrayRead(Y,&y));
5004   sum  = 0.; n_loc  = 0;
5005   suma = 0.; na_loc = 0;
5006   sumr = 0.; nr_loc = 0;
5007   if (ts->vatol && ts->vrtol) {
5008     const PetscScalar *atol,*rtol;
5009     PetscCall(VecGetArrayRead(ts->vatol,&atol));
5010     PetscCall(VecGetArrayRead(ts->vrtol,&rtol));
5011     for (i=0; i<n; i++) {
5012       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5013       diff = PetscAbsScalar(y[i] - u[i]);
5014       tola = PetscRealPart(atol[i]);
5015       if (tola>0.) {
5016         suma  += PetscSqr(diff/tola);
5017         na_loc++;
5018       }
5019       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5020       if (tolr>0.) {
5021         sumr  += PetscSqr(diff/tolr);
5022         nr_loc++;
5023       }
5024       tol=tola+tolr;
5025       if (tol>0.) {
5026         sum  += PetscSqr(diff/tol);
5027         n_loc++;
5028       }
5029     }
5030     PetscCall(VecRestoreArrayRead(ts->vatol,&atol));
5031     PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol));
5032   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5033     const PetscScalar *atol;
5034     PetscCall(VecGetArrayRead(ts->vatol,&atol));
5035     for (i=0; i<n; i++) {
5036       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5037       diff = PetscAbsScalar(y[i] - u[i]);
5038       tola = PetscRealPart(atol[i]);
5039       if (tola>0.) {
5040         suma  += PetscSqr(diff/tola);
5041         na_loc++;
5042       }
5043       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5044       if (tolr>0.) {
5045         sumr  += PetscSqr(diff/tolr);
5046         nr_loc++;
5047       }
5048       tol=tola+tolr;
5049       if (tol>0.) {
5050         sum  += PetscSqr(diff/tol);
5051         n_loc++;
5052       }
5053     }
5054     PetscCall(VecRestoreArrayRead(ts->vatol,&atol));
5055   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5056     const PetscScalar *rtol;
5057     PetscCall(VecGetArrayRead(ts->vrtol,&rtol));
5058     for (i=0; i<n; i++) {
5059       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5060       diff = PetscAbsScalar(y[i] - u[i]);
5061       tola = ts->atol;
5062       if (tola>0.) {
5063         suma  += PetscSqr(diff/tola);
5064         na_loc++;
5065       }
5066       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5067       if (tolr>0.) {
5068         sumr  += PetscSqr(diff/tolr);
5069         nr_loc++;
5070       }
5071       tol=tola+tolr;
5072       if (tol>0.) {
5073         sum  += PetscSqr(diff/tol);
5074         n_loc++;
5075       }
5076     }
5077     PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol));
5078   } else {                      /* scalar atol, scalar rtol */
5079     for (i=0; i<n; i++) {
5080       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5081       diff = PetscAbsScalar(y[i] - u[i]);
5082       tola = ts->atol;
5083       if (tola>0.) {
5084         suma  += PetscSqr(diff/tola);
5085         na_loc++;
5086       }
5087       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5088       if (tolr>0.) {
5089         sumr  += PetscSqr(diff/tolr);
5090         nr_loc++;
5091       }
5092       tol=tola+tolr;
5093       if (tol>0.) {
5094         sum  += PetscSqr(diff/tol);
5095         n_loc++;
5096       }
5097     }
5098   }
5099   PetscCall(VecRestoreArrayRead(U,&u));
5100   PetscCall(VecRestoreArrayRead(Y,&y));
5101 
5102   err_loc[0] = sum;
5103   err_loc[1] = suma;
5104   err_loc[2] = sumr;
5105   err_loc[3] = (PetscReal)n_loc;
5106   err_loc[4] = (PetscReal)na_loc;
5107   err_loc[5] = (PetscReal)nr_loc;
5108 
5109   PetscCall(MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts)));
5110 
5111   gsum   = err_glb[0];
5112   gsuma  = err_glb[1];
5113   gsumr  = err_glb[2];
5114   n_glb  = err_glb[3];
5115   na_glb = err_glb[4];
5116   nr_glb = err_glb[5];
5117 
5118   *norm  = 0.;
5119   if (n_glb>0.) {*norm  = PetscSqrtReal(gsum  / n_glb);}
5120   *norma = 0.;
5121   if (na_glb>0.) {*norma = PetscSqrtReal(gsuma / na_glb);}
5122   *normr = 0.;
5123   if (nr_glb>0.) {*normr = PetscSqrtReal(gsumr / nr_glb);}
5124 
5125   PetscCheck(!PetscIsInfOrNanScalar(*norm),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5126   PetscCheck(!PetscIsInfOrNanScalar(*norma),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5127   PetscCheck(!PetscIsInfOrNanScalar(*normr),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5128   PetscFunctionReturn(0);
5129 }
5130 
5131 /*@
5132    TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors
5133 
5134    Collective on TS
5135 
5136    Input Parameters:
5137 +  ts - time stepping context
5138 .  U - state vector, usually ts->vec_sol
5139 -  Y - state vector to be compared to U
5140 
5141    Output Parameters:
5142 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5143 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5144 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5145 
5146    Level: developer
5147 
5148 .seealso: `TSErrorWeightedNorm()`, `TSErrorWeightedNorm2()`
5149 @*/
5150 PetscErrorCode TSErrorWeightedNormInfinity(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5151 {
5152   PetscInt          i,n,N,rstart;
5153   const PetscScalar *u,*y;
5154   PetscReal         max,gmax,maxa,gmaxa,maxr,gmaxr;
5155   PetscReal         tol,tola,tolr,diff;
5156   PetscReal         err_loc[3],err_glb[3];
5157 
5158   PetscFunctionBegin;
5159   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5160   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5161   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
5162   PetscValidType(U,2);
5163   PetscValidType(Y,3);
5164   PetscCheckSameComm(U,2,Y,3);
5165   PetscValidRealPointer(norm,4);
5166   PetscValidRealPointer(norma,5);
5167   PetscValidRealPointer(normr,6);
5168   PetscCheck(U != Y,PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
5169 
5170   PetscCall(VecGetSize(U,&N));
5171   PetscCall(VecGetLocalSize(U,&n));
5172   PetscCall(VecGetOwnershipRange(U,&rstart,NULL));
5173   PetscCall(VecGetArrayRead(U,&u));
5174   PetscCall(VecGetArrayRead(Y,&y));
5175 
5176   max=0.;
5177   maxa=0.;
5178   maxr=0.;
5179 
5180   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
5181     const PetscScalar *atol,*rtol;
5182     PetscCall(VecGetArrayRead(ts->vatol,&atol));
5183     PetscCall(VecGetArrayRead(ts->vrtol,&rtol));
5184 
5185     for (i=0; i<n; i++) {
5186       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5187       diff = PetscAbsScalar(y[i] - u[i]);
5188       tola = PetscRealPart(atol[i]);
5189       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5190       tol  = tola+tolr;
5191       if (tola>0.) {
5192         maxa = PetscMax(maxa,diff / tola);
5193       }
5194       if (tolr>0.) {
5195         maxr = PetscMax(maxr,diff / tolr);
5196       }
5197       if (tol>0.) {
5198         max = PetscMax(max,diff / tol);
5199       }
5200     }
5201     PetscCall(VecRestoreArrayRead(ts->vatol,&atol));
5202     PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol));
5203   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5204     const PetscScalar *atol;
5205     PetscCall(VecGetArrayRead(ts->vatol,&atol));
5206     for (i=0; i<n; i++) {
5207       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5208       diff = PetscAbsScalar(y[i] - u[i]);
5209       tola = PetscRealPart(atol[i]);
5210       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5211       tol  = tola+tolr;
5212       if (tola>0.) {
5213         maxa = PetscMax(maxa,diff / tola);
5214       }
5215       if (tolr>0.) {
5216         maxr = PetscMax(maxr,diff / tolr);
5217       }
5218       if (tol>0.) {
5219         max = PetscMax(max,diff / tol);
5220       }
5221     }
5222     PetscCall(VecRestoreArrayRead(ts->vatol,&atol));
5223   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5224     const PetscScalar *rtol;
5225     PetscCall(VecGetArrayRead(ts->vrtol,&rtol));
5226 
5227     for (i=0; i<n; i++) {
5228       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5229       diff = PetscAbsScalar(y[i] - u[i]);
5230       tola = ts->atol;
5231       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5232       tol  = tola+tolr;
5233       if (tola>0.) {
5234         maxa = PetscMax(maxa,diff / tola);
5235       }
5236       if (tolr>0.) {
5237         maxr = PetscMax(maxr,diff / tolr);
5238       }
5239       if (tol>0.) {
5240         max = PetscMax(max,diff / tol);
5241       }
5242     }
5243     PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol));
5244   } else {                      /* scalar atol, scalar rtol */
5245 
5246     for (i=0; i<n; i++) {
5247       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5248       diff = PetscAbsScalar(y[i] - u[i]);
5249       tola = ts->atol;
5250       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5251       tol  = tola+tolr;
5252       if (tola>0.) {
5253         maxa = PetscMax(maxa,diff / tola);
5254       }
5255       if (tolr>0.) {
5256         maxr = PetscMax(maxr,diff / tolr);
5257       }
5258       if (tol>0.) {
5259         max = PetscMax(max,diff / tol);
5260       }
5261     }
5262   }
5263   PetscCall(VecRestoreArrayRead(U,&u));
5264   PetscCall(VecRestoreArrayRead(Y,&y));
5265   err_loc[0] = max;
5266   err_loc[1] = maxa;
5267   err_loc[2] = maxr;
5268   PetscCall(MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts)));
5269   gmax   = err_glb[0];
5270   gmaxa  = err_glb[1];
5271   gmaxr  = err_glb[2];
5272 
5273   *norm = gmax;
5274   *norma = gmaxa;
5275   *normr = gmaxr;
5276   PetscCheck(!PetscIsInfOrNanScalar(*norm),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5277   PetscCheck(!PetscIsInfOrNanScalar(*norma),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5278   PetscCheck(!PetscIsInfOrNanScalar(*normr),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5279   PetscFunctionReturn(0);
5280 }
5281 
5282 /*@
5283    TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
5284 
5285    Collective on TS
5286 
5287    Input Parameters:
5288 +  ts - time stepping context
5289 .  U - state vector, usually ts->vec_sol
5290 .  Y - state vector to be compared to U
5291 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
5292 
5293    Output Parameters:
5294 +  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5295 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5296 -  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5297 
5298    Options Database Keys:
5299 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5300 
5301    Level: developer
5302 
5303 .seealso: `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()`, `TSErrorWeightedENorm`
5304 @*/
5305 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5306 {
5307   PetscFunctionBegin;
5308   if (wnormtype == NORM_2) {
5309     PetscCall(TSErrorWeightedNorm2(ts,U,Y,norm,norma,normr));
5310   } else if (wnormtype == NORM_INFINITY) {
5311     PetscCall(TSErrorWeightedNormInfinity(ts,U,Y,norm,norma,normr));
5312   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
5313   PetscFunctionReturn(0);
5314 }
5315 
5316 /*@
5317    TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances
5318 
5319    Collective on TS
5320 
5321    Input Parameters:
5322 +  ts - time stepping context
5323 .  E - error vector
5324 .  U - state vector, usually ts->vec_sol
5325 -  Y - state vector, previous time step
5326 
5327    Output Parameters:
5328 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5329 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5330 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5331 
5332    Level: developer
5333 
5334 .seealso: `TSErrorWeightedENorm()`, `TSErrorWeightedENormInfinity()`
5335 @*/
5336 PetscErrorCode TSErrorWeightedENorm2(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5337 {
5338   PetscInt          i,n,N,rstart;
5339   PetscInt          n_loc,na_loc,nr_loc;
5340   PetscReal         n_glb,na_glb,nr_glb;
5341   const PetscScalar *e,*u,*y;
5342   PetscReal         err,sum,suma,sumr,gsum,gsuma,gsumr;
5343   PetscReal         tol,tola,tolr;
5344   PetscReal         err_loc[6],err_glb[6];
5345 
5346   PetscFunctionBegin;
5347   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5348   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
5349   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
5350   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
5351   PetscValidType(E,2);
5352   PetscValidType(U,3);
5353   PetscValidType(Y,4);
5354   PetscCheckSameComm(E,2,U,3);
5355   PetscCheckSameComm(U,3,Y,4);
5356   PetscValidRealPointer(norm,5);
5357   PetscValidRealPointer(norma,6);
5358   PetscValidRealPointer(normr,7);
5359 
5360   PetscCall(VecGetSize(E,&N));
5361   PetscCall(VecGetLocalSize(E,&n));
5362   PetscCall(VecGetOwnershipRange(E,&rstart,NULL));
5363   PetscCall(VecGetArrayRead(E,&e));
5364   PetscCall(VecGetArrayRead(U,&u));
5365   PetscCall(VecGetArrayRead(Y,&y));
5366   sum  = 0.; n_loc  = 0;
5367   suma = 0.; na_loc = 0;
5368   sumr = 0.; nr_loc = 0;
5369   if (ts->vatol && ts->vrtol) {
5370     const PetscScalar *atol,*rtol;
5371     PetscCall(VecGetArrayRead(ts->vatol,&atol));
5372     PetscCall(VecGetArrayRead(ts->vrtol,&rtol));
5373     for (i=0; i<n; i++) {
5374       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5375       err = PetscAbsScalar(e[i]);
5376       tola = PetscRealPart(atol[i]);
5377       if (tola>0.) {
5378         suma  += PetscSqr(err/tola);
5379         na_loc++;
5380       }
5381       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5382       if (tolr>0.) {
5383         sumr  += PetscSqr(err/tolr);
5384         nr_loc++;
5385       }
5386       tol=tola+tolr;
5387       if (tol>0.) {
5388         sum  += PetscSqr(err/tol);
5389         n_loc++;
5390       }
5391     }
5392     PetscCall(VecRestoreArrayRead(ts->vatol,&atol));
5393     PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol));
5394   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5395     const PetscScalar *atol;
5396     PetscCall(VecGetArrayRead(ts->vatol,&atol));
5397     for (i=0; i<n; i++) {
5398       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5399       err = PetscAbsScalar(e[i]);
5400       tola = PetscRealPart(atol[i]);
5401       if (tola>0.) {
5402         suma  += PetscSqr(err/tola);
5403         na_loc++;
5404       }
5405       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5406       if (tolr>0.) {
5407         sumr  += PetscSqr(err/tolr);
5408         nr_loc++;
5409       }
5410       tol=tola+tolr;
5411       if (tol>0.) {
5412         sum  += PetscSqr(err/tol);
5413         n_loc++;
5414       }
5415     }
5416     PetscCall(VecRestoreArrayRead(ts->vatol,&atol));
5417   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5418     const PetscScalar *rtol;
5419     PetscCall(VecGetArrayRead(ts->vrtol,&rtol));
5420     for (i=0; i<n; i++) {
5421       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5422       err = PetscAbsScalar(e[i]);
5423       tola = ts->atol;
5424       if (tola>0.) {
5425         suma  += PetscSqr(err/tola);
5426         na_loc++;
5427       }
5428       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5429       if (tolr>0.) {
5430         sumr  += PetscSqr(err/tolr);
5431         nr_loc++;
5432       }
5433       tol=tola+tolr;
5434       if (tol>0.) {
5435         sum  += PetscSqr(err/tol);
5436         n_loc++;
5437       }
5438     }
5439     PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol));
5440   } else {                      /* scalar atol, scalar rtol */
5441     for (i=0; i<n; i++) {
5442       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5443       err = PetscAbsScalar(e[i]);
5444       tola = ts->atol;
5445       if (tola>0.) {
5446         suma  += PetscSqr(err/tola);
5447         na_loc++;
5448       }
5449       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5450       if (tolr>0.) {
5451         sumr  += PetscSqr(err/tolr);
5452         nr_loc++;
5453       }
5454       tol=tola+tolr;
5455       if (tol>0.) {
5456         sum  += PetscSqr(err/tol);
5457         n_loc++;
5458       }
5459     }
5460   }
5461   PetscCall(VecRestoreArrayRead(E,&e));
5462   PetscCall(VecRestoreArrayRead(U,&u));
5463   PetscCall(VecRestoreArrayRead(Y,&y));
5464 
5465   err_loc[0] = sum;
5466   err_loc[1] = suma;
5467   err_loc[2] = sumr;
5468   err_loc[3] = (PetscReal)n_loc;
5469   err_loc[4] = (PetscReal)na_loc;
5470   err_loc[5] = (PetscReal)nr_loc;
5471 
5472   PetscCall(MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts)));
5473 
5474   gsum   = err_glb[0];
5475   gsuma  = err_glb[1];
5476   gsumr  = err_glb[2];
5477   n_glb  = err_glb[3];
5478   na_glb = err_glb[4];
5479   nr_glb = err_glb[5];
5480 
5481   *norm  = 0.;
5482   if (n_glb>0.) {*norm  = PetscSqrtReal(gsum  / n_glb);}
5483   *norma = 0.;
5484   if (na_glb>0.) {*norma = PetscSqrtReal(gsuma / na_glb);}
5485   *normr = 0.;
5486   if (nr_glb>0.) {*normr = PetscSqrtReal(gsumr / nr_glb);}
5487 
5488   PetscCheck(!PetscIsInfOrNanScalar(*norm),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5489   PetscCheck(!PetscIsInfOrNanScalar(*norma),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5490   PetscCheck(!PetscIsInfOrNanScalar(*normr),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5491   PetscFunctionReturn(0);
5492 }
5493 
5494 /*@
5495    TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances
5496    Collective on TS
5497 
5498    Input Parameters:
5499 +  ts - time stepping context
5500 .  E - error vector
5501 .  U - state vector, usually ts->vec_sol
5502 -  Y - state vector, previous time step
5503 
5504    Output Parameters:
5505 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5506 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5507 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5508 
5509    Level: developer
5510 
5511 .seealso: `TSErrorWeightedENorm()`, `TSErrorWeightedENorm2()`
5512 @*/
5513 PetscErrorCode TSErrorWeightedENormInfinity(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5514 {
5515   PetscInt          i,n,N,rstart;
5516   const PetscScalar *e,*u,*y;
5517   PetscReal         err,max,gmax,maxa,gmaxa,maxr,gmaxr;
5518   PetscReal         tol,tola,tolr;
5519   PetscReal         err_loc[3],err_glb[3];
5520 
5521   PetscFunctionBegin;
5522   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5523   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
5524   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
5525   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
5526   PetscValidType(E,2);
5527   PetscValidType(U,3);
5528   PetscValidType(Y,4);
5529   PetscCheckSameComm(E,2,U,3);
5530   PetscCheckSameComm(U,3,Y,4);
5531   PetscValidRealPointer(norm,5);
5532   PetscValidRealPointer(norma,6);
5533   PetscValidRealPointer(normr,7);
5534 
5535   PetscCall(VecGetSize(E,&N));
5536   PetscCall(VecGetLocalSize(E,&n));
5537   PetscCall(VecGetOwnershipRange(E,&rstart,NULL));
5538   PetscCall(VecGetArrayRead(E,&e));
5539   PetscCall(VecGetArrayRead(U,&u));
5540   PetscCall(VecGetArrayRead(Y,&y));
5541 
5542   max=0.;
5543   maxa=0.;
5544   maxr=0.;
5545 
5546   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
5547     const PetscScalar *atol,*rtol;
5548     PetscCall(VecGetArrayRead(ts->vatol,&atol));
5549     PetscCall(VecGetArrayRead(ts->vrtol,&rtol));
5550 
5551     for (i=0; i<n; i++) {
5552       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5553       err = PetscAbsScalar(e[i]);
5554       tola = PetscRealPart(atol[i]);
5555       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5556       tol  = tola+tolr;
5557       if (tola>0.) {
5558         maxa = PetscMax(maxa,err / tola);
5559       }
5560       if (tolr>0.) {
5561         maxr = PetscMax(maxr,err / tolr);
5562       }
5563       if (tol>0.) {
5564         max = PetscMax(max,err / tol);
5565       }
5566     }
5567     PetscCall(VecRestoreArrayRead(ts->vatol,&atol));
5568     PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol));
5569   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5570     const PetscScalar *atol;
5571     PetscCall(VecGetArrayRead(ts->vatol,&atol));
5572     for (i=0; i<n; i++) {
5573       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5574       err = PetscAbsScalar(e[i]);
5575       tola = PetscRealPart(atol[i]);
5576       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5577       tol  = tola+tolr;
5578       if (tola>0.) {
5579         maxa = PetscMax(maxa,err / tola);
5580       }
5581       if (tolr>0.) {
5582         maxr = PetscMax(maxr,err / tolr);
5583       }
5584       if (tol>0.) {
5585         max = PetscMax(max,err / tol);
5586       }
5587     }
5588     PetscCall(VecRestoreArrayRead(ts->vatol,&atol));
5589   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5590     const PetscScalar *rtol;
5591     PetscCall(VecGetArrayRead(ts->vrtol,&rtol));
5592 
5593     for (i=0; i<n; i++) {
5594       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5595       err = PetscAbsScalar(e[i]);
5596       tola = ts->atol;
5597       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5598       tol  = tola+tolr;
5599       if (tola>0.) {
5600         maxa = PetscMax(maxa,err / tola);
5601       }
5602       if (tolr>0.) {
5603         maxr = PetscMax(maxr,err / tolr);
5604       }
5605       if (tol>0.) {
5606         max = PetscMax(max,err / tol);
5607       }
5608     }
5609     PetscCall(VecRestoreArrayRead(ts->vrtol,&rtol));
5610   } else {                      /* scalar atol, scalar rtol */
5611 
5612     for (i=0; i<n; i++) {
5613       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5614       err = PetscAbsScalar(e[i]);
5615       tola = ts->atol;
5616       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5617       tol  = tola+tolr;
5618       if (tola>0.) {
5619         maxa = PetscMax(maxa,err / tola);
5620       }
5621       if (tolr>0.) {
5622         maxr = PetscMax(maxr,err / tolr);
5623       }
5624       if (tol>0.) {
5625         max = PetscMax(max,err / tol);
5626       }
5627     }
5628   }
5629   PetscCall(VecRestoreArrayRead(E,&e));
5630   PetscCall(VecRestoreArrayRead(U,&u));
5631   PetscCall(VecRestoreArrayRead(Y,&y));
5632   err_loc[0] = max;
5633   err_loc[1] = maxa;
5634   err_loc[2] = maxr;
5635   PetscCall(MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts)));
5636   gmax   = err_glb[0];
5637   gmaxa  = err_glb[1];
5638   gmaxr  = err_glb[2];
5639 
5640   *norm = gmax;
5641   *norma = gmaxa;
5642   *normr = gmaxr;
5643   PetscCheck(!PetscIsInfOrNanScalar(*norm),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5644   PetscCheck(!PetscIsInfOrNanScalar(*norma),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5645   PetscCheck(!PetscIsInfOrNanScalar(*normr),PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5646   PetscFunctionReturn(0);
5647 }
5648 
5649 /*@
5650    TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
5651 
5652    Collective on TS
5653 
5654    Input Parameters:
5655 +  ts - time stepping context
5656 .  E - error vector
5657 .  U - state vector, usually ts->vec_sol
5658 .  Y - state vector, previous time step
5659 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
5660 
5661    Output Parameters:
5662 +  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5663 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5664 -  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5665 
5666    Options Database Keys:
5667 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5668 
5669    Level: developer
5670 
5671 .seealso: `TSErrorWeightedENormInfinity()`, `TSErrorWeightedENorm2()`, `TSErrorWeightedNormInfinity()`, `TSErrorWeightedNorm2()`
5672 @*/
5673 PetscErrorCode TSErrorWeightedENorm(TS ts,Vec E,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5674 {
5675   PetscFunctionBegin;
5676   if (wnormtype == NORM_2) {
5677     PetscCall(TSErrorWeightedENorm2(ts,E,U,Y,norm,norma,normr));
5678   } else if (wnormtype == NORM_INFINITY) {
5679     PetscCall(TSErrorWeightedENormInfinity(ts,E,U,Y,norm,norma,normr));
5680   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
5681   PetscFunctionReturn(0);
5682 }
5683 
5684 /*@
5685    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
5686 
5687    Logically Collective on TS
5688 
5689    Input Parameters:
5690 +  ts - time stepping context
5691 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
5692 
5693    Note:
5694    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
5695 
5696    Level: intermediate
5697 
5698 .seealso: `TSGetCFLTime()`, `TSADAPTCFL`
5699 @*/
5700 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
5701 {
5702   PetscFunctionBegin;
5703   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5704   ts->cfltime_local = cfltime;
5705   ts->cfltime       = -1.;
5706   PetscFunctionReturn(0);
5707 }
5708 
5709 /*@
5710    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
5711 
5712    Collective on TS
5713 
5714    Input Parameter:
5715 .  ts - time stepping context
5716 
5717    Output Parameter:
5718 .  cfltime - maximum stable time step for forward Euler
5719 
5720    Level: advanced
5721 
5722 .seealso: `TSSetCFLTimeLocal()`
5723 @*/
5724 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
5725 {
5726   PetscFunctionBegin;
5727   if (ts->cfltime < 0) {
5728     PetscCall(MPIU_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts)));
5729   }
5730   *cfltime = ts->cfltime;
5731   PetscFunctionReturn(0);
5732 }
5733 
5734 /*@
5735    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
5736 
5737    Input Parameters:
5738 +  ts   - the TS context.
5739 .  xl   - lower bound.
5740 -  xu   - upper bound.
5741 
5742    Notes:
5743    If this routine is not called then the lower and upper bounds are set to
5744    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
5745 
5746    Level: advanced
5747 
5748 @*/
5749 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
5750 {
5751   SNES           snes;
5752 
5753   PetscFunctionBegin;
5754   PetscCall(TSGetSNES(ts,&snes));
5755   PetscCall(SNESVISetVariableBounds(snes,xl,xu));
5756   PetscFunctionReturn(0);
5757 }
5758 
5759 /*@
5760    TSComputeLinearStability - computes the linear stability function at a point
5761 
5762    Collective on TS
5763 
5764    Input Parameters:
5765 +  ts - the TS context
5766 -  xr,xi - real and imaginary part of input arguments
5767 
5768    Output Parameters:
5769 .  yr,yi - real and imaginary part of function value
5770 
5771    Level: developer
5772 
5773 .seealso: `TSSetRHSFunction()`, `TSComputeIFunction()`
5774 @*/
5775 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
5776 {
5777   PetscFunctionBegin;
5778   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5779   PetscCheck(ts->ops->linearstability,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
5780   PetscCall((*ts->ops->linearstability)(ts,xr,xi,yr,yi));
5781   PetscFunctionReturn(0);
5782 }
5783 
5784 /*@
5785    TSRestartStep - Flags the solver to restart the next step
5786 
5787    Collective on TS
5788 
5789    Input Parameter:
5790 .  ts - the TS context obtained from TSCreate()
5791 
5792    Level: advanced
5793 
5794    Notes:
5795    Multistep methods like BDF or Runge-Kutta methods with FSAL property require restarting the solver in the event of
5796    discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
5797    vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
5798    the sake of correctness and maximum safety, users are expected to call TSRestart() whenever they introduce
5799    discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
5800    discontinuous source terms).
5801 
5802 .seealso: `TSSolve()`, `TSSetPreStep()`, `TSSetPostStep()`
5803 @*/
5804 PetscErrorCode TSRestartStep(TS ts)
5805 {
5806   PetscFunctionBegin;
5807   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5808   ts->steprestart = PETSC_TRUE;
5809   PetscFunctionReturn(0);
5810 }
5811 
5812 /*@
5813    TSRollBack - Rolls back one time step
5814 
5815    Collective on TS
5816 
5817    Input Parameter:
5818 .  ts - the TS context obtained from TSCreate()
5819 
5820    Level: advanced
5821 
5822 .seealso: `TSCreate()`, `TSSetUp()`, `TSDestroy()`, `TSSolve()`, `TSSetPreStep()`, `TSSetPreStage()`, `TSInterpolate()`
5823 @*/
5824 PetscErrorCode  TSRollBack(TS ts)
5825 {
5826   PetscFunctionBegin;
5827   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
5828   PetscCheck(!ts->steprollback,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"TSRollBack already called");
5829   PetscCheck(ts->ops->rollback,PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
5830   PetscCall((*ts->ops->rollback)(ts));
5831   ts->time_step = ts->ptime - ts->ptime_prev;
5832   ts->ptime = ts->ptime_prev;
5833   ts->ptime_prev = ts->ptime_prev_rollback;
5834   ts->steps--;
5835   ts->steprollback = PETSC_TRUE;
5836   PetscFunctionReturn(0);
5837 }
5838 
5839 /*@
5840    TSGetStages - Get the number of stages and stage values
5841 
5842    Input Parameter:
5843 .  ts - the TS context obtained from TSCreate()
5844 
5845    Output Parameters:
5846 +  ns - the number of stages
5847 -  Y - the current stage vectors
5848 
5849    Level: advanced
5850 
5851    Notes: Both ns and Y can be NULL.
5852 
5853 .seealso: `TSCreate()`
5854 @*/
5855 PetscErrorCode  TSGetStages(TS ts,PetscInt *ns,Vec **Y)
5856 {
5857   PetscFunctionBegin;
5858   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
5859   if (ns) PetscValidIntPointer(ns,2);
5860   if (Y) PetscValidPointer(Y,3);
5861   if (!ts->ops->getstages) {
5862     if (ns) *ns = 0;
5863     if (Y) *Y = NULL;
5864   } else {
5865     PetscCall((*ts->ops->getstages)(ts,ns,Y));
5866   }
5867   PetscFunctionReturn(0);
5868 }
5869 
5870 /*@C
5871   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
5872 
5873   Collective on SNES
5874 
5875   Input Parameters:
5876 + ts - the TS context
5877 . t - current timestep
5878 . U - state vector
5879 . Udot - time derivative of state vector
5880 . shift - shift to apply, see note below
5881 - ctx - an optional user context
5882 
5883   Output Parameters:
5884 + J - Jacobian matrix (not altered in this routine)
5885 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
5886 
5887   Level: intermediate
5888 
5889   Notes:
5890   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
5891 
5892   dF/dU + shift*dF/dUdot
5893 
5894   Most users should not need to explicitly call this routine, as it
5895   is used internally within the nonlinear solvers.
5896 
5897   This will first try to get the coloring from the DM.  If the DM type has no coloring
5898   routine, then it will try to get the coloring from the matrix.  This requires that the
5899   matrix have nonzero entries precomputed.
5900 
5901 .seealso: `TSSetIJacobian()`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`
5902 @*/
5903 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat J,Mat B,void *ctx)
5904 {
5905   SNES           snes;
5906   MatFDColoring  color;
5907   PetscBool      hascolor, matcolor = PETSC_FALSE;
5908 
5909   PetscFunctionBegin;
5910   PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options,((PetscObject) ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL));
5911   PetscCall(PetscObjectQuery((PetscObject) B, "TSMatFDColoring", (PetscObject *) &color));
5912   if (!color) {
5913     DM         dm;
5914     ISColoring iscoloring;
5915 
5916     PetscCall(TSGetDM(ts, &dm));
5917     PetscCall(DMHasColoring(dm, &hascolor));
5918     if (hascolor && !matcolor) {
5919       PetscCall(DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring));
5920       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5921       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts));
5922       PetscCall(MatFDColoringSetFromOptions(color));
5923       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5924       PetscCall(ISColoringDestroy(&iscoloring));
5925     } else {
5926       MatColoring mc;
5927 
5928       PetscCall(MatColoringCreate(B, &mc));
5929       PetscCall(MatColoringSetDistance(mc, 2));
5930       PetscCall(MatColoringSetType(mc, MATCOLORINGSL));
5931       PetscCall(MatColoringSetFromOptions(mc));
5932       PetscCall(MatColoringApply(mc, &iscoloring));
5933       PetscCall(MatColoringDestroy(&mc));
5934       PetscCall(MatFDColoringCreate(B, iscoloring, &color));
5935       PetscCall(MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts));
5936       PetscCall(MatFDColoringSetFromOptions(color));
5937       PetscCall(MatFDColoringSetUp(B, iscoloring, color));
5938       PetscCall(ISColoringDestroy(&iscoloring));
5939     }
5940     PetscCall(PetscObjectCompose((PetscObject) B, "TSMatFDColoring", (PetscObject) color));
5941     PetscCall(PetscObjectDereference((PetscObject) color));
5942   }
5943   PetscCall(TSGetSNES(ts, &snes));
5944   PetscCall(MatFDColoringApply(B, color, U, snes));
5945   if (J != B) {
5946     PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
5947     PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
5948   }
5949   PetscFunctionReturn(0);
5950 }
5951 
5952 /*@
5953     TSSetFunctionDomainError - Set a function that tests if the current state vector is valid
5954 
5955     Input Parameters:
5956 +    ts - the TS context
5957 -    func - function called within TSFunctionDomainError
5958 
5959     Calling sequence of func:
5960 $     PetscErrorCode func(TS ts,PetscReal time,Vec state,PetscBool reject)
5961 
5962 +   ts - the TS context
5963 .   time - the current time (of the stage)
5964 .   state - the state to check if it is valid
5965 -   reject - (output parameter) PETSC_FALSE if the state is acceptable, PETSC_TRUE if not acceptable
5966 
5967     Level: intermediate
5968 
5969     Notes:
5970       If an implicit ODE solver is being used then, in addition to providing this routine, the
5971       user's code should call SNESSetFunctionDomainError() when domain errors occur during
5972       function evaluations where the functions are provided by TSSetIFunction() or TSSetRHSFunction().
5973       Use TSGetSNES() to obtain the SNES object
5974 
5975     Developer Notes:
5976       The naming of this function is inconsistent with the SNESSetFunctionDomainError()
5977       since one takes a function pointer and the other does not.
5978 
5979 .seealso: `TSAdaptCheckStage()`, `TSFunctionDomainError()`, `SNESSetFunctionDomainError()`, `TSGetSNES()`
5980 @*/
5981 
5982 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS,PetscReal,Vec,PetscBool*))
5983 {
5984   PetscFunctionBegin;
5985   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
5986   ts->functiondomainerror = func;
5987   PetscFunctionReturn(0);
5988 }
5989 
5990 /*@
5991     TSFunctionDomainError - Checks if the current state is valid
5992 
5993     Input Parameters:
5994 +    ts - the TS context
5995 .    stagetime - time of the simulation
5996 -    Y - state vector to check.
5997 
5998     Output Parameter:
5999 .    accept - Set to PETSC_FALSE if the current state vector is valid.
6000 
6001     Note:
6002     This function is called by the TS integration routines and calls the user provided function (set with TSSetFunctionDomainError())
6003     to check if the current state is valid.
6004 
6005     Level: developer
6006 
6007 .seealso: `TSSetFunctionDomainError()`
6008 @*/
6009 PetscErrorCode TSFunctionDomainError(TS ts,PetscReal stagetime,Vec Y,PetscBool* accept)
6010 {
6011   PetscFunctionBegin;
6012   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6013   *accept = PETSC_TRUE;
6014   if (ts->functiondomainerror) {
6015     PetscStackCallStandard((*ts->functiondomainerror),ts,stagetime,Y,accept);
6016   }
6017   PetscFunctionReturn(0);
6018 }
6019 
6020 /*@C
6021   TSClone - This function clones a time step object.
6022 
6023   Collective
6024 
6025   Input Parameter:
6026 . tsin    - The input TS
6027 
6028   Output Parameter:
6029 . tsout   - The output TS (cloned)
6030 
6031   Notes:
6032   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.
6033 
6034   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);
6035 
6036   Level: developer
6037 
6038 .seealso: `TSCreate()`, `TSSetType()`, `TSSetUp()`, `TSDestroy()`, `TSSetProblemType()`
6039 @*/
6040 PetscErrorCode  TSClone(TS tsin, TS *tsout)
6041 {
6042   TS             t;
6043   SNES           snes_start;
6044   DM             dm;
6045   TSType         type;
6046 
6047   PetscFunctionBegin;
6048   PetscValidPointer(tsin,1);
6049   *tsout = NULL;
6050 
6051   PetscCall(PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView));
6052 
6053   /* General TS description */
6054   t->numbermonitors    = 0;
6055   t->monitorFrequency  = 1;
6056   t->setupcalled       = 0;
6057   t->ksp_its           = 0;
6058   t->snes_its          = 0;
6059   t->nwork             = 0;
6060   t->rhsjacobian.time  = PETSC_MIN_REAL;
6061   t->rhsjacobian.scale = 1.;
6062   t->ijacobian.shift   = 1.;
6063 
6064   PetscCall(TSGetSNES(tsin,&snes_start));
6065   PetscCall(TSSetSNES(t,snes_start));
6066 
6067   PetscCall(TSGetDM(tsin,&dm));
6068   PetscCall(TSSetDM(t,dm));
6069 
6070   t->adapt = tsin->adapt;
6071   PetscCall(PetscObjectReference((PetscObject)t->adapt));
6072 
6073   t->trajectory = tsin->trajectory;
6074   PetscCall(PetscObjectReference((PetscObject)t->trajectory));
6075 
6076   t->event = tsin->event;
6077   if (t->event) t->event->refct++;
6078 
6079   t->problem_type      = tsin->problem_type;
6080   t->ptime             = tsin->ptime;
6081   t->ptime_prev        = tsin->ptime_prev;
6082   t->time_step         = tsin->time_step;
6083   t->max_time          = tsin->max_time;
6084   t->steps             = tsin->steps;
6085   t->max_steps         = tsin->max_steps;
6086   t->equation_type     = tsin->equation_type;
6087   t->atol              = tsin->atol;
6088   t->rtol              = tsin->rtol;
6089   t->max_snes_failures = tsin->max_snes_failures;
6090   t->max_reject        = tsin->max_reject;
6091   t->errorifstepfailed = tsin->errorifstepfailed;
6092 
6093   PetscCall(TSGetType(tsin,&type));
6094   PetscCall(TSSetType(t,type));
6095 
6096   t->vec_sol           = NULL;
6097 
6098   t->cfltime          = tsin->cfltime;
6099   t->cfltime_local    = tsin->cfltime_local;
6100   t->exact_final_time = tsin->exact_final_time;
6101 
6102   PetscCall(PetscMemcpy(t->ops,tsin->ops,sizeof(struct _TSOps)));
6103 
6104   if (((PetscObject)tsin)->fortran_func_pointers) {
6105     PetscInt i;
6106     PetscCall(PetscMalloc((10)*sizeof(void(*)(void)),&((PetscObject)t)->fortran_func_pointers));
6107     for (i=0; i<10; i++) {
6108       ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
6109     }
6110   }
6111   *tsout = t;
6112   PetscFunctionReturn(0);
6113 }
6114 
6115 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void* ctx,Vec x,Vec y)
6116 {
6117   TS             ts = (TS) ctx;
6118 
6119   PetscFunctionBegin;
6120   PetscCall(TSComputeRHSFunction(ts,0,x,y));
6121   PetscFunctionReturn(0);
6122 }
6123 
6124 /*@
6125     TSRHSJacobianTest - Compares the multiply routine provided to the MATSHELL with differencing on the TS given RHS function.
6126 
6127    Logically Collective on TS
6128 
6129     Input Parameters:
6130     TS - the time stepping routine
6131 
6132    Output Parameter:
6133 .   flg - PETSC_TRUE if the multiply is likely correct
6134 
6135    Options Database:
6136  .   -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
6137 
6138    Level: advanced
6139 
6140    Notes:
6141     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
6142 
6143 .seealso: `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTestTranspose()`
6144 @*/
6145 PetscErrorCode  TSRHSJacobianTest(TS ts,PetscBool *flg)
6146 {
6147   Mat            J,B;
6148   TSRHSJacobian  func;
6149   void*          ctx;
6150 
6151   PetscFunctionBegin;
6152   PetscCall(TSGetRHSJacobian(ts,&J,&B,&func,&ctx));
6153   PetscCall((*func)(ts,0.0,ts->vec_sol,J,B,ctx));
6154   PetscCall(MatShellTestMult(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg));
6155   PetscFunctionReturn(0);
6156 }
6157 
6158 /*@C
6159     TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the MATSHELL with differencing on the TS given RHS function.
6160 
6161    Logically Collective on TS
6162 
6163     Input Parameters:
6164     TS - the time stepping routine
6165 
6166    Output Parameter:
6167 .   flg - PETSC_TRUE if the multiply is likely correct
6168 
6169    Options Database:
6170 .   -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
6171 
6172    Notes:
6173     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
6174 
6175    Level: advanced
6176 
6177 .seealso: `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`, `MatShellTestMultTranspose()`, `TSRHSJacobianTest()`
6178 @*/
6179 PetscErrorCode  TSRHSJacobianTestTranspose(TS ts,PetscBool *flg)
6180 {
6181   Mat            J,B;
6182   void           *ctx;
6183   TSRHSJacobian  func;
6184 
6185   PetscFunctionBegin;
6186   PetscCall(TSGetRHSJacobian(ts,&J,&B,&func,&ctx));
6187   PetscCall((*func)(ts,0.0,ts->vec_sol,J,B,ctx));
6188   PetscCall(MatShellTestMultTranspose(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg));
6189   PetscFunctionReturn(0);
6190 }
6191 
6192 /*@
6193   TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used.
6194 
6195   Logically collective
6196 
6197   Input Parameters:
6198 +  ts - timestepping context
6199 -  use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used
6200 
6201   Options Database:
6202 .   -ts_use_splitrhsfunction - <true,false>
6203 
6204   Notes:
6205     This is only useful for multirate methods
6206 
6207   Level: intermediate
6208 
6209 .seealso: `TSGetUseSplitRHSFunction()`
6210 @*/
6211 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction)
6212 {
6213   PetscFunctionBegin;
6214   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6215   ts->use_splitrhsfunction = use_splitrhsfunction;
6216   PetscFunctionReturn(0);
6217 }
6218 
6219 /*@
6220   TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used.
6221 
6222   Not collective
6223 
6224   Input Parameter:
6225 .  ts - timestepping context
6226 
6227   Output Parameter:
6228 .  use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used
6229 
6230   Level: intermediate
6231 
6232 .seealso: `TSSetUseSplitRHSFunction()`
6233 @*/
6234 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction)
6235 {
6236   PetscFunctionBegin;
6237   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6238   *use_splitrhsfunction = ts->use_splitrhsfunction;
6239   PetscFunctionReturn(0);
6240 }
6241 
6242 /*@
6243     TSSetMatStructure - sets the relationship between the nonzero structure of the RHS Jacobian matrix to the IJacobian matrix.
6244 
6245    Logically  Collective on ts
6246 
6247    Input Parameters:
6248 +  ts - the time-stepper
6249 -  str - the structure (the default is UNKNOWN_NONZERO_PATTERN)
6250 
6251    Level: intermediate
6252 
6253    Notes:
6254      When the relationship between the nonzero structures is known and supplied the solution process can be much faster
6255 
6256 .seealso: `MatAXPY()`, `MatStructure`
6257  @*/
6258 PetscErrorCode TSSetMatStructure(TS ts,MatStructure str)
6259 {
6260   PetscFunctionBegin;
6261   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6262   ts->axpy_pattern = str;
6263   PetscFunctionReturn(0);
6264 }
6265 
6266 /*@
6267   TSSetTimeSpan - sets the time span. The solution will be computed and stored for each time requested.
6268 
6269   Collective on ts
6270 
6271   Input Parameters:
6272 + ts - the time-stepper
6273 . n - number of the time points (>=2)
6274 - span_times - array of the time points. The first element and the last element are the initial time and the final time respectively.
6275 
6276   Options Database Keys:
6277 . -ts_time_span <t0,...tf> - Sets the time span
6278 
6279   Level: beginner
6280 
6281   Notes:
6282   The elements in tspan must be all increasing. They correspond to the intermediate points for time integration.
6283   TS_EXACTFINALTIME_MATCHSTEP must be used to make the last time step in each sub-interval match the intermediate points specified.
6284   The intermediate solutions are saved in a vector array that can be accessed with TSGetSolutions(). Thus using time span may
6285   pressure the memory system when using a large number of span points.
6286 
6287 .seealso: `TSGetTimeSpan()`, `TSGetSolutions()`
6288  @*/
6289 PetscErrorCode TSSetTimeSpan(TS ts,PetscInt n,PetscReal *span_times)
6290 {
6291   PetscFunctionBegin;
6292   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6293   PetscCheck(n >= 2,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Minimum time span size is 2 but %" PetscInt_FMT " is provided",n);
6294   if (ts->tspan && n != ts->tspan->num_span_times) {
6295     PetscCall(PetscFree(ts->tspan->span_times));
6296     PetscCall(VecDestroyVecs(ts->tspan->num_span_times,&ts->tspan->vecs_sol));
6297     PetscCall(PetscMalloc1(n,&ts->tspan->span_times));
6298   }
6299   if (!ts->tspan) {
6300     TSTimeSpan tspan;
6301     PetscCall(PetscNew(&tspan));
6302     PetscCall(PetscMalloc1(n,&tspan->span_times));
6303     ts->tspan = tspan;
6304   }
6305   ts->tspan->num_span_times = n;
6306   PetscCall(PetscArraycpy(ts->tspan->span_times,span_times,n));
6307   PetscCall(TSSetTime(ts,ts->tspan->span_times[0]));
6308   PetscCall(TSSetMaxTime(ts,ts->tspan->span_times[n-1]));
6309   PetscFunctionReturn(0);
6310 }
6311 
6312 /*@C
6313   TSGetTimeSpan - gets the time span.
6314 
6315   Not Collective
6316 
6317   Input Parameter:
6318 . ts - the time-stepper
6319 
6320   Output Parameters:
6321 + n - number of the time points (>=2)
6322 - 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.
6323 
6324   Level: beginner
6325   Notes: Both n and span_times can be NULL.
6326 
6327 .seealso: `TSSetTimeSpan()`, `TSGetSolutions()`
6328  @*/
6329 PetscErrorCode TSGetTimeSpan(TS ts,PetscInt *n,const PetscReal **span_times)
6330 {
6331   PetscFunctionBegin;
6332   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6333   if (n) PetscValidIntPointer(n,2);
6334   if (span_times) PetscValidPointer(span_times,3);
6335   if (!ts->tspan) {
6336     if (n) *n = 0;
6337     if (span_times) *span_times = NULL;
6338   } else {
6339     if (n) *n = ts->tspan->num_span_times;
6340     if (span_times) *span_times = ts->tspan->span_times;
6341   }
6342   PetscFunctionReturn(0);
6343 }
6344 
6345 /*@
6346    TSGetTimeSpanSolutions - Get the number of solutions and the solutions at the time points specified by the time span.
6347 
6348    Input Parameter:
6349 .  ts - the TS context obtained from TSCreate()
6350 
6351    Output Parameters:
6352 +  nsol - the number of solutions
6353 -  Sols - the solution vectors
6354 
6355    Level: beginner
6356 
6357    Notes: Both nsol and Sols can be NULL.
6358 
6359 .seealso: `TSSetTimeSpan()`
6360 @*/
6361 PetscErrorCode TSGetTimeSpanSolutions(TS ts,PetscInt *nsol,Vec **Sols)
6362 {
6363   PetscFunctionBegin;
6364   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
6365   if (nsol) PetscValidIntPointer(nsol,2);
6366   if (Sols) PetscValidPointer(Sols,3);
6367   if (!ts->tspan) {
6368     if (nsol) *nsol = 0;
6369     if (Sols) *Sols = NULL;
6370   } else {
6371     if (nsol) *nsol = ts->tspan->num_span_times;
6372     if (Sols) *Sols = ts->tspan->vecs_sol;
6373   }
6374   PetscFunctionReturn(0);
6375 }
6376