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