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