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