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