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