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