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