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