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