xref: /petsc/src/ts/interface/ts.c (revision 2808aa04d940ba1f87fcb21c96b65d17786a2b67)
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->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   ptime = ts->ptime; ts->ptime_prev_rollback = ts->ptime_prev;
4075   ts->reason = TS_CONVERGED_ITERATING;
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++;
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->adjoint_steps++; ts->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->adjoint_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 
4300   if (!ts->steps) {
4301     ts->ksp_its           = 0;
4302     ts->snes_its          = 0;
4303     ts->num_snes_failures = 0;
4304     ts->reject            = 0;
4305     ts->steprestart       = PETSC_TRUE;
4306     ts->steprollback      = PETSC_FALSE;
4307   }
4308   ts->reason = TS_CONVERGED_ITERATING;
4309 
4310   ierr = TSViewFromOptions(ts,NULL,"-ts_view_pre");CHKERRQ(ierr);
4311 
4312   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
4313     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
4314     if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
4315     ts->solvetime = ts->ptime;
4316     solution = ts->vec_sol;
4317   } else { /* Step the requested number of timesteps. */
4318     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4319     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4320 
4321     if (!ts->steps) {
4322       ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4323       ierr = TSEventInitialize(ts->event,ts,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4324     }
4325 
4326     while (!ts->reason) {
4327       ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4328       if (!ts->steprollback) {
4329         ierr = TSPreStep(ts);CHKERRQ(ierr);
4330       }
4331       ierr = TSStep(ts);CHKERRQ(ierr);
4332       if (ts->vec_costintegral && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
4333         ierr = TSForwardCostIntegral(ts);CHKERRQ(ierr);
4334       }
4335       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 */
4336         ierr = TSForwardStep(ts);CHKERRQ(ierr);
4337       }
4338       ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
4339       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. */
4340       if (!ts->steprollback) {
4341         ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4342         ierr = TSPostStep(ts);CHKERRQ(ierr);
4343       }
4344     }
4345     ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4346 
4347     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
4348       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
4349       ts->solvetime = ts->max_time;
4350       solution = u;
4351       ierr = TSMonitor(ts,-1,ts->solvetime,solution);CHKERRQ(ierr);
4352     } else {
4353       if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
4354       ts->solvetime = ts->ptime;
4355       solution = ts->vec_sol;
4356     }
4357   }
4358 
4359   ierr = TSViewFromOptions(ts,NULL,"-ts_view");CHKERRQ(ierr);
4360   ierr = VecViewFromOptions(solution,NULL,"-ts_view_solution");CHKERRQ(ierr);
4361   ierr = PetscObjectSAWsBlock((PetscObject)ts);CHKERRQ(ierr);
4362   if (ts->adjoint_solve) {
4363     ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
4364   }
4365   PetscFunctionReturn(0);
4366 }
4367 
4368 /*@
4369  TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run.
4370 
4371  Collective on TS
4372 
4373  Input Arguments:
4374  .  ts - time stepping context
4375 
4376  Level: advanced
4377 
4378  Notes:
4379  This function cannot be called until TSAdjointStep() has been completed.
4380 
4381  .seealso: TSAdjointSolve(), TSAdjointStep
4382  @*/
4383 PetscErrorCode TSAdjointCostIntegral(TS ts)
4384 {
4385     PetscErrorCode ierr;
4386     PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4387     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);
4388     ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr);
4389     PetscFunctionReturn(0);
4390 }
4391 
4392 /*@
4393    TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
4394 
4395    Collective on TS
4396 
4397    Input Parameter:
4398 .  ts - the TS context obtained from TSCreate()
4399 
4400    Options Database:
4401 . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values
4402 
4403    Level: intermediate
4404 
4405    Notes:
4406    This must be called after a call to TSSolve() that solves the forward problem
4407 
4408    By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time
4409 
4410 .keywords: TS, timestep, solve
4411 
4412 .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep()
4413 @*/
4414 PetscErrorCode TSAdjointSolve(TS ts)
4415 {
4416   PetscErrorCode    ierr;
4417 
4418   PetscFunctionBegin;
4419   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4420   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
4421 
4422   /* reset time step and iteration counters */
4423   ts->adjoint_steps     = 0;
4424   ts->ksp_its           = 0;
4425   ts->snes_its          = 0;
4426   ts->num_snes_failures = 0;
4427   ts->reject            = 0;
4428   ts->reason            = TS_CONVERGED_ITERATING;
4429 
4430   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps;
4431   if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
4432 
4433   while (!ts->reason) {
4434     ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
4435     ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
4436     ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr);
4437     ierr = TSAdjointStep(ts);CHKERRQ(ierr);
4438     if (ts->vec_costintegral && !ts->costintegralfwd) {
4439       ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr);
4440     }
4441   }
4442   ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
4443   ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
4444   ts->solvetime = ts->ptime;
4445   ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr);
4446   ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr);
4447   PetscFunctionReturn(0);
4448 }
4449 
4450 /*@C
4451    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
4452 
4453    Collective on TS
4454 
4455    Input Parameters:
4456 +  ts - time stepping context obtained from TSCreate()
4457 .  step - step number that has just completed
4458 .  ptime - model time of the state
4459 -  u - state at the current model time
4460 
4461    Notes:
4462    TSMonitor() is typically used automatically within the time stepping implementations.
4463    Users would almost never call this routine directly.
4464 
4465    A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
4466 
4467    Level: developer
4468 
4469 .keywords: TS, timestep
4470 @*/
4471 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
4472 {
4473   DM             dm;
4474   PetscInt       i,n = ts->numbermonitors;
4475   PetscErrorCode ierr;
4476 
4477   PetscFunctionBegin;
4478   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4479   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4480 
4481   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4482   ierr = DMSetOutputSequenceNumber(dm,step,ptime);CHKERRQ(ierr);
4483 
4484   ierr = VecLockPush(u);CHKERRQ(ierr);
4485   for (i=0; i<n; i++) {
4486     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
4487   }
4488   ierr = VecLockPop(u);CHKERRQ(ierr);
4489   PetscFunctionReturn(0);
4490 }
4491 
4492 /*@C
4493    TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet()
4494 
4495    Collective on TS
4496 
4497    Input Parameters:
4498 +  ts - time stepping context obtained from TSCreate()
4499 .  step - step number that has just completed
4500 .  ptime - model time of the state
4501 .  u - state at the current model time
4502 .  numcost - number of cost functions (dimension of lambda  or mu)
4503 .  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
4504 -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
4505 
4506    Notes:
4507    TSAdjointMonitor() is typically used automatically within the time stepping implementations.
4508    Users would almost never call this routine directly.
4509 
4510    Level: developer
4511 
4512 .keywords: TS, timestep
4513 @*/
4514 PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu)
4515 {
4516   PetscErrorCode ierr;
4517   PetscInt       i,n = ts->numberadjointmonitors;
4518 
4519   PetscFunctionBegin;
4520   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4521   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4522   ierr = VecLockPush(u);CHKERRQ(ierr);
4523   for (i=0; i<n; i++) {
4524     ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
4525   }
4526   ierr = VecLockPop(u);CHKERRQ(ierr);
4527   PetscFunctionReturn(0);
4528 }
4529 
4530 /* ------------------------------------------------------------------------*/
4531 /*@C
4532    TSMonitorLGCtxCreate - Creates a TSMonitorLGCtx context for use with
4533    TS to monitor the solution process graphically in various ways
4534 
4535    Collective on TS
4536 
4537    Input Parameters:
4538 +  host - the X display to open, or null for the local machine
4539 .  label - the title to put in the title bar
4540 .  x, y - the screen coordinates of the upper left coordinate of the window
4541 .  m, n - the screen width and height in pixels
4542 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
4543 
4544    Output Parameter:
4545 .  ctx - the context
4546 
4547    Options Database Key:
4548 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
4549 .  -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling TSMonitorLGSetDisplayVariables() or TSMonitorLGCtxSetDisplayVariables())
4550 .  -ts_monitor_lg_error -  monitor the error
4551 .  -ts_monitor_lg_ksp_iterations - monitor the number of KSP iterations needed for each timestep
4552 .  -ts_monitor_lg_snes_iterations - monitor the number of SNES iterations needed for each timestep
4553 -  -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
4554 
4555    Notes:
4556    Use TSMonitorLGCtxDestroy() to destroy.
4557 
4558    One can provide a function that transforms the solution before plotting it with TSMonitorLGCtxSetTransform() or TSMonitorLGSetTransform()
4559 
4560    Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a TS object as the
4561    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
4562    as the first argument.
4563 
4564    One can control the names displayed for each solution or error variable with TSMonitorLGCtxSetVariableNames() or TSMonitorLGSetVariableNames()
4565 
4566    Level: intermediate
4567 
4568 .keywords: TS, monitor, line graph, residual
4569 
4570 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError(), TSMonitorDefault(), VecView(),
4571            TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
4572            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
4573            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
4574            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
4575 
4576 @*/
4577 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
4578 {
4579   PetscDraw      draw;
4580   PetscErrorCode ierr;
4581 
4582   PetscFunctionBegin;
4583   ierr = PetscNew(ctx);CHKERRQ(ierr);
4584   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&draw);CHKERRQ(ierr);
4585   ierr = PetscDrawSetFromOptions(draw);CHKERRQ(ierr);
4586   ierr = PetscDrawLGCreate(draw,1,&(*ctx)->lg);CHKERRQ(ierr);
4587   ierr = PetscDrawLGSetFromOptions((*ctx)->lg);CHKERRQ(ierr);
4588   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
4589   (*ctx)->howoften = howoften;
4590   PetscFunctionReturn(0);
4591 }
4592 
4593 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
4594 {
4595   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4596   PetscReal      x   = ptime,y;
4597   PetscErrorCode ierr;
4598 
4599   PetscFunctionBegin;
4600   if (step < 0) PetscFunctionReturn(0); /* -1 indicates an interpolated solution */
4601   if (!step) {
4602     PetscDrawAxis axis;
4603     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4604     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time","Time Step");CHKERRQ(ierr);
4605     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4606   }
4607   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
4608   y =  PetscLog10Real(y);
4609   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4610   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4611     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4612     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
4613   }
4614   PetscFunctionReturn(0);
4615 }
4616 
4617 /*@C
4618    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
4619    with TSMonitorLGCtxCreate().
4620 
4621    Collective on TSMonitorLGCtx
4622 
4623    Input Parameter:
4624 .  ctx - the monitor context
4625 
4626    Level: intermediate
4627 
4628 .keywords: TS, monitor, line graph, destroy
4629 
4630 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
4631 @*/
4632 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
4633 {
4634   PetscErrorCode ierr;
4635 
4636   PetscFunctionBegin;
4637   if ((*ctx)->transformdestroy) {
4638     ierr = ((*ctx)->transformdestroy)((*ctx)->transformctx);CHKERRQ(ierr);
4639   }
4640   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
4641   ierr = PetscStrArrayDestroy(&(*ctx)->names);CHKERRQ(ierr);
4642   ierr = PetscStrArrayDestroy(&(*ctx)->displaynames);CHKERRQ(ierr);
4643   ierr = PetscFree((*ctx)->displayvariables);CHKERRQ(ierr);
4644   ierr = PetscFree((*ctx)->displayvalues);CHKERRQ(ierr);
4645   ierr = PetscFree(*ctx);CHKERRQ(ierr);
4646   PetscFunctionReturn(0);
4647 }
4648 
4649 /*@
4650    TSGetTime - Gets the time of the most recently completed step.
4651 
4652    Not Collective
4653 
4654    Input Parameter:
4655 .  ts - the TS context obtained from TSCreate()
4656 
4657    Output Parameter:
4658 .  t  - the current time. This time may not corresponds to the final time set with TSSetDuration(), use TSGetSolveTime().
4659 
4660    Level: beginner
4661 
4662    Note:
4663    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
4664    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
4665 
4666 .seealso: TSSetInitialTimeStep(), TSGetTimeStep(), TSGetSolveTime()
4667 
4668 .keywords: TS, get, time
4669 @*/
4670 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
4671 {
4672   PetscFunctionBegin;
4673   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4674   PetscValidRealPointer(t,2);
4675   *t = ts->ptime;
4676   PetscFunctionReturn(0);
4677 }
4678 
4679 /*@
4680    TSGetPrevTime - Gets the starting time of the previously completed step.
4681 
4682    Not Collective
4683 
4684    Input Parameter:
4685 .  ts - the TS context obtained from TSCreate()
4686 
4687    Output Parameter:
4688 .  t  - the previous time
4689 
4690    Level: beginner
4691 
4692 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
4693 
4694 .keywords: TS, get, time
4695 @*/
4696 PetscErrorCode  TSGetPrevTime(TS ts,PetscReal *t)
4697 {
4698   PetscFunctionBegin;
4699   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4700   PetscValidRealPointer(t,2);
4701   *t = ts->ptime_prev;
4702   PetscFunctionReturn(0);
4703 }
4704 
4705 /*@
4706    TSSetTime - Allows one to reset the time.
4707 
4708    Logically Collective on TS
4709 
4710    Input Parameters:
4711 +  ts - the TS context obtained from TSCreate()
4712 -  time - the time
4713 
4714    Level: intermediate
4715 
4716 .seealso: TSGetTime(), TSSetDuration()
4717 
4718 .keywords: TS, set, time
4719 @*/
4720 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
4721 {
4722   PetscFunctionBegin;
4723   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4724   PetscValidLogicalCollectiveReal(ts,t,2);
4725   ts->ptime = t;
4726   PetscFunctionReturn(0);
4727 }
4728 
4729 /*@C
4730    TSSetOptionsPrefix - Sets the prefix used for searching for all
4731    TS options in the database.
4732 
4733    Logically Collective on TS
4734 
4735    Input Parameter:
4736 +  ts     - The TS context
4737 -  prefix - The prefix to prepend to all option names
4738 
4739    Notes:
4740    A hyphen (-) must NOT be given at the beginning of the prefix name.
4741    The first character of all runtime options is AUTOMATICALLY the
4742    hyphen.
4743 
4744    Level: advanced
4745 
4746 .keywords: TS, set, options, prefix, database
4747 
4748 .seealso: TSSetFromOptions()
4749 
4750 @*/
4751 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
4752 {
4753   PetscErrorCode ierr;
4754   SNES           snes;
4755 
4756   PetscFunctionBegin;
4757   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4758   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4759   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4760   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4761   PetscFunctionReturn(0);
4762 }
4763 
4764 /*@C
4765    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4766    TS options in the database.
4767 
4768    Logically Collective on TS
4769 
4770    Input Parameter:
4771 +  ts     - The TS context
4772 -  prefix - The prefix to prepend to all option names
4773 
4774    Notes:
4775    A hyphen (-) must NOT be given at the beginning of the prefix name.
4776    The first character of all runtime options is AUTOMATICALLY the
4777    hyphen.
4778 
4779    Level: advanced
4780 
4781 .keywords: TS, append, options, prefix, database
4782 
4783 .seealso: TSGetOptionsPrefix()
4784 
4785 @*/
4786 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
4787 {
4788   PetscErrorCode ierr;
4789   SNES           snes;
4790 
4791   PetscFunctionBegin;
4792   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4793   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4794   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4795   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4796   PetscFunctionReturn(0);
4797 }
4798 
4799 /*@C
4800    TSGetOptionsPrefix - Sets the prefix used for searching for all
4801    TS options in the database.
4802 
4803    Not Collective
4804 
4805    Input Parameter:
4806 .  ts - The TS context
4807 
4808    Output Parameter:
4809 .  prefix - A pointer to the prefix string used
4810 
4811    Notes: On the fortran side, the user should pass in a string 'prifix' of
4812    sufficient length to hold the prefix.
4813 
4814    Level: intermediate
4815 
4816 .keywords: TS, get, options, prefix, database
4817 
4818 .seealso: TSAppendOptionsPrefix()
4819 @*/
4820 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
4821 {
4822   PetscErrorCode ierr;
4823 
4824   PetscFunctionBegin;
4825   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4826   PetscValidPointer(prefix,2);
4827   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4828   PetscFunctionReturn(0);
4829 }
4830 
4831 /*@C
4832    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4833 
4834    Not Collective, but parallel objects are returned if TS is parallel
4835 
4836    Input Parameter:
4837 .  ts  - The TS context obtained from TSCreate()
4838 
4839    Output Parameters:
4840 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
4841 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
4842 .  func - Function to compute the Jacobian of the RHS  (or NULL)
4843 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
4844 
4845    Notes: You can pass in NULL for any return argument you do not need.
4846 
4847    Level: intermediate
4848 
4849 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4850 
4851 .keywords: TS, timestep, get, matrix, Jacobian
4852 @*/
4853 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
4854 {
4855   PetscErrorCode ierr;
4856   DM             dm;
4857 
4858   PetscFunctionBegin;
4859   if (Amat || Pmat) {
4860     SNES snes;
4861     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4862     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4863     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4864   }
4865   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4866   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
4867   PetscFunctionReturn(0);
4868 }
4869 
4870 /*@C
4871    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4872 
4873    Not Collective, but parallel objects are returned if TS is parallel
4874 
4875    Input Parameter:
4876 .  ts  - The TS context obtained from TSCreate()
4877 
4878    Output Parameters:
4879 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
4880 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
4881 .  f   - The function to compute the matrices
4882 - ctx - User-defined context for Jacobian evaluation routine
4883 
4884    Notes: You can pass in NULL for any return argument you do not need.
4885 
4886    Level: advanced
4887 
4888 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4889 
4890 .keywords: TS, timestep, get, matrix, Jacobian
4891 @*/
4892 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
4893 {
4894   PetscErrorCode ierr;
4895   DM             dm;
4896 
4897   PetscFunctionBegin;
4898   if (Amat || Pmat) {
4899     SNES snes;
4900     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4901     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4902     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4903   }
4904   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4905   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
4906   PetscFunctionReturn(0);
4907 }
4908 
4909 /*@C
4910    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
4911    VecView() for the solution at each timestep
4912 
4913    Collective on TS
4914 
4915    Input Parameters:
4916 +  ts - the TS context
4917 .  step - current time-step
4918 .  ptime - current time
4919 -  dummy - either a viewer or NULL
4920 
4921    Options Database:
4922 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
4923 
4924    Notes: the initial solution and current solution are not display with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
4925        will look bad
4926 
4927    Level: intermediate
4928 
4929 .keywords: TS,  vector, monitor, view
4930 
4931 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4932 @*/
4933 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4934 {
4935   PetscErrorCode   ierr;
4936   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
4937   PetscDraw        draw;
4938 
4939   PetscFunctionBegin;
4940   if (!step && ictx->showinitial) {
4941     if (!ictx->initialsolution) {
4942       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
4943     }
4944     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
4945   }
4946   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4947 
4948   if (ictx->showinitial) {
4949     PetscReal pause;
4950     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
4951     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
4952     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
4953     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
4954     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
4955   }
4956   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
4957   if (ictx->showtimestepandtime) {
4958     PetscReal xl,yl,xr,yr,h;
4959     char      time[32];
4960 
4961     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4962     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4963     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4964     h    = yl + .95*(yr - yl);
4965     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4966     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4967   }
4968 
4969   if (ictx->showinitial) {
4970     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
4971   }
4972   PetscFunctionReturn(0);
4973 }
4974 
4975 /*@C
4976    TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling
4977    VecView() for the sensitivities to initial states at each timestep
4978 
4979    Collective on TS
4980 
4981    Input Parameters:
4982 +  ts - the TS context
4983 .  step - current time-step
4984 .  ptime - current time
4985 .  u - current state
4986 .  numcost - number of cost functions
4987 .  lambda - sensitivities to initial conditions
4988 .  mu - sensitivities to parameters
4989 -  dummy - either a viewer or NULL
4990 
4991    Level: intermediate
4992 
4993 .keywords: TS,  vector, adjoint, monitor, view
4994 
4995 .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView()
4996 @*/
4997 PetscErrorCode  TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy)
4998 {
4999   PetscErrorCode   ierr;
5000   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
5001   PetscDraw        draw;
5002   PetscReal        xl,yl,xr,yr,h;
5003   char             time[32];
5004 
5005   PetscFunctionBegin;
5006   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
5007 
5008   ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr);
5009   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
5010   ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
5011   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
5012   h    = yl + .95*(yr - yl);
5013   ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
5014   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
5015   PetscFunctionReturn(0);
5016 }
5017 
5018 /*@C
5019    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
5020 
5021    Collective on TS
5022 
5023    Input Parameters:
5024 +  ts - the TS context
5025 .  step - current time-step
5026 .  ptime - current time
5027 -  dummy - either a viewer or NULL
5028 
5029    Level: intermediate
5030 
5031 .keywords: TS,  vector, monitor, view
5032 
5033 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5034 @*/
5035 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5036 {
5037   PetscErrorCode    ierr;
5038   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
5039   PetscDraw         draw;
5040   PetscDrawAxis     axis;
5041   PetscInt          n;
5042   PetscMPIInt       size;
5043   PetscReal         U0,U1,xl,yl,xr,yr,h;
5044   char              time[32];
5045   const PetscScalar *U;
5046 
5047   PetscFunctionBegin;
5048   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)ts),&size);CHKERRQ(ierr);
5049   if (size != 1) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only allowed for sequential runs");
5050   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
5051   if (n != 2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only for ODEs with two unknowns");
5052 
5053   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
5054   ierr = PetscViewerDrawGetDrawAxis(ictx->viewer,0,&axis);CHKERRQ(ierr);
5055   ierr = PetscDrawAxisGetLimits(axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
5056   if (!step) {
5057     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
5058     ierr = PetscDrawAxisDraw(axis);CHKERRQ(ierr);
5059   }
5060 
5061   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
5062   U0 = PetscRealPart(U[0]);
5063   U1 = PetscRealPart(U[1]);
5064   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
5065   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(0);
5066 
5067   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
5068   ierr = PetscDrawPoint(draw,U0,U1,PETSC_DRAW_BLACK);CHKERRQ(ierr);
5069   if (ictx->showtimestepandtime) {
5070     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
5071     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
5072     h    = yl + .95*(yr - yl);
5073     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
5074   }
5075   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
5076   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
5077   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
5078   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
5079   PetscFunctionReturn(0);
5080 }
5081 
5082 /*@C
5083    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
5084 
5085    Collective on TS
5086 
5087    Input Parameters:
5088 .    ctx - the monitor context
5089 
5090    Level: intermediate
5091 
5092 .keywords: TS,  vector, monitor, view
5093 
5094 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
5095 @*/
5096 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
5097 {
5098   PetscErrorCode ierr;
5099 
5100   PetscFunctionBegin;
5101   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
5102   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
5103   ierr = PetscFree(*ictx);CHKERRQ(ierr);
5104   PetscFunctionReturn(0);
5105 }
5106 
5107 /*@C
5108    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
5109 
5110    Collective on TS
5111 
5112    Input Parameter:
5113 .    ts - time-step context
5114 
5115    Output Patameter:
5116 .    ctx - the monitor context
5117 
5118    Options Database:
5119 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
5120 
5121    Level: intermediate
5122 
5123 .keywords: TS,  vector, monitor, view
5124 
5125 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
5126 @*/
5127 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
5128 {
5129   PetscErrorCode   ierr;
5130 
5131   PetscFunctionBegin;
5132   ierr = PetscNew(ctx);CHKERRQ(ierr);
5133   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
5134   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
5135 
5136   (*ctx)->howoften    = howoften;
5137   (*ctx)->showinitial = PETSC_FALSE;
5138   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
5139 
5140   (*ctx)->showtimestepandtime = PETSC_FALSE;
5141   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
5142   PetscFunctionReturn(0);
5143 }
5144 
5145 /*@C
5146    TSMonitorDrawError - Monitors progress of the TS solvers by calling
5147    VecView() for the error at each timestep
5148 
5149    Collective on TS
5150 
5151    Input Parameters:
5152 +  ts - the TS context
5153 .  step - current time-step
5154 .  ptime - current time
5155 -  dummy - either a viewer or NULL
5156 
5157    Level: intermediate
5158 
5159 .keywords: TS,  vector, monitor, view
5160 
5161 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5162 @*/
5163 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5164 {
5165   PetscErrorCode   ierr;
5166   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
5167   PetscViewer      viewer = ctx->viewer;
5168   Vec              work;
5169 
5170   PetscFunctionBegin;
5171   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
5172   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
5173   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
5174   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
5175   ierr = VecView(work,viewer);CHKERRQ(ierr);
5176   ierr = VecDestroy(&work);CHKERRQ(ierr);
5177   PetscFunctionReturn(0);
5178 }
5179 
5180 #include <petsc/private/dmimpl.h>
5181 /*@
5182    TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS
5183 
5184    Logically Collective on TS and DM
5185 
5186    Input Parameters:
5187 +  ts - the ODE integrator object
5188 -  dm - the dm, cannot be NULL
5189 
5190    Level: intermediate
5191 
5192 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
5193 @*/
5194 PetscErrorCode  TSSetDM(TS ts,DM dm)
5195 {
5196   PetscErrorCode ierr;
5197   SNES           snes;
5198   DMTS           tsdm;
5199 
5200   PetscFunctionBegin;
5201   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5202   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
5203   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
5204   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
5205     if (ts->dm->dmts && !dm->dmts) {
5206       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
5207       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
5208       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
5209         tsdm->originaldm = dm;
5210       }
5211     }
5212     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
5213   }
5214   ts->dm = dm;
5215 
5216   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
5217   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
5218   PetscFunctionReturn(0);
5219 }
5220 
5221 /*@
5222    TSGetDM - Gets the DM that may be used by some preconditioners
5223 
5224    Not Collective
5225 
5226    Input Parameter:
5227 . ts - the preconditioner context
5228 
5229    Output Parameter:
5230 .  dm - the dm
5231 
5232    Level: intermediate
5233 
5234 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
5235 @*/
5236 PetscErrorCode  TSGetDM(TS ts,DM *dm)
5237 {
5238   PetscErrorCode ierr;
5239 
5240   PetscFunctionBegin;
5241   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5242   if (!ts->dm) {
5243     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
5244     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
5245   }
5246   *dm = ts->dm;
5247   PetscFunctionReturn(0);
5248 }
5249 
5250 /*@
5251    SNESTSFormFunction - Function to evaluate nonlinear residual
5252 
5253    Logically Collective on SNES
5254 
5255    Input Parameter:
5256 + snes - nonlinear solver
5257 . U - the current state at which to evaluate the residual
5258 - ctx - user context, must be a TS
5259 
5260    Output Parameter:
5261 . F - the nonlinear residual
5262 
5263    Notes:
5264    This function is not normally called by users and is automatically registered with the SNES used by TS.
5265    It is most frequently passed to MatFDColoringSetFunction().
5266 
5267    Level: advanced
5268 
5269 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
5270 @*/
5271 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
5272 {
5273   TS             ts = (TS)ctx;
5274   PetscErrorCode ierr;
5275 
5276   PetscFunctionBegin;
5277   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
5278   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5279   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
5280   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
5281   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
5282   PetscFunctionReturn(0);
5283 }
5284 
5285 /*@
5286    SNESTSFormJacobian - Function to evaluate the Jacobian
5287 
5288    Collective on SNES
5289 
5290    Input Parameter:
5291 + snes - nonlinear solver
5292 . U - the current state at which to evaluate the residual
5293 - ctx - user context, must be a TS
5294 
5295    Output Parameter:
5296 + A - the Jacobian
5297 . B - the preconditioning matrix (may be the same as A)
5298 - flag - indicates any structure change in the matrix
5299 
5300    Notes:
5301    This function is not normally called by users and is automatically registered with the SNES used by TS.
5302 
5303    Level: developer
5304 
5305 .seealso: SNESSetJacobian()
5306 @*/
5307 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
5308 {
5309   TS             ts = (TS)ctx;
5310   PetscErrorCode ierr;
5311 
5312   PetscFunctionBegin;
5313   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
5314   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5315   PetscValidPointer(A,3);
5316   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
5317   PetscValidPointer(B,4);
5318   PetscValidHeaderSpecific(B,MAT_CLASSID,4);
5319   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
5320   ierr = (ts->ops->snesjacobian)(snes,U,A,B,ts);CHKERRQ(ierr);
5321   PetscFunctionReturn(0);
5322 }
5323 
5324 /*@C
5325    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only
5326 
5327    Collective on TS
5328 
5329    Input Arguments:
5330 +  ts - time stepping context
5331 .  t - time at which to evaluate
5332 .  U - state at which to evaluate
5333 -  ctx - context
5334 
5335    Output Arguments:
5336 .  F - right hand side
5337 
5338    Level: intermediate
5339 
5340    Notes:
5341    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
5342    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
5343 
5344 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
5345 @*/
5346 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
5347 {
5348   PetscErrorCode ierr;
5349   Mat            Arhs,Brhs;
5350 
5351   PetscFunctionBegin;
5352   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
5353   ierr = TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);CHKERRQ(ierr);
5354   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
5355   PetscFunctionReturn(0);
5356 }
5357 
5358 /*@C
5359    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
5360 
5361    Collective on TS
5362 
5363    Input Arguments:
5364 +  ts - time stepping context
5365 .  t - time at which to evaluate
5366 .  U - state at which to evaluate
5367 -  ctx - context
5368 
5369    Output Arguments:
5370 +  A - pointer to operator
5371 .  B - pointer to preconditioning matrix
5372 -  flg - matrix structure flag
5373 
5374    Level: intermediate
5375 
5376    Notes:
5377    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
5378 
5379 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
5380 @*/
5381 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
5382 {
5383   PetscFunctionBegin;
5384   PetscFunctionReturn(0);
5385 }
5386 
5387 /*@C
5388    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
5389 
5390    Collective on TS
5391 
5392    Input Arguments:
5393 +  ts - time stepping context
5394 .  t - time at which to evaluate
5395 .  U - state at which to evaluate
5396 .  Udot - time derivative of state vector
5397 -  ctx - context
5398 
5399    Output Arguments:
5400 .  F - left hand side
5401 
5402    Level: intermediate
5403 
5404    Notes:
5405    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
5406    user is required to write their own TSComputeIFunction.
5407    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
5408    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
5409 
5410    Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U
5411 
5412 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant(), TSComputeRHSFunctionLinear()
5413 @*/
5414 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
5415 {
5416   PetscErrorCode ierr;
5417   Mat            A,B;
5418 
5419   PetscFunctionBegin;
5420   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
5421   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE);CHKERRQ(ierr);
5422   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
5423   PetscFunctionReturn(0);
5424 }
5425 
5426 /*@C
5427    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
5428 
5429    Collective on TS
5430 
5431    Input Arguments:
5432 +  ts - time stepping context
5433 .  t - time at which to evaluate
5434 .  U - state at which to evaluate
5435 .  Udot - time derivative of state vector
5436 .  shift - shift to apply
5437 -  ctx - context
5438 
5439    Output Arguments:
5440 +  A - pointer to operator
5441 .  B - pointer to preconditioning matrix
5442 -  flg - matrix structure flag
5443 
5444    Level: advanced
5445 
5446    Notes:
5447    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
5448 
5449    It is only appropriate for problems of the form
5450 
5451 $     M Udot = F(U,t)
5452 
5453   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
5454   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
5455   an implicit operator of the form
5456 
5457 $    shift*M + J
5458 
5459   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
5460   a copy of M or reassemble it when requested.
5461 
5462 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
5463 @*/
5464 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
5465 {
5466   PetscErrorCode ierr;
5467 
5468   PetscFunctionBegin;
5469   ierr = MatScale(A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
5470   ts->ijacobian.shift = shift;
5471   PetscFunctionReturn(0);
5472 }
5473 
5474 /*@
5475    TSGetEquationType - Gets the type of the equation that TS is solving.
5476 
5477    Not Collective
5478 
5479    Input Parameter:
5480 .  ts - the TS context
5481 
5482    Output Parameter:
5483 .  equation_type - see TSEquationType
5484 
5485    Level: beginner
5486 
5487 .keywords: TS, equation type
5488 
5489 .seealso: TSSetEquationType(), TSEquationType
5490 @*/
5491 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
5492 {
5493   PetscFunctionBegin;
5494   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5495   PetscValidPointer(equation_type,2);
5496   *equation_type = ts->equation_type;
5497   PetscFunctionReturn(0);
5498 }
5499 
5500 /*@
5501    TSSetEquationType - Sets the type of the equation that TS is solving.
5502 
5503    Not Collective
5504 
5505    Input Parameter:
5506 +  ts - the TS context
5507 -  equation_type - see TSEquationType
5508 
5509    Level: advanced
5510 
5511 .keywords: TS, equation type
5512 
5513 .seealso: TSGetEquationType(), TSEquationType
5514 @*/
5515 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
5516 {
5517   PetscFunctionBegin;
5518   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5519   ts->equation_type = equation_type;
5520   PetscFunctionReturn(0);
5521 }
5522 
5523 /*@
5524    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
5525 
5526    Not Collective
5527 
5528    Input Parameter:
5529 .  ts - the TS context
5530 
5531    Output Parameter:
5532 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5533             manual pages for the individual convergence tests for complete lists
5534 
5535    Level: beginner
5536 
5537    Notes:
5538    Can only be called after the call to TSSolve() is complete.
5539 
5540 .keywords: TS, nonlinear, set, convergence, test
5541 
5542 .seealso: TSSetConvergenceTest(), TSConvergedReason
5543 @*/
5544 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
5545 {
5546   PetscFunctionBegin;
5547   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5548   PetscValidPointer(reason,2);
5549   *reason = ts->reason;
5550   PetscFunctionReturn(0);
5551 }
5552 
5553 /*@
5554    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
5555 
5556    Not Collective
5557 
5558    Input Parameter:
5559 +  ts - the TS context
5560 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5561             manual pages for the individual convergence tests for complete lists
5562 
5563    Level: advanced
5564 
5565    Notes:
5566    Can only be called during TSSolve() is active.
5567 
5568 .keywords: TS, nonlinear, set, convergence, test
5569 
5570 .seealso: TSConvergedReason
5571 @*/
5572 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
5573 {
5574   PetscFunctionBegin;
5575   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5576   ts->reason = reason;
5577   PetscFunctionReturn(0);
5578 }
5579 
5580 /*@
5581    TSGetSolveTime - Gets the time after a call to TSSolve()
5582 
5583    Not Collective
5584 
5585    Input Parameter:
5586 .  ts - the TS context
5587 
5588    Output Parameter:
5589 .  ftime - the final time. This time corresponds to the final time set with TSSetDuration()
5590 
5591    Level: beginner
5592 
5593    Notes:
5594    Can only be called after the call to TSSolve() is complete.
5595 
5596 .keywords: TS, nonlinear, set, convergence, test
5597 
5598 .seealso: TSSetConvergenceTest(), TSConvergedReason
5599 @*/
5600 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
5601 {
5602   PetscFunctionBegin;
5603   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5604   PetscValidPointer(ftime,2);
5605   *ftime = ts->solvetime;
5606   PetscFunctionReturn(0);
5607 }
5608 
5609 /*@
5610    TSGetSNESIterations - Gets the total number of nonlinear iterations
5611    used by the time integrator.
5612 
5613    Not Collective
5614 
5615    Input Parameter:
5616 .  ts - TS context
5617 
5618    Output Parameter:
5619 .  nits - number of nonlinear iterations
5620 
5621    Notes:
5622    This counter is reset to zero for each successive call to TSSolve().
5623 
5624    Level: intermediate
5625 
5626 .keywords: TS, get, number, nonlinear, iterations
5627 
5628 .seealso:  TSGetKSPIterations()
5629 @*/
5630 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
5631 {
5632   PetscFunctionBegin;
5633   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5634   PetscValidIntPointer(nits,2);
5635   *nits = ts->snes_its;
5636   PetscFunctionReturn(0);
5637 }
5638 
5639 /*@
5640    TSGetKSPIterations - Gets the total number of linear iterations
5641    used by the time integrator.
5642 
5643    Not Collective
5644 
5645    Input Parameter:
5646 .  ts - TS context
5647 
5648    Output Parameter:
5649 .  lits - number of linear iterations
5650 
5651    Notes:
5652    This counter is reset to zero for each successive call to TSSolve().
5653 
5654    Level: intermediate
5655 
5656 .keywords: TS, get, number, linear, iterations
5657 
5658 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
5659 @*/
5660 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
5661 {
5662   PetscFunctionBegin;
5663   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5664   PetscValidIntPointer(lits,2);
5665   *lits = ts->ksp_its;
5666   PetscFunctionReturn(0);
5667 }
5668 
5669 /*@
5670    TSGetStepRejections - Gets the total number of rejected steps.
5671 
5672    Not Collective
5673 
5674    Input Parameter:
5675 .  ts - TS context
5676 
5677    Output Parameter:
5678 .  rejects - number of steps rejected
5679 
5680    Notes:
5681    This counter is reset to zero for each successive call to TSSolve().
5682 
5683    Level: intermediate
5684 
5685 .keywords: TS, get, number
5686 
5687 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
5688 @*/
5689 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
5690 {
5691   PetscFunctionBegin;
5692   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5693   PetscValidIntPointer(rejects,2);
5694   *rejects = ts->reject;
5695   PetscFunctionReturn(0);
5696 }
5697 
5698 /*@
5699    TSGetSNESFailures - Gets the total number of failed SNES solves
5700 
5701    Not Collective
5702 
5703    Input Parameter:
5704 .  ts - TS context
5705 
5706    Output Parameter:
5707 .  fails - number of failed nonlinear solves
5708 
5709    Notes:
5710    This counter is reset to zero for each successive call to TSSolve().
5711 
5712    Level: intermediate
5713 
5714 .keywords: TS, get, number
5715 
5716 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
5717 @*/
5718 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
5719 {
5720   PetscFunctionBegin;
5721   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5722   PetscValidIntPointer(fails,2);
5723   *fails = ts->num_snes_failures;
5724   PetscFunctionReturn(0);
5725 }
5726 
5727 /*@
5728    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
5729 
5730    Not Collective
5731 
5732    Input Parameter:
5733 +  ts - TS context
5734 -  rejects - maximum number of rejected steps, pass -1 for unlimited
5735 
5736    Notes:
5737    The counter is reset to zero for each step
5738 
5739    Options Database Key:
5740  .  -ts_max_reject - Maximum number of step rejections before a step fails
5741 
5742    Level: intermediate
5743 
5744 .keywords: TS, set, maximum, number
5745 
5746 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5747 @*/
5748 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
5749 {
5750   PetscFunctionBegin;
5751   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5752   ts->max_reject = rejects;
5753   PetscFunctionReturn(0);
5754 }
5755 
5756 /*@
5757    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
5758 
5759    Not Collective
5760 
5761    Input Parameter:
5762 +  ts - TS context
5763 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
5764 
5765    Notes:
5766    The counter is reset to zero for each successive call to TSSolve().
5767 
5768    Options Database Key:
5769  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
5770 
5771    Level: intermediate
5772 
5773 .keywords: TS, set, maximum, number
5774 
5775 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
5776 @*/
5777 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
5778 {
5779   PetscFunctionBegin;
5780   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5781   ts->max_snes_failures = fails;
5782   PetscFunctionReturn(0);
5783 }
5784 
5785 /*@
5786    TSSetErrorIfStepFails - Error if no step succeeds
5787 
5788    Not Collective
5789 
5790    Input Parameter:
5791 +  ts - TS context
5792 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
5793 
5794    Options Database Key:
5795  .  -ts_error_if_step_fails - Error if no step succeeds
5796 
5797    Level: intermediate
5798 
5799 .keywords: TS, set, error
5800 
5801 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5802 @*/
5803 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
5804 {
5805   PetscFunctionBegin;
5806   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5807   ts->errorifstepfailed = err;
5808   PetscFunctionReturn(0);
5809 }
5810 
5811 /*@C
5812    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
5813 
5814    Collective on TS
5815 
5816    Input Parameters:
5817 +  ts - the TS context
5818 .  step - current time-step
5819 .  ptime - current time
5820 .  u - current state
5821 -  vf - viewer and its format
5822 
5823    Level: intermediate
5824 
5825 .keywords: TS,  vector, monitor, view
5826 
5827 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5828 @*/
5829 PetscErrorCode  TSMonitorSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
5830 {
5831   PetscErrorCode ierr;
5832 
5833   PetscFunctionBegin;
5834   ierr = PetscViewerPushFormat(vf->viewer,vf->format);CHKERRQ(ierr);
5835   ierr = VecView(u,vf->viewer);CHKERRQ(ierr);
5836   ierr = PetscViewerPopFormat(vf->viewer);CHKERRQ(ierr);
5837   PetscFunctionReturn(0);
5838 }
5839 
5840 /*@C
5841    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
5842 
5843    Collective on TS
5844 
5845    Input Parameters:
5846 +  ts - the TS context
5847 .  step - current time-step
5848 .  ptime - current time
5849 .  u - current state
5850 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5851 
5852    Level: intermediate
5853 
5854    Notes:
5855    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.
5856    These are named according to the file name template.
5857 
5858    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
5859 
5860 .keywords: TS,  vector, monitor, view
5861 
5862 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5863 @*/
5864 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
5865 {
5866   PetscErrorCode ierr;
5867   char           filename[PETSC_MAX_PATH_LEN];
5868   PetscViewer    viewer;
5869 
5870   PetscFunctionBegin;
5871   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
5872   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
5873   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
5874   ierr = VecView(u,viewer);CHKERRQ(ierr);
5875   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5876   PetscFunctionReturn(0);
5877 }
5878 
5879 /*@C
5880    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
5881 
5882    Collective on TS
5883 
5884    Input Parameters:
5885 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5886 
5887    Level: intermediate
5888 
5889    Note:
5890    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
5891 
5892 .keywords: TS,  vector, monitor, view
5893 
5894 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
5895 @*/
5896 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
5897 {
5898   PetscErrorCode ierr;
5899 
5900   PetscFunctionBegin;
5901   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
5902   PetscFunctionReturn(0);
5903 }
5904 
5905 /*@
5906    TSGetAdapt - Get the adaptive controller context for the current method
5907 
5908    Collective on TS if controller has not been created yet
5909 
5910    Input Arguments:
5911 .  ts - time stepping context
5912 
5913    Output Arguments:
5914 .  adapt - adaptive controller
5915 
5916    Level: intermediate
5917 
5918 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
5919 @*/
5920 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
5921 {
5922   PetscErrorCode ierr;
5923 
5924   PetscFunctionBegin;
5925   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5926   PetscValidPointer(adapt,2);
5927   if (!ts->adapt) {
5928     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
5929     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt);CHKERRQ(ierr);
5930     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
5931   }
5932   *adapt = ts->adapt;
5933   PetscFunctionReturn(0);
5934 }
5935 
5936 /*@
5937    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
5938 
5939    Logically Collective
5940 
5941    Input Arguments:
5942 +  ts - time integration context
5943 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
5944 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
5945 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
5946 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
5947 
5948    Options Database keys:
5949 +  -ts_rtol <rtol> - relative tolerance for local truncation error
5950 -  -ts_atol <atol> Absolute tolerance for local truncation error
5951 
5952    Notes:
5953    With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5954    (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5955    computed only for the differential or the algebraic part then this can be done using the vector of
5956    tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5957    differential part and infinity for the algebraic part, the LTE calculation will include only the
5958    differential variables.
5959 
5960    Level: beginner
5961 
5962 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
5963 @*/
5964 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
5965 {
5966   PetscErrorCode ierr;
5967 
5968   PetscFunctionBegin;
5969   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
5970   if (vatol) {
5971     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
5972     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
5973     ts->vatol = vatol;
5974   }
5975   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
5976   if (vrtol) {
5977     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
5978     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
5979     ts->vrtol = vrtol;
5980   }
5981   PetscFunctionReturn(0);
5982 }
5983 
5984 /*@
5985    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
5986 
5987    Logically Collective
5988 
5989    Input Arguments:
5990 .  ts - time integration context
5991 
5992    Output Arguments:
5993 +  atol - scalar absolute tolerances, NULL to ignore
5994 .  vatol - vector of absolute tolerances, NULL to ignore
5995 .  rtol - scalar relative tolerances, NULL to ignore
5996 -  vrtol - vector of relative tolerances, NULL to ignore
5997 
5998    Level: beginner
5999 
6000 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
6001 @*/
6002 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
6003 {
6004   PetscFunctionBegin;
6005   if (atol)  *atol  = ts->atol;
6006   if (vatol) *vatol = ts->vatol;
6007   if (rtol)  *rtol  = ts->rtol;
6008   if (vrtol) *vrtol = ts->vrtol;
6009   PetscFunctionReturn(0);
6010 }
6011 
6012 /*@
6013    TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors
6014 
6015    Collective on TS
6016 
6017    Input Arguments:
6018 +  ts - time stepping context
6019 .  U - state vector, usually ts->vec_sol
6020 -  Y - state vector to be compared to U
6021 
6022    Output Arguments:
6023 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6024 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6025 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6026 
6027    Level: developer
6028 
6029 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNormInfinity()
6030 @*/
6031 PetscErrorCode TSErrorWeightedNorm2(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6032 {
6033   PetscErrorCode    ierr;
6034   PetscInt          i,n,N,rstart;
6035   PetscInt          n_loc,na_loc,nr_loc;
6036   PetscReal         n_glb,na_glb,nr_glb;
6037   const PetscScalar *u,*y;
6038   PetscReal         sum,suma,sumr,gsum,gsuma,gsumr,diff;
6039   PetscReal         tol,tola,tolr;
6040   PetscReal         err_loc[6],err_glb[6];
6041 
6042   PetscFunctionBegin;
6043   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6044   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
6045   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
6046   PetscValidType(U,2);
6047   PetscValidType(Y,3);
6048   PetscCheckSameComm(U,2,Y,3);
6049   PetscValidPointer(norm,4);
6050   PetscValidPointer(norma,5);
6051   PetscValidPointer(normr,6);
6052   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
6053 
6054   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
6055   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
6056   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
6057   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6058   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6059   sum  = 0.; n_loc  = 0;
6060   suma = 0.; na_loc = 0;
6061   sumr = 0.; nr_loc = 0;
6062   if (ts->vatol && ts->vrtol) {
6063     const PetscScalar *atol,*rtol;
6064     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6065     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6066     for (i=0; i<n; i++) {
6067       diff = PetscAbsScalar(y[i] - u[i]);
6068       tola = PetscRealPart(atol[i]);
6069       if(tola>0.){
6070         suma  += PetscSqr(diff/tola);
6071         na_loc++;
6072       }
6073       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6074       if(tolr>0.){
6075         sumr  += PetscSqr(diff/tolr);
6076         nr_loc++;
6077       }
6078       tol=tola+tolr;
6079       if(tol>0.){
6080         sum  += PetscSqr(diff/tol);
6081         n_loc++;
6082       }
6083     }
6084     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6085     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6086   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6087     const PetscScalar *atol;
6088     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6089     for (i=0; i<n; i++) {
6090       diff = PetscAbsScalar(y[i] - u[i]);
6091       tola = PetscRealPart(atol[i]);
6092       if(tola>0.){
6093         suma  += PetscSqr(diff/tola);
6094         na_loc++;
6095       }
6096       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6097       if(tolr>0.){
6098         sumr  += PetscSqr(diff/tolr);
6099         nr_loc++;
6100       }
6101       tol=tola+tolr;
6102       if(tol>0.){
6103         sum  += PetscSqr(diff/tol);
6104         n_loc++;
6105       }
6106     }
6107     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6108   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6109     const PetscScalar *rtol;
6110     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6111     for (i=0; i<n; i++) {
6112       diff = PetscAbsScalar(y[i] - u[i]);
6113       tola = ts->atol;
6114       if(tola>0.){
6115         suma  += PetscSqr(diff/tola);
6116         na_loc++;
6117       }
6118       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6119       if(tolr>0.){
6120         sumr  += PetscSqr(diff/tolr);
6121         nr_loc++;
6122       }
6123       tol=tola+tolr;
6124       if(tol>0.){
6125         sum  += PetscSqr(diff/tol);
6126         n_loc++;
6127       }
6128     }
6129     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6130   } else {                      /* scalar atol, scalar rtol */
6131     for (i=0; i<n; i++) {
6132       diff = PetscAbsScalar(y[i] - u[i]);
6133      tola = ts->atol;
6134       if(tola>0.){
6135         suma  += PetscSqr(diff/tola);
6136         na_loc++;
6137       }
6138       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6139       if(tolr>0.){
6140         sumr  += PetscSqr(diff/tolr);
6141         nr_loc++;
6142       }
6143       tol=tola+tolr;
6144       if(tol>0.){
6145         sum  += PetscSqr(diff/tol);
6146         n_loc++;
6147       }
6148     }
6149   }
6150   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6151   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6152 
6153   err_loc[0] = sum;
6154   err_loc[1] = suma;
6155   err_loc[2] = sumr;
6156   err_loc[3] = (PetscReal)n_loc;
6157   err_loc[4] = (PetscReal)na_loc;
6158   err_loc[5] = (PetscReal)nr_loc;
6159 
6160   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6161 
6162   gsum   = err_glb[0];
6163   gsuma  = err_glb[1];
6164   gsumr  = err_glb[2];
6165   n_glb  = err_glb[3];
6166   na_glb = err_glb[4];
6167   nr_glb = err_glb[5];
6168 
6169   *norm  = 0.;
6170   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
6171   *norma = 0.;
6172   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
6173   *normr = 0.;
6174   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
6175 
6176   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6177   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6178   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6179   PetscFunctionReturn(0);
6180 }
6181 
6182 /*@
6183    TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors
6184 
6185    Collective on TS
6186 
6187    Input Arguments:
6188 +  ts - time stepping context
6189 .  U - state vector, usually ts->vec_sol
6190 -  Y - state vector to be compared to U
6191 
6192    Output Arguments:
6193 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6194 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6195 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6196 
6197    Level: developer
6198 
6199 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNorm2()
6200 @*/
6201 PetscErrorCode TSErrorWeightedNormInfinity(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6202 {
6203   PetscErrorCode    ierr;
6204   PetscInt          i,n,N,rstart;
6205   const PetscScalar *u,*y;
6206   PetscReal         max,gmax,maxa,gmaxa,maxr,gmaxr;
6207   PetscReal         tol,tola,tolr,diff;
6208   PetscReal         err_loc[3],err_glb[3];
6209 
6210   PetscFunctionBegin;
6211   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6212   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
6213   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
6214   PetscValidType(U,2);
6215   PetscValidType(Y,3);
6216   PetscCheckSameComm(U,2,Y,3);
6217   PetscValidPointer(norm,4);
6218   PetscValidPointer(norma,5);
6219   PetscValidPointer(normr,6);
6220   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
6221 
6222   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
6223   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
6224   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
6225   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6226   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6227 
6228   max=0.;
6229   maxa=0.;
6230   maxr=0.;
6231 
6232   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
6233     const PetscScalar *atol,*rtol;
6234     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6235     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6236 
6237     for (i=0; i<n; i++) {
6238       diff = PetscAbsScalar(y[i] - u[i]);
6239       tola = PetscRealPart(atol[i]);
6240       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6241       tol  = tola+tolr;
6242       if(tola>0.){
6243         maxa = PetscMax(maxa,diff / tola);
6244       }
6245       if(tolr>0.){
6246         maxr = PetscMax(maxr,diff / tolr);
6247       }
6248       if(tol>0.){
6249         max = PetscMax(max,diff / tol);
6250       }
6251     }
6252     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6253     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6254   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6255     const PetscScalar *atol;
6256     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6257     for (i=0; i<n; i++) {
6258       diff = PetscAbsScalar(y[i] - u[i]);
6259       tola = PetscRealPart(atol[i]);
6260       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6261       tol  = tola+tolr;
6262       if(tola>0.){
6263         maxa = PetscMax(maxa,diff / tola);
6264       }
6265       if(tolr>0.){
6266         maxr = PetscMax(maxr,diff / tolr);
6267       }
6268       if(tol>0.){
6269         max = PetscMax(max,diff / tol);
6270       }
6271     }
6272     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6273   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6274     const PetscScalar *rtol;
6275     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6276 
6277     for (i=0; i<n; i++) {
6278       diff = PetscAbsScalar(y[i] - u[i]);
6279       tola = ts->atol;
6280       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6281       tol  = tola+tolr;
6282       if(tola>0.){
6283         maxa = PetscMax(maxa,diff / tola);
6284       }
6285       if(tolr>0.){
6286         maxr = PetscMax(maxr,diff / tolr);
6287       }
6288       if(tol>0.){
6289         max = PetscMax(max,diff / tol);
6290       }
6291     }
6292     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6293   } else {                      /* scalar atol, scalar rtol */
6294 
6295     for (i=0; i<n; i++) {
6296       diff = PetscAbsScalar(y[i] - u[i]);
6297       tola = ts->atol;
6298       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6299       tol  = tola+tolr;
6300       if(tola>0.){
6301         maxa = PetscMax(maxa,diff / tola);
6302       }
6303       if(tolr>0.){
6304         maxr = PetscMax(maxr,diff / tolr);
6305       }
6306       if(tol>0.){
6307         max = PetscMax(max,diff / tol);
6308       }
6309     }
6310   }
6311   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6312   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6313   err_loc[0] = max;
6314   err_loc[1] = maxa;
6315   err_loc[2] = maxr;
6316   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6317   gmax   = err_glb[0];
6318   gmaxa  = err_glb[1];
6319   gmaxr  = err_glb[2];
6320 
6321   *norm = gmax;
6322   *norma = gmaxa;
6323   *normr = gmaxr;
6324   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6325     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6326     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6327   PetscFunctionReturn(0);
6328 }
6329 
6330 /*@
6331    TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
6332 
6333    Collective on TS
6334 
6335    Input Arguments:
6336 +  ts - time stepping context
6337 .  U - state vector, usually ts->vec_sol
6338 .  Y - state vector to be compared to U
6339 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6340 
6341    Output Arguments:
6342 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6343 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6344 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6345 
6346    Options Database Keys:
6347 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6348 
6349    Level: developer
6350 
6351 .seealso: TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2(), TSErrorWeightedENorm
6352 @*/
6353 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6354 {
6355   PetscErrorCode ierr;
6356 
6357   PetscFunctionBegin;
6358   if (wnormtype == NORM_2) {
6359     ierr = TSErrorWeightedNorm2(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
6360   } else if(wnormtype == NORM_INFINITY) {
6361     ierr = TSErrorWeightedNormInfinity(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
6362   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6363   PetscFunctionReturn(0);
6364 }
6365 
6366 
6367 /*@
6368    TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances
6369 
6370    Collective on TS
6371 
6372    Input Arguments:
6373 +  ts - time stepping context
6374 .  E - error vector
6375 .  U - state vector, usually ts->vec_sol
6376 -  Y - state vector, previous time step
6377 
6378    Output Arguments:
6379 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6380 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6381 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6382 
6383    Level: developer
6384 
6385 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENormInfinity()
6386 @*/
6387 PetscErrorCode TSErrorWeightedENorm2(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6388 {
6389   PetscErrorCode    ierr;
6390   PetscInt          i,n,N,rstart;
6391   PetscInt          n_loc,na_loc,nr_loc;
6392   PetscReal         n_glb,na_glb,nr_glb;
6393   const PetscScalar *e,*u,*y;
6394   PetscReal         err,sum,suma,sumr,gsum,gsuma,gsumr;
6395   PetscReal         tol,tola,tolr;
6396   PetscReal         err_loc[6],err_glb[6];
6397 
6398   PetscFunctionBegin;
6399   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6400   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
6401   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
6402   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
6403   PetscValidType(E,2);
6404   PetscValidType(U,3);
6405   PetscValidType(Y,4);
6406   PetscCheckSameComm(E,2,U,3);
6407   PetscCheckSameComm(U,2,Y,3);
6408   PetscValidPointer(norm,5);
6409   PetscValidPointer(norma,6);
6410   PetscValidPointer(normr,7);
6411 
6412   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
6413   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
6414   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
6415   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
6416   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6417   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6418   sum  = 0.; n_loc  = 0;
6419   suma = 0.; na_loc = 0;
6420   sumr = 0.; nr_loc = 0;
6421   if (ts->vatol && ts->vrtol) {
6422     const PetscScalar *atol,*rtol;
6423     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6424     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6425     for (i=0; i<n; i++) {
6426       err = PetscAbsScalar(e[i]);
6427       tola = PetscRealPart(atol[i]);
6428       if(tola>0.){
6429         suma  += PetscSqr(err/tola);
6430         na_loc++;
6431       }
6432       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6433       if(tolr>0.){
6434         sumr  += PetscSqr(err/tolr);
6435         nr_loc++;
6436       }
6437       tol=tola+tolr;
6438       if(tol>0.){
6439         sum  += PetscSqr(err/tol);
6440         n_loc++;
6441       }
6442     }
6443     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6444     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6445   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6446     const PetscScalar *atol;
6447     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6448     for (i=0; i<n; i++) {
6449       err = PetscAbsScalar(e[i]);
6450       tola = PetscRealPart(atol[i]);
6451       if(tola>0.){
6452         suma  += PetscSqr(err/tola);
6453         na_loc++;
6454       }
6455       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6456       if(tolr>0.){
6457         sumr  += PetscSqr(err/tolr);
6458         nr_loc++;
6459       }
6460       tol=tola+tolr;
6461       if(tol>0.){
6462         sum  += PetscSqr(err/tol);
6463         n_loc++;
6464       }
6465     }
6466     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6467   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6468     const PetscScalar *rtol;
6469     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6470     for (i=0; i<n; i++) {
6471       err = PetscAbsScalar(e[i]);
6472       tola = ts->atol;
6473       if(tola>0.){
6474         suma  += PetscSqr(err/tola);
6475         na_loc++;
6476       }
6477       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6478       if(tolr>0.){
6479         sumr  += PetscSqr(err/tolr);
6480         nr_loc++;
6481       }
6482       tol=tola+tolr;
6483       if(tol>0.){
6484         sum  += PetscSqr(err/tol);
6485         n_loc++;
6486       }
6487     }
6488     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6489   } else {                      /* scalar atol, scalar rtol */
6490     for (i=0; i<n; i++) {
6491       err = PetscAbsScalar(e[i]);
6492      tola = ts->atol;
6493       if(tola>0.){
6494         suma  += PetscSqr(err/tola);
6495         na_loc++;
6496       }
6497       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6498       if(tolr>0.){
6499         sumr  += PetscSqr(err/tolr);
6500         nr_loc++;
6501       }
6502       tol=tola+tolr;
6503       if(tol>0.){
6504         sum  += PetscSqr(err/tol);
6505         n_loc++;
6506       }
6507     }
6508   }
6509   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6510   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6511   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6512 
6513   err_loc[0] = sum;
6514   err_loc[1] = suma;
6515   err_loc[2] = sumr;
6516   err_loc[3] = (PetscReal)n_loc;
6517   err_loc[4] = (PetscReal)na_loc;
6518   err_loc[5] = (PetscReal)nr_loc;
6519 
6520   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6521 
6522   gsum   = err_glb[0];
6523   gsuma  = err_glb[1];
6524   gsumr  = err_glb[2];
6525   n_glb  = err_glb[3];
6526   na_glb = err_glb[4];
6527   nr_glb = err_glb[5];
6528 
6529   *norm  = 0.;
6530   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
6531   *norma = 0.;
6532   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
6533   *normr = 0.;
6534   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
6535 
6536   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6537   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6538   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6539   PetscFunctionReturn(0);
6540 }
6541 
6542 /*@
6543    TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances
6544    Collective on TS
6545 
6546    Input Arguments:
6547 +  ts - time stepping context
6548 .  E - error vector
6549 .  U - state vector, usually ts->vec_sol
6550 -  Y - state vector, previous time step
6551 
6552    Output Arguments:
6553 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6554 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6555 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6556 
6557    Level: developer
6558 
6559 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENorm2()
6560 @*/
6561 PetscErrorCode TSErrorWeightedENormInfinity(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6562 {
6563   PetscErrorCode    ierr;
6564   PetscInt          i,n,N,rstart;
6565   const PetscScalar *e,*u,*y;
6566   PetscReal         err,max,gmax,maxa,gmaxa,maxr,gmaxr;
6567   PetscReal         tol,tola,tolr;
6568   PetscReal         err_loc[3],err_glb[3];
6569 
6570   PetscFunctionBegin;
6571   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6572   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
6573   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
6574   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
6575   PetscValidType(E,2);
6576   PetscValidType(U,3);
6577   PetscValidType(Y,4);
6578   PetscCheckSameComm(E,2,U,3);
6579   PetscCheckSameComm(U,2,Y,3);
6580   PetscValidPointer(norm,5);
6581   PetscValidPointer(norma,6);
6582   PetscValidPointer(normr,7);
6583 
6584   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
6585   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
6586   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
6587   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
6588   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6589   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6590 
6591   max=0.;
6592   maxa=0.;
6593   maxr=0.;
6594 
6595   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
6596     const PetscScalar *atol,*rtol;
6597     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6598     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6599 
6600     for (i=0; i<n; i++) {
6601       err = PetscAbsScalar(e[i]);
6602       tola = PetscRealPart(atol[i]);
6603       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6604       tol  = tola+tolr;
6605       if(tola>0.){
6606         maxa = PetscMax(maxa,err / tola);
6607       }
6608       if(tolr>0.){
6609         maxr = PetscMax(maxr,err / tolr);
6610       }
6611       if(tol>0.){
6612         max = PetscMax(max,err / tol);
6613       }
6614     }
6615     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6616     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6617   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6618     const PetscScalar *atol;
6619     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6620     for (i=0; i<n; i++) {
6621       err = PetscAbsScalar(e[i]);
6622       tola = PetscRealPart(atol[i]);
6623       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6624       tol  = tola+tolr;
6625       if(tola>0.){
6626         maxa = PetscMax(maxa,err / tola);
6627       }
6628       if(tolr>0.){
6629         maxr = PetscMax(maxr,err / tolr);
6630       }
6631       if(tol>0.){
6632         max = PetscMax(max,err / tol);
6633       }
6634     }
6635     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6636   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6637     const PetscScalar *rtol;
6638     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6639 
6640     for (i=0; i<n; i++) {
6641       err = PetscAbsScalar(e[i]);
6642       tola = ts->atol;
6643       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6644       tol  = tola+tolr;
6645       if(tola>0.){
6646         maxa = PetscMax(maxa,err / tola);
6647       }
6648       if(tolr>0.){
6649         maxr = PetscMax(maxr,err / tolr);
6650       }
6651       if(tol>0.){
6652         max = PetscMax(max,err / tol);
6653       }
6654     }
6655     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6656   } else {                      /* scalar atol, scalar rtol */
6657 
6658     for (i=0; i<n; i++) {
6659       err = PetscAbsScalar(e[i]);
6660       tola = ts->atol;
6661       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6662       tol  = tola+tolr;
6663       if(tola>0.){
6664         maxa = PetscMax(maxa,err / tola);
6665       }
6666       if(tolr>0.){
6667         maxr = PetscMax(maxr,err / tolr);
6668       }
6669       if(tol>0.){
6670         max = PetscMax(max,err / tol);
6671       }
6672     }
6673   }
6674   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6675   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6676   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6677   err_loc[0] = max;
6678   err_loc[1] = maxa;
6679   err_loc[2] = maxr;
6680   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6681   gmax   = err_glb[0];
6682   gmaxa  = err_glb[1];
6683   gmaxr  = err_glb[2];
6684 
6685   *norm = gmax;
6686   *norma = gmaxa;
6687   *normr = gmaxr;
6688   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6689     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6690     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6691   PetscFunctionReturn(0);
6692 }
6693 
6694 /*@
6695    TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
6696 
6697    Collective on TS
6698 
6699    Input Arguments:
6700 +  ts - time stepping context
6701 .  E - error vector
6702 .  U - state vector, usually ts->vec_sol
6703 .  Y - state vector, previous time step
6704 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6705 
6706    Output Arguments:
6707 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6708 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6709 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6710 
6711    Options Database Keys:
6712 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6713 
6714    Level: developer
6715 
6716 .seealso: TSErrorWeightedENormInfinity(), TSErrorWeightedENorm2(), TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2()
6717 @*/
6718 PetscErrorCode TSErrorWeightedENorm(TS ts,Vec E,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6719 {
6720   PetscErrorCode ierr;
6721 
6722   PetscFunctionBegin;
6723   if (wnormtype == NORM_2) {
6724     ierr = TSErrorWeightedENorm2(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6725   } else if(wnormtype == NORM_INFINITY) {
6726     ierr = TSErrorWeightedENormInfinity(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6727   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6728   PetscFunctionReturn(0);
6729 }
6730 
6731 
6732 /*@
6733    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
6734 
6735    Logically Collective on TS
6736 
6737    Input Arguments:
6738 +  ts - time stepping context
6739 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
6740 
6741    Note:
6742    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
6743 
6744    Level: intermediate
6745 
6746 .seealso: TSGetCFLTime(), TSADAPTCFL
6747 @*/
6748 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
6749 {
6750   PetscFunctionBegin;
6751   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6752   ts->cfltime_local = cfltime;
6753   ts->cfltime       = -1.;
6754   PetscFunctionReturn(0);
6755 }
6756 
6757 /*@
6758    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
6759 
6760    Collective on TS
6761 
6762    Input Arguments:
6763 .  ts - time stepping context
6764 
6765    Output Arguments:
6766 .  cfltime - maximum stable time step for forward Euler
6767 
6768    Level: advanced
6769 
6770 .seealso: TSSetCFLTimeLocal()
6771 @*/
6772 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
6773 {
6774   PetscErrorCode ierr;
6775 
6776   PetscFunctionBegin;
6777   if (ts->cfltime < 0) {
6778     ierr = MPIU_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6779   }
6780   *cfltime = ts->cfltime;
6781   PetscFunctionReturn(0);
6782 }
6783 
6784 /*@
6785    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
6786 
6787    Input Parameters:
6788 .  ts   - the TS context.
6789 .  xl   - lower bound.
6790 .  xu   - upper bound.
6791 
6792    Notes:
6793    If this routine is not called then the lower and upper bounds are set to
6794    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
6795 
6796    Level: advanced
6797 
6798 @*/
6799 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
6800 {
6801   PetscErrorCode ierr;
6802   SNES           snes;
6803 
6804   PetscFunctionBegin;
6805   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
6806   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
6807   PetscFunctionReturn(0);
6808 }
6809 
6810 #if defined(PETSC_HAVE_MATLAB_ENGINE)
6811 #include <mex.h>
6812 
6813 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
6814 
6815 /*
6816    TSComputeFunction_Matlab - Calls the function that has been set with
6817                          TSSetFunctionMatlab().
6818 
6819    Collective on TS
6820 
6821    Input Parameters:
6822 +  snes - the TS context
6823 -  u - input vector
6824 
6825    Output Parameter:
6826 .  y - function vector, as set by TSSetFunction()
6827 
6828    Notes:
6829    TSComputeFunction() is typically used within nonlinear solvers
6830    implementations, so most users would not generally call this routine
6831    themselves.
6832 
6833    Level: developer
6834 
6835 .keywords: TS, nonlinear, compute, function
6836 
6837 .seealso: TSSetFunction(), TSGetFunction()
6838 */
6839 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
6840 {
6841   PetscErrorCode  ierr;
6842   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6843   int             nlhs  = 1,nrhs = 7;
6844   mxArray         *plhs[1],*prhs[7];
6845   long long int   lx = 0,lxdot = 0,ly = 0,ls = 0;
6846 
6847   PetscFunctionBegin;
6848   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
6849   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
6850   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
6851   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
6852   PetscCheckSameComm(snes,1,u,3);
6853   PetscCheckSameComm(snes,1,y,5);
6854 
6855   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
6856   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6857   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
6858   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
6859 
6860   prhs[0] =  mxCreateDoubleScalar((double)ls);
6861   prhs[1] =  mxCreateDoubleScalar(time);
6862   prhs[2] =  mxCreateDoubleScalar((double)lx);
6863   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
6864   prhs[4] =  mxCreateDoubleScalar((double)ly);
6865   prhs[5] =  mxCreateString(sctx->funcname);
6866   prhs[6] =  sctx->ctx;
6867   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
6868   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6869   mxDestroyArray(prhs[0]);
6870   mxDestroyArray(prhs[1]);
6871   mxDestroyArray(prhs[2]);
6872   mxDestroyArray(prhs[3]);
6873   mxDestroyArray(prhs[4]);
6874   mxDestroyArray(prhs[5]);
6875   mxDestroyArray(plhs[0]);
6876   PetscFunctionReturn(0);
6877 }
6878 
6879 /*
6880    TSSetFunctionMatlab - Sets the function evaluation routine and function
6881    vector for use by the TS routines in solving ODEs
6882    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
6883 
6884    Logically Collective on TS
6885 
6886    Input Parameters:
6887 +  ts - the TS context
6888 -  func - function evaluation routine
6889 
6890    Calling sequence of func:
6891 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
6892 
6893    Level: beginner
6894 
6895 .keywords: TS, nonlinear, set, function
6896 
6897 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6898 */
6899 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
6900 {
6901   PetscErrorCode  ierr;
6902   TSMatlabContext *sctx;
6903 
6904   PetscFunctionBegin;
6905   /* currently sctx is memory bleed */
6906   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6907   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6908   /*
6909      This should work, but it doesn't
6910   sctx->ctx = ctx;
6911   mexMakeArrayPersistent(sctx->ctx);
6912   */
6913   sctx->ctx = mxDuplicateArray(ctx);
6914 
6915   ierr = TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
6916   PetscFunctionReturn(0);
6917 }
6918 
6919 /*
6920    TSComputeJacobian_Matlab - Calls the function that has been set with
6921                          TSSetJacobianMatlab().
6922 
6923    Collective on TS
6924 
6925    Input Parameters:
6926 +  ts - the TS context
6927 .  u - input vector
6928 .  A, B - the matrices
6929 -  ctx - user context
6930 
6931    Level: developer
6932 
6933 .keywords: TS, nonlinear, compute, function
6934 
6935 .seealso: TSSetFunction(), TSGetFunction()
6936 @*/
6937 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat A,Mat B,void *ctx)
6938 {
6939   PetscErrorCode  ierr;
6940   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6941   int             nlhs  = 2,nrhs = 9;
6942   mxArray         *plhs[2],*prhs[9];
6943   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
6944 
6945   PetscFunctionBegin;
6946   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6947   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
6948 
6949   /* call Matlab function in ctx with arguments u and y */
6950 
6951   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
6952   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6953   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
6954   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
6955   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
6956 
6957   prhs[0] =  mxCreateDoubleScalar((double)ls);
6958   prhs[1] =  mxCreateDoubleScalar((double)time);
6959   prhs[2] =  mxCreateDoubleScalar((double)lx);
6960   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
6961   prhs[4] =  mxCreateDoubleScalar((double)shift);
6962   prhs[5] =  mxCreateDoubleScalar((double)lA);
6963   prhs[6] =  mxCreateDoubleScalar((double)lB);
6964   prhs[7] =  mxCreateString(sctx->funcname);
6965   prhs[8] =  sctx->ctx;
6966   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
6967   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6968   mxDestroyArray(prhs[0]);
6969   mxDestroyArray(prhs[1]);
6970   mxDestroyArray(prhs[2]);
6971   mxDestroyArray(prhs[3]);
6972   mxDestroyArray(prhs[4]);
6973   mxDestroyArray(prhs[5]);
6974   mxDestroyArray(prhs[6]);
6975   mxDestroyArray(prhs[7]);
6976   mxDestroyArray(plhs[0]);
6977   mxDestroyArray(plhs[1]);
6978   PetscFunctionReturn(0);
6979 }
6980 
6981 /*
6982    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
6983    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
6984 
6985    Logically Collective on TS
6986 
6987    Input Parameters:
6988 +  ts - the TS context
6989 .  A,B - Jacobian matrices
6990 .  func - function evaluation routine
6991 -  ctx - user context
6992 
6993    Calling sequence of func:
6994 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
6995 
6996    Level: developer
6997 
6998 .keywords: TS, nonlinear, set, function
6999 
7000 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
7001 */
7002 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
7003 {
7004   PetscErrorCode  ierr;
7005   TSMatlabContext *sctx;
7006 
7007   PetscFunctionBegin;
7008   /* currently sctx is memory bleed */
7009   ierr = PetscNew(&sctx);CHKERRQ(ierr);
7010   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
7011   /*
7012      This should work, but it doesn't
7013   sctx->ctx = ctx;
7014   mexMakeArrayPersistent(sctx->ctx);
7015   */
7016   sctx->ctx = mxDuplicateArray(ctx);
7017 
7018   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
7019   PetscFunctionReturn(0);
7020 }
7021 
7022 /*
7023    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
7024 
7025    Collective on TS
7026 
7027 .seealso: TSSetFunction(), TSGetFunction()
7028 @*/
7029 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
7030 {
7031   PetscErrorCode  ierr;
7032   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
7033   int             nlhs  = 1,nrhs = 6;
7034   mxArray         *plhs[1],*prhs[6];
7035   long long int   lx = 0,ls = 0;
7036 
7037   PetscFunctionBegin;
7038   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7039   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
7040 
7041   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
7042   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
7043 
7044   prhs[0] =  mxCreateDoubleScalar((double)ls);
7045   prhs[1] =  mxCreateDoubleScalar((double)it);
7046   prhs[2] =  mxCreateDoubleScalar((double)time);
7047   prhs[3] =  mxCreateDoubleScalar((double)lx);
7048   prhs[4] =  mxCreateString(sctx->funcname);
7049   prhs[5] =  sctx->ctx;
7050   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
7051   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
7052   mxDestroyArray(prhs[0]);
7053   mxDestroyArray(prhs[1]);
7054   mxDestroyArray(prhs[2]);
7055   mxDestroyArray(prhs[3]);
7056   mxDestroyArray(prhs[4]);
7057   mxDestroyArray(plhs[0]);
7058   PetscFunctionReturn(0);
7059 }
7060 
7061 /*
7062    TSMonitorSetMatlab - Sets the monitor function from Matlab
7063 
7064    Level: developer
7065 
7066 .keywords: TS, nonlinear, set, function
7067 
7068 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
7069 */
7070 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
7071 {
7072   PetscErrorCode  ierr;
7073   TSMatlabContext *sctx;
7074 
7075   PetscFunctionBegin;
7076   /* currently sctx is memory bleed */
7077   ierr = PetscNew(&sctx);CHKERRQ(ierr);
7078   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
7079   /*
7080      This should work, but it doesn't
7081   sctx->ctx = ctx;
7082   mexMakeArrayPersistent(sctx->ctx);
7083   */
7084   sctx->ctx = mxDuplicateArray(ctx);
7085 
7086   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);CHKERRQ(ierr);
7087   PetscFunctionReturn(0);
7088 }
7089 #endif
7090 
7091 /*@C
7092    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
7093        in a time based line graph
7094 
7095    Collective on TS
7096 
7097    Input Parameters:
7098 +  ts - the TS context
7099 .  step - current time-step
7100 .  ptime - current time
7101 .  u - current solution
7102 -  dctx - the TSMonitorLGCtx object that contains all the options for the monitoring, this is created with TSMonitorLGCtxCreate()
7103 
7104    Options Database:
7105 .   -ts_monitor_lg_solution_variables
7106 
7107    Level: intermediate
7108 
7109    Notes: Each process in a parallel run displays its component solutions in a separate window
7110 
7111 .keywords: TS,  vector, monitor, view
7112 
7113 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
7114            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
7115            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
7116            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
7117 @*/
7118 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
7119 {
7120   PetscErrorCode    ierr;
7121   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dctx;
7122   const PetscScalar *yy;
7123   Vec               v;
7124 
7125   PetscFunctionBegin;
7126   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7127   if (!step) {
7128     PetscDrawAxis axis;
7129     PetscInt      dim;
7130     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7131     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
7132     if (!ctx->names) {
7133       PetscBool flg;
7134       /* user provides names of variables to plot but no names has been set so assume names are integer values */
7135       ierr = PetscOptionsHasName(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",&flg);CHKERRQ(ierr);
7136       if (flg) {
7137         PetscInt i,n;
7138         char     **names;
7139         ierr = VecGetSize(u,&n);CHKERRQ(ierr);
7140         ierr = PetscMalloc1(n+1,&names);CHKERRQ(ierr);
7141         for (i=0; i<n; i++) {
7142           ierr = PetscMalloc1(5,&names[i]);CHKERRQ(ierr);
7143           ierr = PetscSNPrintf(names[i],5,"%D",i);CHKERRQ(ierr);
7144         }
7145         names[n] = NULL;
7146         ctx->names = names;
7147       }
7148     }
7149     if (ctx->names && !ctx->displaynames) {
7150       char      **displaynames;
7151       PetscBool flg;
7152       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7153       ierr = PetscMalloc1(dim+1,&displaynames);CHKERRQ(ierr);
7154       ierr = PetscMemzero(displaynames,(dim+1)*sizeof(char*));CHKERRQ(ierr);
7155       ierr = PetscOptionsGetStringArray(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",displaynames,&dim,&flg);CHKERRQ(ierr);
7156       if (flg) {
7157         ierr = TSMonitorLGCtxSetDisplayVariables(ctx,(const char *const *)displaynames);CHKERRQ(ierr);
7158       }
7159       ierr = PetscStrArrayDestroy(&displaynames);CHKERRQ(ierr);
7160     }
7161     if (ctx->displaynames) {
7162       ierr = PetscDrawLGSetDimension(ctx->lg,ctx->ndisplayvariables);CHKERRQ(ierr);
7163       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->displaynames);CHKERRQ(ierr);
7164     } else if (ctx->names) {
7165       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7166       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
7167       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->names);CHKERRQ(ierr);
7168     } else {
7169       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7170       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
7171     }
7172     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7173   }
7174 
7175   if (!ctx->transform) v = u;
7176   else {ierr = (*ctx->transform)(ctx->transformctx,u,&v);CHKERRQ(ierr);}
7177   ierr = VecGetArrayRead(v,&yy);CHKERRQ(ierr);
7178   if (ctx->displaynames) {
7179     PetscInt i;
7180     for (i=0; i<ctx->ndisplayvariables; i++)
7181       ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
7182     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,ctx->displayvalues);CHKERRQ(ierr);
7183   } else {
7184 #if defined(PETSC_USE_COMPLEX)
7185     PetscInt  i,n;
7186     PetscReal *yreal;
7187     ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
7188     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
7189     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
7190     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
7191     ierr = PetscFree(yreal);CHKERRQ(ierr);
7192 #else
7193     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
7194 #endif
7195   }
7196   ierr = VecRestoreArrayRead(v,&yy);CHKERRQ(ierr);
7197   if (ctx->transform) {ierr = VecDestroy(&v);CHKERRQ(ierr);}
7198 
7199   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
7200     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7201     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7202   }
7203   PetscFunctionReturn(0);
7204 }
7205 
7206 /*@C
7207    TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
7208 
7209    Collective on TS
7210 
7211    Input Parameters:
7212 +  ts - the TS context
7213 -  names - the names of the components, final string must be NULL
7214 
7215    Level: intermediate
7216 
7217    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7218 
7219 .keywords: TS,  vector, monitor, view
7220 
7221 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetVariableNames()
7222 @*/
7223 PetscErrorCode  TSMonitorLGSetVariableNames(TS ts,const char * const *names)
7224 {
7225   PetscErrorCode    ierr;
7226   PetscInt          i;
7227 
7228   PetscFunctionBegin;
7229   for (i=0; i<ts->numbermonitors; i++) {
7230     if (ts->monitor[i] == TSMonitorLGSolution) {
7231       ierr = TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i],names);CHKERRQ(ierr);
7232       break;
7233     }
7234   }
7235   PetscFunctionReturn(0);
7236 }
7237 
7238 /*@C
7239    TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
7240 
7241    Collective on TS
7242 
7243    Input Parameters:
7244 +  ts - the TS context
7245 -  names - the names of the components, final string must be NULL
7246 
7247    Level: intermediate
7248 
7249 .keywords: TS,  vector, monitor, view
7250 
7251 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGSetVariableNames()
7252 @*/
7253 PetscErrorCode  TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx,const char * const *names)
7254 {
7255   PetscErrorCode    ierr;
7256 
7257   PetscFunctionBegin;
7258   ierr = PetscStrArrayDestroy(&ctx->names);CHKERRQ(ierr);
7259   ierr = PetscStrArrayallocpy(names,&ctx->names);CHKERRQ(ierr);
7260   PetscFunctionReturn(0);
7261 }
7262 
7263 /*@C
7264    TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
7265 
7266    Collective on TS
7267 
7268    Input Parameter:
7269 .  ts - the TS context
7270 
7271    Output Parameter:
7272 .  names - the names of the components, final string must be NULL
7273 
7274    Level: intermediate
7275 
7276    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7277 
7278 .keywords: TS,  vector, monitor, view
7279 
7280 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
7281 @*/
7282 PetscErrorCode  TSMonitorLGGetVariableNames(TS ts,const char *const **names)
7283 {
7284   PetscInt       i;
7285 
7286   PetscFunctionBegin;
7287   *names = NULL;
7288   for (i=0; i<ts->numbermonitors; i++) {
7289     if (ts->monitor[i] == TSMonitorLGSolution) {
7290       TSMonitorLGCtx  ctx = (TSMonitorLGCtx) ts->monitorcontext[i];
7291       *names = (const char *const *)ctx->names;
7292       break;
7293     }
7294   }
7295   PetscFunctionReturn(0);
7296 }
7297 
7298 /*@C
7299    TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
7300 
7301    Collective on TS
7302 
7303    Input Parameters:
7304 +  ctx - the TSMonitorLG context
7305 .  displaynames - the names of the components, final string must be NULL
7306 
7307    Level: intermediate
7308 
7309 .keywords: TS,  vector, monitor, view
7310 
7311 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
7312 @*/
7313 PetscErrorCode  TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx,const char * const *displaynames)
7314 {
7315   PetscInt          j = 0,k;
7316   PetscErrorCode    ierr;
7317 
7318   PetscFunctionBegin;
7319   if (!ctx->names) PetscFunctionReturn(0);
7320   ierr = PetscStrArrayDestroy(&ctx->displaynames);CHKERRQ(ierr);
7321   ierr = PetscStrArrayallocpy(displaynames,&ctx->displaynames);CHKERRQ(ierr);
7322   while (displaynames[j]) j++;
7323   ctx->ndisplayvariables = j;
7324   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvariables);CHKERRQ(ierr);
7325   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvalues);CHKERRQ(ierr);
7326   j = 0;
7327   while (displaynames[j]) {
7328     k = 0;
7329     while (ctx->names[k]) {
7330       PetscBool flg;
7331       ierr = PetscStrcmp(displaynames[j],ctx->names[k],&flg);CHKERRQ(ierr);
7332       if (flg) {
7333         ctx->displayvariables[j] = k;
7334         break;
7335       }
7336       k++;
7337     }
7338     j++;
7339   }
7340   PetscFunctionReturn(0);
7341 }
7342 
7343 /*@C
7344    TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
7345 
7346    Collective on TS
7347 
7348    Input Parameters:
7349 +  ts - the TS context
7350 .  displaynames - the names of the components, final string must be NULL
7351 
7352    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7353 
7354    Level: intermediate
7355 
7356 .keywords: TS,  vector, monitor, view
7357 
7358 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
7359 @*/
7360 PetscErrorCode  TSMonitorLGSetDisplayVariables(TS ts,const char * const *displaynames)
7361 {
7362   PetscInt          i;
7363   PetscErrorCode    ierr;
7364 
7365   PetscFunctionBegin;
7366   for (i=0; i<ts->numbermonitors; i++) {
7367     if (ts->monitor[i] == TSMonitorLGSolution) {
7368       ierr = TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i],displaynames);CHKERRQ(ierr);
7369       break;
7370     }
7371   }
7372   PetscFunctionReturn(0);
7373 }
7374 
7375 /*@C
7376    TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
7377 
7378    Collective on TS
7379 
7380    Input Parameters:
7381 +  ts - the TS context
7382 .  transform - the transform function
7383 .  destroy - function to destroy the optional context
7384 -  ctx - optional context used by transform function
7385 
7386    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7387 
7388    Level: intermediate
7389 
7390 .keywords: TS,  vector, monitor, view
7391 
7392 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGCtxSetTransform()
7393 @*/
7394 PetscErrorCode  TSMonitorLGSetTransform(TS ts,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
7395 {
7396   PetscInt          i;
7397   PetscErrorCode    ierr;
7398 
7399   PetscFunctionBegin;
7400   for (i=0; i<ts->numbermonitors; i++) {
7401     if (ts->monitor[i] == TSMonitorLGSolution) {
7402       ierr = TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i],transform,destroy,tctx);CHKERRQ(ierr);
7403     }
7404   }
7405   PetscFunctionReturn(0);
7406 }
7407 
7408 /*@C
7409    TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
7410 
7411    Collective on TSLGCtx
7412 
7413    Input Parameters:
7414 +  ts - the TS context
7415 .  transform - the transform function
7416 .  destroy - function to destroy the optional context
7417 -  ctx - optional context used by transform function
7418 
7419    Level: intermediate
7420 
7421 .keywords: TS,  vector, monitor, view
7422 
7423 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGSetTransform()
7424 @*/
7425 PetscErrorCode  TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
7426 {
7427   PetscFunctionBegin;
7428   ctx->transform    = transform;
7429   ctx->transformdestroy = destroy;
7430   ctx->transformctx = tctx;
7431   PetscFunctionReturn(0);
7432 }
7433 
7434 /*@C
7435    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the solution vector
7436        in a time based line graph
7437 
7438    Collective on TS
7439 
7440    Input Parameters:
7441 +  ts - the TS context
7442 .  step - current time-step
7443 .  ptime - current time
7444 .  u - current solution
7445 -  dctx - TSMonitorLGCtx object created with TSMonitorLGCtxCreate()
7446 
7447    Level: intermediate
7448 
7449    Notes: Each process in a parallel run displays its component errors in a separate window
7450 
7451    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
7452 
7453    Options Database Keys:
7454 .  -ts_monitor_lg_error - create a graphical monitor of error history
7455 
7456 .keywords: TS,  vector, monitor, view
7457 
7458 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
7459 @*/
7460 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
7461 {
7462   PetscErrorCode    ierr;
7463   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
7464   const PetscScalar *yy;
7465   Vec               y;
7466 
7467   PetscFunctionBegin;
7468   if (!step) {
7469     PetscDrawAxis axis;
7470     PetscInt      dim;
7471     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7472     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Solution");CHKERRQ(ierr);
7473     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7474     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
7475     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7476   }
7477   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
7478   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
7479   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
7480   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
7481 #if defined(PETSC_USE_COMPLEX)
7482   {
7483     PetscReal *yreal;
7484     PetscInt  i,n;
7485     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
7486     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
7487     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
7488     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
7489     ierr = PetscFree(yreal);CHKERRQ(ierr);
7490   }
7491 #else
7492   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
7493 #endif
7494   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
7495   ierr = VecDestroy(&y);CHKERRQ(ierr);
7496   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
7497     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7498     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7499   }
7500   PetscFunctionReturn(0);
7501 }
7502 
7503 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
7504 {
7505   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7506   PetscReal      x   = ptime,y;
7507   PetscErrorCode ierr;
7508   PetscInt       its;
7509 
7510   PetscFunctionBegin;
7511   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7512   if (!n) {
7513     PetscDrawAxis axis;
7514     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7515     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
7516     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7517     ctx->snes_its = 0;
7518   }
7519   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
7520   y    = its - ctx->snes_its;
7521   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7522   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7523     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7524     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7525   }
7526   ctx->snes_its = its;
7527   PetscFunctionReturn(0);
7528 }
7529 
7530 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
7531 {
7532   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7533   PetscReal      x   = ptime,y;
7534   PetscErrorCode ierr;
7535   PetscInt       its;
7536 
7537   PetscFunctionBegin;
7538   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7539   if (!n) {
7540     PetscDrawAxis axis;
7541     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7542     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
7543     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7544     ctx->ksp_its = 0;
7545   }
7546   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
7547   y    = its - ctx->ksp_its;
7548   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7549   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7550     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7551     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7552   }
7553   ctx->ksp_its = its;
7554   PetscFunctionReturn(0);
7555 }
7556 
7557 /*@
7558    TSComputeLinearStability - computes the linear stability function at a point
7559 
7560    Collective on TS and Vec
7561 
7562    Input Parameters:
7563 +  ts - the TS context
7564 -  xr,xi - real and imaginary part of input arguments
7565 
7566    Output Parameters:
7567 .  yr,yi - real and imaginary part of function value
7568 
7569    Level: developer
7570 
7571 .keywords: TS, compute
7572 
7573 .seealso: TSSetRHSFunction(), TSComputeIFunction()
7574 @*/
7575 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
7576 {
7577   PetscErrorCode ierr;
7578 
7579   PetscFunctionBegin;
7580   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7581   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
7582   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
7583   PetscFunctionReturn(0);
7584 }
7585 
7586 /* ------------------------------------------------------------------------*/
7587 /*@C
7588    TSMonitorEnvelopeCtxCreate - Creates a context for use with TSMonitorEnvelope()
7589 
7590    Collective on TS
7591 
7592    Input Parameters:
7593 .  ts  - the ODE solver object
7594 
7595    Output Parameter:
7596 .  ctx - the context
7597 
7598    Level: intermediate
7599 
7600 .keywords: TS, monitor, line graph, residual, seealso
7601 
7602 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
7603 
7604 @*/
7605 PetscErrorCode  TSMonitorEnvelopeCtxCreate(TS ts,TSMonitorEnvelopeCtx *ctx)
7606 {
7607   PetscErrorCode ierr;
7608 
7609   PetscFunctionBegin;
7610   ierr = PetscNew(ctx);CHKERRQ(ierr);
7611   PetscFunctionReturn(0);
7612 }
7613 
7614 /*@C
7615    TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
7616 
7617    Collective on TS
7618 
7619    Input Parameters:
7620 +  ts - the TS context
7621 .  step - current time-step
7622 .  ptime - current time
7623 .  u  - current solution
7624 -  dctx - the envelope context
7625 
7626    Options Database:
7627 .  -ts_monitor_envelope
7628 
7629    Level: intermediate
7630 
7631    Notes: after a solve you can use TSMonitorEnvelopeGetBounds() to access the envelope
7632 
7633 .keywords: TS,  vector, monitor, view
7634 
7635 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxCreate()
7636 @*/
7637 PetscErrorCode  TSMonitorEnvelope(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
7638 {
7639   PetscErrorCode       ierr;
7640   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
7641 
7642   PetscFunctionBegin;
7643   if (!ctx->max) {
7644     ierr = VecDuplicate(u,&ctx->max);CHKERRQ(ierr);
7645     ierr = VecDuplicate(u,&ctx->min);CHKERRQ(ierr);
7646     ierr = VecCopy(u,ctx->max);CHKERRQ(ierr);
7647     ierr = VecCopy(u,ctx->min);CHKERRQ(ierr);
7648   } else {
7649     ierr = VecPointwiseMax(ctx->max,u,ctx->max);CHKERRQ(ierr);
7650     ierr = VecPointwiseMin(ctx->min,u,ctx->min);CHKERRQ(ierr);
7651   }
7652   PetscFunctionReturn(0);
7653 }
7654 
7655 /*@C
7656    TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
7657 
7658    Collective on TS
7659 
7660    Input Parameter:
7661 .  ts - the TS context
7662 
7663    Output Parameter:
7664 +  max - the maximum values
7665 -  min - the minimum values
7666 
7667    Notes: If the TS does not have a TSMonitorEnvelopeCtx associated with it then this function is ignored
7668 
7669    Level: intermediate
7670 
7671 .keywords: TS,  vector, monitor, view
7672 
7673 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
7674 @*/
7675 PetscErrorCode  TSMonitorEnvelopeGetBounds(TS ts,Vec *max,Vec *min)
7676 {
7677   PetscInt i;
7678 
7679   PetscFunctionBegin;
7680   if (max) *max = NULL;
7681   if (min) *min = NULL;
7682   for (i=0; i<ts->numbermonitors; i++) {
7683     if (ts->monitor[i] == TSMonitorEnvelope) {
7684       TSMonitorEnvelopeCtx  ctx = (TSMonitorEnvelopeCtx) ts->monitorcontext[i];
7685       if (max) *max = ctx->max;
7686       if (min) *min = ctx->min;
7687       break;
7688     }
7689   }
7690   PetscFunctionReturn(0);
7691 }
7692 
7693 /*@C
7694    TSMonitorEnvelopeCtxDestroy - Destroys a context that was created  with TSMonitorEnvelopeCtxCreate().
7695 
7696    Collective on TSMonitorEnvelopeCtx
7697 
7698    Input Parameter:
7699 .  ctx - the monitor context
7700 
7701    Level: intermediate
7702 
7703 .keywords: TS, monitor, line graph, destroy
7704 
7705 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep()
7706 @*/
7707 PetscErrorCode  TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
7708 {
7709   PetscErrorCode ierr;
7710 
7711   PetscFunctionBegin;
7712   ierr = VecDestroy(&(*ctx)->min);CHKERRQ(ierr);
7713   ierr = VecDestroy(&(*ctx)->max);CHKERRQ(ierr);
7714   ierr = PetscFree(*ctx);CHKERRQ(ierr);
7715   PetscFunctionReturn(0);
7716 }
7717 
7718 /*@
7719    TSRollBack - Rolls back one time step
7720 
7721    Collective on TS
7722 
7723    Input Parameter:
7724 .  ts - the TS context obtained from TSCreate()
7725 
7726    Level: advanced
7727 
7728 .keywords: TS, timestep, rollback
7729 
7730 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
7731 @*/
7732 PetscErrorCode  TSRollBack(TS ts)
7733 {
7734   PetscErrorCode ierr;
7735 
7736   PetscFunctionBegin;
7737   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7738   if (ts->steprollback) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"TSRollBack already called");
7739   if (!ts->ops->rollback) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
7740   ierr = (*ts->ops->rollback)(ts);CHKERRQ(ierr);
7741   ts->time_step = ts->ptime - ts->ptime_prev;
7742   ts->ptime = ts->ptime_prev;
7743   ts->ptime_prev = ts->ptime_prev_rollback;
7744   ts->steps--;
7745   ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
7746   ts->steprollback = PETSC_TRUE;
7747   PetscFunctionReturn(0);
7748 }
7749 
7750 /*@
7751    TSGetStages - Get the number of stages and stage values
7752 
7753    Input Parameter:
7754 .  ts - the TS context obtained from TSCreate()
7755 
7756    Level: advanced
7757 
7758 .keywords: TS, getstages
7759 
7760 .seealso: TSCreate()
7761 @*/
7762 PetscErrorCode  TSGetStages(TS ts,PetscInt *ns,Vec **Y)
7763 {
7764   PetscErrorCode ierr;
7765 
7766   PetscFunctionBegin;
7767   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7768   PetscValidPointer(ns,2);
7769 
7770   if (!ts->ops->getstages) *ns=0;
7771   else {
7772     ierr = (*ts->ops->getstages)(ts,ns,Y);CHKERRQ(ierr);
7773   }
7774   PetscFunctionReturn(0);
7775 }
7776 
7777 /*@C
7778   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
7779 
7780   Collective on SNES
7781 
7782   Input Parameters:
7783 + ts - the TS context
7784 . t - current timestep
7785 . U - state vector
7786 . Udot - time derivative of state vector
7787 . shift - shift to apply, see note below
7788 - ctx - an optional user context
7789 
7790   Output Parameters:
7791 + J - Jacobian matrix (not altered in this routine)
7792 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
7793 
7794   Level: intermediate
7795 
7796   Notes:
7797   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
7798 
7799   dF/dU + shift*dF/dUdot
7800 
7801   Most users should not need to explicitly call this routine, as it
7802   is used internally within the nonlinear solvers.
7803 
7804   This will first try to get the coloring from the DM.  If the DM type has no coloring
7805   routine, then it will try to get the coloring from the matrix.  This requires that the
7806   matrix have nonzero entries precomputed.
7807 
7808 .keywords: TS, finite differences, Jacobian, coloring, sparse
7809 .seealso: TSSetIJacobian(), MatFDColoringCreate(), MatFDColoringSetFunction()
7810 @*/
7811 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat J,Mat B,void *ctx)
7812 {
7813   SNES           snes;
7814   MatFDColoring  color;
7815   PetscBool      hascolor, matcolor = PETSC_FALSE;
7816   PetscErrorCode ierr;
7817 
7818   PetscFunctionBegin;
7819   ierr = PetscOptionsGetBool(((PetscObject)ts)->options,((PetscObject) ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL);CHKERRQ(ierr);
7820   ierr = PetscObjectQuery((PetscObject) B, "TSMatFDColoring", (PetscObject *) &color);CHKERRQ(ierr);
7821   if (!color) {
7822     DM         dm;
7823     ISColoring iscoloring;
7824 
7825     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
7826     ierr = DMHasColoring(dm, &hascolor);CHKERRQ(ierr);
7827     if (hascolor && !matcolor) {
7828       ierr = DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring);CHKERRQ(ierr);
7829       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7830       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7831       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7832       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7833       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7834     } else {
7835       MatColoring mc;
7836 
7837       ierr = MatColoringCreate(B, &mc);CHKERRQ(ierr);
7838       ierr = MatColoringSetDistance(mc, 2);CHKERRQ(ierr);
7839       ierr = MatColoringSetType(mc, MATCOLORINGSL);CHKERRQ(ierr);
7840       ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr);
7841       ierr = MatColoringApply(mc, &iscoloring);CHKERRQ(ierr);
7842       ierr = MatColoringDestroy(&mc);CHKERRQ(ierr);
7843       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7844       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7845       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7846       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7847       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7848     }
7849     ierr = PetscObjectCompose((PetscObject) B, "TSMatFDColoring", (PetscObject) color);CHKERRQ(ierr);
7850     ierr = PetscObjectDereference((PetscObject) color);CHKERRQ(ierr);
7851   }
7852   ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
7853   ierr = MatFDColoringApply(B, color, U, snes);CHKERRQ(ierr);
7854   if (J != B) {
7855     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7856     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7857   }
7858   PetscFunctionReturn(0);
7859 }
7860 
7861 /*@
7862     TSSetFunctionDomainError - Set the function testing if the current state vector is valid
7863 
7864     Input Parameters:
7865     ts - the TS context
7866     func - function called within TSFunctionDomainError
7867 
7868     Level: intermediate
7869 
7870 .keywords: TS, state, domain
7871 .seealso: TSAdaptCheckStage(), TSFunctionDomainError()
7872 @*/
7873 
7874 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS,PetscReal,Vec,PetscBool*))
7875 {
7876   PetscFunctionBegin;
7877   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7878   ts->functiondomainerror = func;
7879   PetscFunctionReturn(0);
7880 }
7881 
7882 /*@
7883     TSFunctionDomainError - Check if the current state is valid
7884 
7885     Input Parameters:
7886     ts - the TS context
7887     stagetime - time of the simulation
7888     Y - state vector to check.
7889 
7890     Output Parameter:
7891     accept - Set to PETSC_FALSE if the current state vector is valid.
7892 
7893     Note:
7894     This function should be used to ensure the state is in a valid part of the space.
7895     For example, one can ensure here all values are positive.
7896 
7897     Level: advanced
7898 @*/
7899 PetscErrorCode TSFunctionDomainError(TS ts,PetscReal stagetime,Vec Y,PetscBool* accept)
7900 {
7901   PetscErrorCode ierr;
7902 
7903   PetscFunctionBegin;
7904 
7905   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7906   *accept = PETSC_TRUE;
7907   if (ts->functiondomainerror) {
7908     PetscStackCallStandard((*ts->functiondomainerror),(ts,stagetime,Y,accept));
7909   }
7910   PetscFunctionReturn(0);
7911 }
7912 
7913 /*@C
7914   TSClone - This function clones a time step object.
7915 
7916   Collective on MPI_Comm
7917 
7918   Input Parameter:
7919 . tsin    - The input TS
7920 
7921   Output Parameter:
7922 . tsout   - The output TS (cloned)
7923 
7924   Notes:
7925   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.
7926 
7927   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);
7928 
7929   Level: developer
7930 
7931 .keywords: TS, clone
7932 .seealso: TSCreate(), TSSetType(), TSSetUp(), TSDestroy(), TSSetProblemType()
7933 @*/
7934 PetscErrorCode  TSClone(TS tsin, TS *tsout)
7935 {
7936   TS             t;
7937   PetscErrorCode ierr;
7938   SNES           snes_start;
7939   DM             dm;
7940   TSType         type;
7941 
7942   PetscFunctionBegin;
7943   PetscValidPointer(tsin,1);
7944   *tsout = NULL;
7945 
7946   ierr = PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView);CHKERRQ(ierr);
7947 
7948   /* General TS description */
7949   t->numbermonitors    = 0;
7950   t->setupcalled       = 0;
7951   t->ksp_its           = 0;
7952   t->snes_its          = 0;
7953   t->nwork             = 0;
7954   t->rhsjacobian.time  = -1e20;
7955   t->rhsjacobian.scale = 1.;
7956   t->ijacobian.shift   = 1.;
7957 
7958   ierr = TSGetSNES(tsin,&snes_start);CHKERRQ(ierr);
7959   ierr = TSSetSNES(t,snes_start);CHKERRQ(ierr);
7960 
7961   ierr = TSGetDM(tsin,&dm);CHKERRQ(ierr);
7962   ierr = TSSetDM(t,dm);CHKERRQ(ierr);
7963 
7964   t->adapt = tsin->adapt;
7965   ierr = PetscObjectReference((PetscObject)t->adapt);CHKERRQ(ierr);
7966 
7967   t->trajectory = tsin->trajectory;
7968   ierr = PetscObjectReference((PetscObject)t->trajectory);CHKERRQ(ierr);
7969 
7970   t->event = tsin->event;
7971   if (t->event) t->event->refct++;
7972 
7973   t->problem_type      = tsin->problem_type;
7974   t->ptime             = tsin->ptime;
7975   t->ptime_prev        = tsin->ptime_prev;
7976   t->time_step         = tsin->time_step;
7977   t->max_time          = tsin->max_time;
7978   t->steps             = tsin->steps;
7979   t->max_steps         = tsin->max_steps;
7980   t->equation_type     = tsin->equation_type;
7981   t->atol              = tsin->atol;
7982   t->rtol              = tsin->rtol;
7983   t->max_snes_failures = tsin->max_snes_failures;
7984   t->max_reject        = tsin->max_reject;
7985   t->errorifstepfailed = tsin->errorifstepfailed;
7986 
7987   ierr = TSGetType(tsin,&type);CHKERRQ(ierr);
7988   ierr = TSSetType(t,type);CHKERRQ(ierr);
7989 
7990   t->vec_sol           = NULL;
7991 
7992   t->cfltime          = tsin->cfltime;
7993   t->cfltime_local    = tsin->cfltime_local;
7994   t->exact_final_time = tsin->exact_final_time;
7995 
7996   ierr = PetscMemcpy(t->ops,tsin->ops,sizeof(struct _TSOps));CHKERRQ(ierr);
7997 
7998   if (((PetscObject)tsin)->fortran_func_pointers) {
7999     PetscInt i;
8000     ierr = PetscMalloc((10)*sizeof(void(*)(void)),&((PetscObject)t)->fortran_func_pointers);CHKERRQ(ierr);
8001     for (i=0; i<10; i++) {
8002       ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
8003     }
8004   }
8005   *tsout = t;
8006   PetscFunctionReturn(0);
8007 }
8008