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