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