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