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