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