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