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