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