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