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