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