xref: /petsc/src/ts/interface/ts.c (revision 93283c780aaaccb179e6ff65a062ae33718e0161)
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       /* we need to copy the values of the matrix because for the constant Jacobian case the user will never set the numerical values in this new location */
2567       ierr = MatDuplicate(ts->Arhs,MAT_COPY_VALUES,&Amat);CHKERRQ(ierr);
2568       ierr = SNESSetJacobian(snes,Amat,NULL,NULL,NULL);CHKERRQ(ierr);
2569       ierr = MatDestroy(&Amat);CHKERRQ(ierr);
2570     }
2571     if (Pmat == ts->Brhs) {
2572       ierr = MatDuplicate(ts->Brhs,MAT_COPY_VALUES,&Pmat);CHKERRQ(ierr);
2573       ierr = SNESSetJacobian(snes,NULL,Pmat,NULL,NULL);CHKERRQ(ierr);
2574       ierr = MatDestroy(&Pmat);CHKERRQ(ierr);
2575     }
2576   }
2577 
2578   ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr);
2579   ierr = TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type);CHKERRQ(ierr);
2580 
2581   if (ts->ops->setup) {
2582     ierr = (*ts->ops->setup)(ts);CHKERRQ(ierr);
2583   }
2584 
2585   /* Attempt to check/preset a default value for the exact final time option */
2586   ierr = PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&isnone);CHKERRQ(ierr);
2587   if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED)
2588     ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP;
2589 
2590   /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
2591      to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
2592    */
2593   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2594   ierr = DMSNESGetFunction(dm,&func,NULL);CHKERRQ(ierr);
2595   if (!func) {
2596     ierr = DMSNESSetFunction(dm,SNESTSFormFunction,ts);CHKERRQ(ierr);
2597   }
2598   /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
2599      Otherwise, the SNES will use coloring internally to form the Jacobian.
2600    */
2601   ierr = DMSNESGetJacobian(dm,&jac,NULL);CHKERRQ(ierr);
2602   ierr = DMTSGetIJacobian(dm,&ijac,NULL);CHKERRQ(ierr);
2603   ierr = DMTSGetI2Jacobian(dm,&i2jac,NULL);CHKERRQ(ierr);
2604   ierr = DMTSGetRHSJacobian(dm,&rhsjac,NULL);CHKERRQ(ierr);
2605   if (!jac && (ijac || i2jac || rhsjac)) {
2606     ierr = DMSNESSetJacobian(dm,SNESTSFormJacobian,ts);CHKERRQ(ierr);
2607   }
2608 
2609   /* if time integration scheme has a starting method, call it */
2610   if (ts->ops->startingmethod) {
2611     ierr = (*ts->ops->startingmethod)(ts);CHKERRQ(ierr);
2612   }
2613 
2614   ts->setupcalled = PETSC_TRUE;
2615   PetscFunctionReturn(0);
2616 }
2617 
2618 /*@
2619    TSAdjointSetUp - Sets up the internal data structures for the later use
2620    of an adjoint solver
2621 
2622    Collective on TS
2623 
2624    Input Parameter:
2625 .  ts - the TS context obtained from TSCreate()
2626 
2627    Level: advanced
2628 
2629 .keywords: TS, timestep, setup
2630 
2631 .seealso: TSCreate(), TSAdjointStep(), TSSetCostGradients()
2632 @*/
2633 PetscErrorCode  TSAdjointSetUp(TS ts)
2634 {
2635   PetscErrorCode ierr;
2636 
2637   PetscFunctionBegin;
2638   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2639   if (ts->adjointsetupcalled) PetscFunctionReturn(0);
2640   if (!ts->vecs_sensi) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetCostGradients() first");
2641   if (ts->vecs_sensip && !ts->Jacp) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSAdjointSetRHSJacobian() first");
2642 
2643   if (ts->vec_costintegral) { /* if there is integral in the cost function */
2644     ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&ts->vecs_drdy);CHKERRQ(ierr);
2645     if (ts->vecs_sensip){
2646       ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
2647     }
2648   }
2649 
2650   if (ts->ops->adjointsetup) {
2651     ierr = (*ts->ops->adjointsetup)(ts);CHKERRQ(ierr);
2652   }
2653   ts->adjointsetupcalled = PETSC_TRUE;
2654   PetscFunctionReturn(0);
2655 }
2656 
2657 /*@
2658    TSReset - Resets a TS context and removes any allocated Vecs and Mats.
2659 
2660    Collective on TS
2661 
2662    Input Parameter:
2663 .  ts - the TS context obtained from TSCreate()
2664 
2665    Level: beginner
2666 
2667 .keywords: TS, timestep, reset
2668 
2669 .seealso: TSCreate(), TSSetup(), TSDestroy()
2670 @*/
2671 PetscErrorCode  TSReset(TS ts)
2672 {
2673   PetscErrorCode ierr;
2674 
2675   PetscFunctionBegin;
2676   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2677 
2678   if (ts->ops->reset) {
2679     ierr = (*ts->ops->reset)(ts);CHKERRQ(ierr);
2680   }
2681   if (ts->snes) {ierr = SNESReset(ts->snes);CHKERRQ(ierr);}
2682   if (ts->adapt) {ierr = TSAdaptReset(ts->adapt);CHKERRQ(ierr);}
2683 
2684   ierr = MatDestroy(&ts->Arhs);CHKERRQ(ierr);
2685   ierr = MatDestroy(&ts->Brhs);CHKERRQ(ierr);
2686   ierr = VecDestroy(&ts->Frhs);CHKERRQ(ierr);
2687   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
2688   ierr = VecDestroy(&ts->vec_dot);CHKERRQ(ierr);
2689   ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
2690   ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
2691   ierr = VecDestroyVecs(ts->nwork,&ts->work);CHKERRQ(ierr);
2692 
2693  if (ts->vec_costintegral) {
2694     ierr = VecDestroyVecs(ts->numcost,&ts->vecs_drdy);CHKERRQ(ierr);
2695     if (ts->vecs_drdp){
2696       ierr = VecDestroyVecs(ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
2697     }
2698   }
2699   ts->vecs_sensi  = NULL;
2700   ts->vecs_sensip = NULL;
2701   ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
2702   ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr);
2703   ierr = VecDestroy(&ts->vec_costintegrand);CHKERRQ(ierr);
2704   ts->setupcalled = PETSC_FALSE;
2705   PetscFunctionReturn(0);
2706 }
2707 
2708 /*@
2709    TSDestroy - Destroys the timestepper context that was created
2710    with TSCreate().
2711 
2712    Collective on TS
2713 
2714    Input Parameter:
2715 .  ts - the TS context obtained from TSCreate()
2716 
2717    Level: beginner
2718 
2719 .keywords: TS, timestepper, destroy
2720 
2721 .seealso: TSCreate(), TSSetUp(), TSSolve()
2722 @*/
2723 PetscErrorCode  TSDestroy(TS *ts)
2724 {
2725   PetscErrorCode ierr;
2726 
2727   PetscFunctionBegin;
2728   if (!*ts) PetscFunctionReturn(0);
2729   PetscValidHeaderSpecific((*ts),TS_CLASSID,1);
2730   if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; PetscFunctionReturn(0);}
2731 
2732   ierr = TSReset((*ts));CHKERRQ(ierr);
2733 
2734   /* if memory was published with SAWs then destroy it */
2735   ierr = PetscObjectSAWsViewOff((PetscObject)*ts);CHKERRQ(ierr);
2736   if ((*ts)->ops->destroy) {ierr = (*(*ts)->ops->destroy)((*ts));CHKERRQ(ierr);}
2737 
2738   ierr = TSTrajectoryDestroy(&(*ts)->trajectory);CHKERRQ(ierr);
2739 
2740   ierr = TSAdaptDestroy(&(*ts)->adapt);CHKERRQ(ierr);
2741   ierr = TSEventDestroy(&(*ts)->event);CHKERRQ(ierr);
2742 
2743   ierr = SNESDestroy(&(*ts)->snes);CHKERRQ(ierr);
2744   ierr = DMDestroy(&(*ts)->dm);CHKERRQ(ierr);
2745   ierr = TSMonitorCancel((*ts));CHKERRQ(ierr);
2746   ierr = TSAdjointMonitorCancel((*ts));CHKERRQ(ierr);
2747 
2748   ierr = PetscHeaderDestroy(ts);CHKERRQ(ierr);
2749   PetscFunctionReturn(0);
2750 }
2751 
2752 /*@
2753    TSGetSNES - Returns the SNES (nonlinear solver) associated with
2754    a TS (timestepper) context. Valid only for nonlinear problems.
2755 
2756    Not Collective, but SNES is parallel if TS is parallel
2757 
2758    Input Parameter:
2759 .  ts - the TS context obtained from TSCreate()
2760 
2761    Output Parameter:
2762 .  snes - the nonlinear solver context
2763 
2764    Notes:
2765    The user can then directly manipulate the SNES context to set various
2766    options, etc.  Likewise, the user can then extract and manipulate the
2767    KSP, KSP, and PC contexts as well.
2768 
2769    TSGetSNES() does not work for integrators that do not use SNES; in
2770    this case TSGetSNES() returns NULL in snes.
2771 
2772    Level: beginner
2773 
2774 .keywords: timestep, get, SNES
2775 @*/
2776 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
2777 {
2778   PetscErrorCode ierr;
2779 
2780   PetscFunctionBegin;
2781   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2782   PetscValidPointer(snes,2);
2783   if (!ts->snes) {
2784     ierr = SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes);CHKERRQ(ierr);
2785     ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2786     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->snes);CHKERRQ(ierr);
2787     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);CHKERRQ(ierr);
2788     if (ts->dm) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
2789     if (ts->problem_type == TS_LINEAR) {
2790       ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr);
2791     }
2792   }
2793   *snes = ts->snes;
2794   PetscFunctionReturn(0);
2795 }
2796 
2797 /*@
2798    TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
2799 
2800    Collective
2801 
2802    Input Parameter:
2803 +  ts - the TS context obtained from TSCreate()
2804 -  snes - the nonlinear solver context
2805 
2806    Notes:
2807    Most users should have the TS created by calling TSGetSNES()
2808 
2809    Level: developer
2810 
2811 .keywords: timestep, set, SNES
2812 @*/
2813 PetscErrorCode TSSetSNES(TS ts,SNES snes)
2814 {
2815   PetscErrorCode ierr;
2816   PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*);
2817 
2818   PetscFunctionBegin;
2819   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2820   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
2821   ierr = PetscObjectReference((PetscObject)snes);CHKERRQ(ierr);
2822   ierr = SNESDestroy(&ts->snes);CHKERRQ(ierr);
2823 
2824   ts->snes = snes;
2825 
2826   ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2827   ierr = SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL);CHKERRQ(ierr);
2828   if (func == SNESTSFormJacobian) {
2829     ierr = SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts);CHKERRQ(ierr);
2830   }
2831   PetscFunctionReturn(0);
2832 }
2833 
2834 /*@
2835    TSGetKSP - Returns the KSP (linear solver) associated with
2836    a TS (timestepper) context.
2837 
2838    Not Collective, but KSP is parallel if TS is parallel
2839 
2840    Input Parameter:
2841 .  ts - the TS context obtained from TSCreate()
2842 
2843    Output Parameter:
2844 .  ksp - the nonlinear solver context
2845 
2846    Notes:
2847    The user can then directly manipulate the KSP context to set various
2848    options, etc.  Likewise, the user can then extract and manipulate the
2849    KSP and PC contexts as well.
2850 
2851    TSGetKSP() does not work for integrators that do not use KSP;
2852    in this case TSGetKSP() returns NULL in ksp.
2853 
2854    Level: beginner
2855 
2856 .keywords: timestep, get, KSP
2857 @*/
2858 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
2859 {
2860   PetscErrorCode ierr;
2861   SNES           snes;
2862 
2863   PetscFunctionBegin;
2864   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2865   PetscValidPointer(ksp,2);
2866   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
2867   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
2868   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2869   ierr = SNESGetKSP(snes,ksp);CHKERRQ(ierr);
2870   PetscFunctionReturn(0);
2871 }
2872 
2873 /* ----------- Routines to set solver parameters ---------- */
2874 
2875 /*@
2876    TSGetDuration - Gets the maximum number of timesteps to use and
2877    maximum time for iteration.
2878 
2879    Not Collective
2880 
2881    Input Parameters:
2882 +  ts       - the TS context obtained from TSCreate()
2883 .  maxsteps - maximum number of iterations to use, or NULL
2884 -  maxtime  - final time to iterate to, or NULL
2885 
2886    Level: intermediate
2887 
2888 .keywords: TS, timestep, get, maximum, iterations, time
2889 @*/
2890 PetscErrorCode  TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
2891 {
2892   PetscFunctionBegin;
2893   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2894   if (maxsteps) {
2895     PetscValidIntPointer(maxsteps,2);
2896     *maxsteps = ts->max_steps;
2897   }
2898   if (maxtime) {
2899     PetscValidScalarPointer(maxtime,3);
2900     *maxtime = ts->max_time;
2901   }
2902   PetscFunctionReturn(0);
2903 }
2904 
2905 /*@
2906    TSSetDuration - Sets the maximum number of timesteps to use and
2907    maximum time for iteration.
2908 
2909    Logically Collective on TS
2910 
2911    Input Parameters:
2912 +  ts - the TS context obtained from TSCreate()
2913 .  maxsteps - maximum number of iterations to use
2914 -  maxtime - final time to iterate to
2915 
2916    Options Database Keys:
2917 .  -ts_max_steps <maxsteps> - Sets maxsteps
2918 .  -ts_final_time <maxtime> - Sets maxtime
2919 
2920    Notes:
2921    The default maximum number of iterations is 5000. Default time is 5.0
2922 
2923    Level: intermediate
2924 
2925 .keywords: TS, timestep, set, maximum, iterations
2926 
2927 .seealso: TSSetExactFinalTime()
2928 @*/
2929 PetscErrorCode  TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
2930 {
2931   PetscFunctionBegin;
2932   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2933   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
2934   PetscValidLogicalCollectiveReal(ts,maxtime,2);
2935   if (maxsteps >= 0) ts->max_steps = maxsteps;
2936   if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
2937   PetscFunctionReturn(0);
2938 }
2939 
2940 /*@
2941    TSSetSolution - Sets the initial solution vector
2942    for use by the TS routines.
2943 
2944    Logically Collective on TS and Vec
2945 
2946    Input Parameters:
2947 +  ts - the TS context obtained from TSCreate()
2948 -  u - the solution vector
2949 
2950    Level: beginner
2951 
2952 .keywords: TS, timestep, set, solution, initial conditions
2953 @*/
2954 PetscErrorCode  TSSetSolution(TS ts,Vec u)
2955 {
2956   PetscErrorCode ierr;
2957   DM             dm;
2958 
2959   PetscFunctionBegin;
2960   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2961   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
2962   ierr = PetscObjectReference((PetscObject)u);CHKERRQ(ierr);
2963   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
2964   ts->vec_sol = u;
2965 
2966   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2967   ierr = DMShellSetGlobalVector(dm,u);CHKERRQ(ierr);
2968   PetscFunctionReturn(0);
2969 }
2970 
2971 /*@
2972    TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time
2973 
2974    Logically Collective on TS
2975 
2976    Input Parameters:
2977 +  ts - the TS context obtained from TSCreate()
2978 .  steps - number of steps to use
2979 
2980    Level: intermediate
2981 
2982    Notes: Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this
2983           so as to integrate back to less than the original timestep
2984 
2985 .keywords: TS, timestep, set, maximum, iterations
2986 
2987 .seealso: TSSetExactFinalTime()
2988 @*/
2989 PetscErrorCode  TSAdjointSetSteps(TS ts,PetscInt steps)
2990 {
2991   PetscFunctionBegin;
2992   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2993   PetscValidLogicalCollectiveInt(ts,steps,2);
2994   if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps");
2995   if (steps > ts->total_steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps");
2996   ts->adjoint_max_steps = steps;
2997   PetscFunctionReturn(0);
2998 }
2999 
3000 /*@
3001    TSSetCostGradients - Sets the initial value of the gradients of the cost function w.r.t. initial conditions and w.r.t. the problem parameters
3002       for use by the TSAdjoint routines.
3003 
3004    Logically Collective on TS and Vec
3005 
3006    Input Parameters:
3007 +  ts - the TS context obtained from TSCreate()
3008 .  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
3009 -  mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
3010 
3011    Level: beginner
3012 
3013    Notes: the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime  mu_i = df/dp|finaltime
3014 
3015 .keywords: TS, timestep, set, sensitivity, initial conditions
3016 @*/
3017 PetscErrorCode  TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu)
3018 {
3019   PetscFunctionBegin;
3020   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3021   PetscValidPointer(lambda,2);
3022   ts->vecs_sensi  = lambda;
3023   ts->vecs_sensip = mu;
3024   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");
3025   ts->numcost  = numcost;
3026   PetscFunctionReturn(0);
3027 }
3028 
3029 /*@C
3030   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.
3031 
3032   Logically Collective on TS
3033 
3034   Input Parameters:
3035 + ts   - The TS context obtained from TSCreate()
3036 - func - The function
3037 
3038   Calling sequence of func:
3039 $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx);
3040 +   t - current timestep
3041 .   y - input vector (current ODE solution)
3042 .   A - output matrix
3043 -   ctx - [optional] user-defined function context
3044 
3045   Level: intermediate
3046 
3047   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
3048 
3049 .keywords: TS, sensitivity
3050 .seealso:
3051 @*/
3052 PetscErrorCode  TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
3053 {
3054   PetscErrorCode ierr;
3055 
3056   PetscFunctionBegin;
3057   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3058   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
3059 
3060   ts->rhsjacobianp    = func;
3061   ts->rhsjacobianpctx = ctx;
3062   if(Amat) {
3063     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
3064     ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
3065     ts->Jacp = Amat;
3066   }
3067   PetscFunctionReturn(0);
3068 }
3069 
3070 /*@C
3071   TSAdjointComputeRHSJacobian - Runs the user-defined Jacobian function.
3072 
3073   Collective on TS
3074 
3075   Input Parameters:
3076 . ts   - The TS context obtained from TSCreate()
3077 
3078   Level: developer
3079 
3080 .keywords: TS, sensitivity
3081 .seealso: TSAdjointSetRHSJacobian()
3082 @*/
3083 PetscErrorCode  TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec X,Mat Amat)
3084 {
3085   PetscErrorCode ierr;
3086 
3087   PetscFunctionBegin;
3088   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3089   PetscValidHeaderSpecific(X,VEC_CLASSID,3);
3090   PetscValidPointer(Amat,4);
3091 
3092   PetscStackPush("TS user JacobianP function for sensitivity analysis");
3093   ierr = (*ts->rhsjacobianp)(ts,t,X,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr);
3094   PetscStackPop;
3095   PetscFunctionReturn(0);
3096 }
3097 
3098 /*@C
3099     TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions
3100 
3101     Logically Collective on TS
3102 
3103     Input Parameters:
3104 +   ts - the TS context obtained from TSCreate()
3105 .   numcost - number of gradients to be computed, this is the number of cost functions
3106 .   costintegral - vector that stores the integral values
3107 .   rf - routine for evaluating the integrand function
3108 .   drdyf - function that computes the gradients of the r's with respect to y,NULL if not a function y
3109 .   drdpf - function that computes the gradients of the r's with respect to p, NULL if not a function of p
3110 .   fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
3111 -   ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
3112 
3113     Calling sequence of rf:
3114 $   PetscErrorCode rf(TS ts,PetscReal t,Vec y,Vec f,void *ctx);
3115 
3116     Calling sequence of drdyf:
3117 $   PetscErroCode drdyf(TS ts,PetscReal t,Vec y,Vec *drdy,void *ctx);
3118 
3119     Calling sequence of drdpf:
3120 $   PetscErroCode drdpf(TS ts,PetscReal t,Vec y,Vec *drdp,void *ctx);
3121 
3122     Level: intermediate
3123 
3124     Notes: For optimization there is generally a single cost function, numcost = 1. For sensitivities there may be multiple cost functions
3125 
3126 .keywords: TS, sensitivity analysis, timestep, set, quadrature, function
3127 
3128 .seealso: TSAdjointSetRHSJacobian(),TSGetCostGradients(), TSSetCostGradients()
3129 @*/
3130 PetscErrorCode  TSSetCostIntegrand(TS ts,PetscInt numcost,Vec costintegral,PetscErrorCode (*rf)(TS,PetscReal,Vec,Vec,void*),
3131                                                           PetscErrorCode (*drdyf)(TS,PetscReal,Vec,Vec*,void*),
3132                                                           PetscErrorCode (*drdpf)(TS,PetscReal,Vec,Vec*,void*),
3133                                                           PetscBool fwd,void *ctx)
3134 {
3135   PetscErrorCode ierr;
3136 
3137   PetscFunctionBegin;
3138   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3139   if (costintegral) PetscValidHeaderSpecific(costintegral,VEC_CLASSID,3);
3140   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()");
3141   if (!ts->numcost) ts->numcost=numcost;
3142 
3143   if (costintegral) {
3144     ierr = PetscObjectReference((PetscObject)costintegral);CHKERRQ(ierr);
3145     ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr);
3146     ts->vec_costintegral = costintegral;
3147   } else { ierr = VecCreateSeq(PETSC_COMM_SELF,numcost,&ts->vec_costintegral);CHKERRQ(ierr); /* works for serial only */ }
3148 
3149   ts->costintegralfwd  = fwd; /* Evaluate the cost integral in forward run if fwd is true */
3150   ierr                 = VecDuplicate(ts->vec_costintegral,&ts->vec_costintegrand);CHKERRQ(ierr);
3151   ts->costintegrand    = rf;
3152   ts->costintegrandctx = ctx;
3153   ts->drdyfunction     = drdyf;
3154   ts->drdpfunction     = drdpf;
3155   PetscFunctionReturn(0);
3156 }
3157 
3158 /*@
3159    TSGetCostIntegral - Returns the values of the integral term in the cost functions.
3160    It is valid to call the routine after a backward run.
3161 
3162    Not Collective
3163 
3164    Input Parameter:
3165 .  ts - the TS context obtained from TSCreate()
3166 
3167    Output Parameter:
3168 .  v - the vector containing the integrals for each cost function
3169 
3170    Level: intermediate
3171 
3172 .seealso: TSSetCostIntegrand()
3173 
3174 .keywords: TS, sensitivity analysis
3175 @*/
3176 PetscErrorCode  TSGetCostIntegral(TS ts,Vec *v)
3177 {
3178   PetscFunctionBegin;
3179   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3180   PetscValidPointer(v,2);
3181   *v = ts->vec_costintegral;
3182   PetscFunctionReturn(0);
3183 }
3184 
3185 /*@
3186    TSAdjointComputeCostIntegrand - Evaluates the integral function in the cost functions.
3187 
3188    Input Parameters:
3189 +  ts - the TS context
3190 .  t - current time
3191 -  y - state vector, i.e. current solution
3192 
3193    Output Parameter:
3194 .  q - vector of size numcost to hold the outputs
3195 
3196    Note:
3197    Most users should not need to explicitly call this routine, as it
3198    is used internally within the sensitivity analysis context.
3199 
3200    Level: developer
3201 
3202 .keywords: TS, compute
3203 
3204 .seealso: TSSetCostIntegrand()
3205 @*/
3206 PetscErrorCode TSAdjointComputeCostIntegrand(TS ts,PetscReal t,Vec y,Vec q)
3207 {
3208   PetscErrorCode ierr;
3209 
3210   PetscFunctionBegin;
3211   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3212   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3213   PetscValidHeaderSpecific(q,VEC_CLASSID,4);
3214 
3215   ierr = PetscLogEventBegin(TS_FunctionEval,ts,y,q,0);CHKERRQ(ierr);
3216   if (ts->costintegrand) {
3217     PetscStackPush("TS user integrand in the cost function");
3218     ierr = (*ts->costintegrand)(ts,t,y,q,ts->costintegrandctx);CHKERRQ(ierr);
3219     PetscStackPop;
3220   } else {
3221     ierr = VecZeroEntries(q);CHKERRQ(ierr);
3222   }
3223 
3224   ierr = PetscLogEventEnd(TS_FunctionEval,ts,y,q,0);CHKERRQ(ierr);
3225   PetscFunctionReturn(0);
3226 }
3227 
3228 /*@
3229   TSAdjointComputeDRDYFunction - Runs the user-defined DRDY function.
3230 
3231   Collective on TS
3232 
3233   Input Parameters:
3234 . ts   - The TS context obtained from TSCreate()
3235 
3236   Notes:
3237   TSAdjointComputeDRDYFunction() is typically used for sensitivity implementation,
3238   so most users would not generally call this routine themselves.
3239 
3240   Level: developer
3241 
3242 .keywords: TS, sensitivity
3243 .seealso: TSAdjointComputeDRDYFunction()
3244 @*/
3245 PetscErrorCode  TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec y,Vec *drdy)
3246 {
3247   PetscErrorCode ierr;
3248 
3249   PetscFunctionBegin;
3250   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3251   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3252 
3253   PetscStackPush("TS user DRDY function for sensitivity analysis");
3254   ierr = (*ts->drdyfunction)(ts,t,y,drdy,ts->costintegrandctx); CHKERRQ(ierr);
3255   PetscStackPop;
3256   PetscFunctionReturn(0);
3257 }
3258 
3259 /*@
3260   TSAdjointComputeDRDPFunction - Runs the user-defined DRDP function.
3261 
3262   Collective on TS
3263 
3264   Input Parameters:
3265 . ts   - The TS context obtained from TSCreate()
3266 
3267   Notes:
3268   TSDRDPFunction() is typically used for sensitivity implementation,
3269   so most users would not generally call this routine themselves.
3270 
3271   Level: developer
3272 
3273 .keywords: TS, sensitivity
3274 .seealso: TSAdjointSetDRDPFunction()
3275 @*/
3276 PetscErrorCode  TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec y,Vec *drdp)
3277 {
3278   PetscErrorCode ierr;
3279 
3280   PetscFunctionBegin;
3281   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3282   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3283 
3284   PetscStackPush("TS user DRDP function for sensitivity analysis");
3285   ierr = (*ts->drdpfunction)(ts,t,y,drdp,ts->costintegrandctx); CHKERRQ(ierr);
3286   PetscStackPop;
3287   PetscFunctionReturn(0);
3288 }
3289 
3290 /*@C
3291   TSSetPreStep - Sets the general-purpose function
3292   called once at the beginning of each time step.
3293 
3294   Logically Collective on TS
3295 
3296   Input Parameters:
3297 + ts   - The TS context obtained from TSCreate()
3298 - func - The function
3299 
3300   Calling sequence of func:
3301 . func (TS ts);
3302 
3303   Level: intermediate
3304 
3305 .keywords: TS, timestep
3306 .seealso: TSSetPreStage(), TSSetPostStage(), TSSetPostStep(), TSStep()
3307 @*/
3308 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
3309 {
3310   PetscFunctionBegin;
3311   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3312   ts->prestep = func;
3313   PetscFunctionReturn(0);
3314 }
3315 
3316 /*@
3317   TSPreStep - Runs the user-defined pre-step function.
3318 
3319   Collective on TS
3320 
3321   Input Parameters:
3322 . ts   - The TS context obtained from TSCreate()
3323 
3324   Notes:
3325   TSPreStep() is typically used within time stepping implementations,
3326   so most users would not generally call this routine themselves.
3327 
3328   Level: developer
3329 
3330 .keywords: TS, timestep
3331 .seealso: TSSetPreStep(), TSPreStage(), TSPostStage(), TSPostStep()
3332 @*/
3333 PetscErrorCode  TSPreStep(TS ts)
3334 {
3335   PetscErrorCode ierr;
3336 
3337   PetscFunctionBegin;
3338   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3339   if (ts->prestep) {
3340     PetscStackCallStandard((*ts->prestep),(ts));
3341   }
3342   PetscFunctionReturn(0);
3343 }
3344 
3345 /*@C
3346   TSSetPreStage - Sets the general-purpose function
3347   called once at the beginning of each stage.
3348 
3349   Logically Collective on TS
3350 
3351   Input Parameters:
3352 + ts   - The TS context obtained from TSCreate()
3353 - func - The function
3354 
3355   Calling sequence of func:
3356 . PetscErrorCode func(TS ts, PetscReal stagetime);
3357 
3358   Level: intermediate
3359 
3360   Note:
3361   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3362   The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
3363   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3364 
3365 .keywords: TS, timestep
3366 .seealso: TSSetPostStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3367 @*/
3368 PetscErrorCode  TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
3369 {
3370   PetscFunctionBegin;
3371   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3372   ts->prestage = func;
3373   PetscFunctionReturn(0);
3374 }
3375 
3376 /*@C
3377   TSSetPostStage - Sets the general-purpose function
3378   called once at the end of each stage.
3379 
3380   Logically Collective on TS
3381 
3382   Input Parameters:
3383 + ts   - The TS context obtained from TSCreate()
3384 - func - The function
3385 
3386   Calling sequence of func:
3387 . PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y);
3388 
3389   Level: intermediate
3390 
3391   Note:
3392   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3393   The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
3394   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3395 
3396 .keywords: TS, timestep
3397 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3398 @*/
3399 PetscErrorCode  TSSetPostStage(TS ts, PetscErrorCode (*func)(TS,PetscReal,PetscInt,Vec*))
3400 {
3401   PetscFunctionBegin;
3402   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3403   ts->poststage = func;
3404   PetscFunctionReturn(0);
3405 }
3406 
3407 /*@C
3408   TSSetPostEvaluate - Sets the general-purpose function
3409   called once at the end of each step evaluation.
3410 
3411   Logically Collective on TS
3412 
3413   Input Parameters:
3414 + ts   - The TS context obtained from TSCreate()
3415 - func - The function
3416 
3417   Calling sequence of func:
3418 . PetscErrorCode func(TS ts);
3419 
3420   Level: intermediate
3421 
3422   Note:
3423   Semantically, TSSetPostEvaluate() differs from TSSetPostStep() since the function it sets is called before event-handling
3424   thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, TSPostStep()
3425   may be passed a different solution, possibly changed by the event handler. TSPostEvaluate() is called after the next step
3426   solution is evaluated allowing to modify it, if need be. The solution can be obtained with TSGetSolution(), the time step
3427   with TSGetTimeStep(), and the time at the start of the step is available via TSGetTime()
3428 
3429 .keywords: TS, timestep
3430 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3431 @*/
3432 PetscErrorCode  TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS))
3433 {
3434   PetscFunctionBegin;
3435   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3436   ts->postevaluate = func;
3437   PetscFunctionReturn(0);
3438 }
3439 
3440 /*@
3441   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
3442 
3443   Collective on TS
3444 
3445   Input Parameters:
3446 . ts          - The TS context obtained from TSCreate()
3447   stagetime   - The absolute time of the current stage
3448 
3449   Notes:
3450   TSPreStage() is typically used within time stepping implementations,
3451   most users would not generally call this routine themselves.
3452 
3453   Level: developer
3454 
3455 .keywords: TS, timestep
3456 .seealso: TSPostStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
3457 @*/
3458 PetscErrorCode  TSPreStage(TS ts, PetscReal stagetime)
3459 {
3460   PetscErrorCode ierr;
3461 
3462   PetscFunctionBegin;
3463   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3464   if (ts->prestage) {
3465     PetscStackCallStandard((*ts->prestage),(ts,stagetime));
3466   }
3467   PetscFunctionReturn(0);
3468 }
3469 
3470 /*@
3471   TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage()
3472 
3473   Collective on TS
3474 
3475   Input Parameters:
3476 . ts          - The TS context obtained from TSCreate()
3477   stagetime   - The absolute time of the current stage
3478   stageindex  - Stage number
3479   Y           - Array of vectors (of size = total number
3480                 of stages) with the stage solutions
3481 
3482   Notes:
3483   TSPostStage() is typically used within time stepping implementations,
3484   most users would not generally call this routine themselves.
3485 
3486   Level: developer
3487 
3488 .keywords: TS, timestep
3489 .seealso: TSPreStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
3490 @*/
3491 PetscErrorCode  TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
3492 {
3493   PetscErrorCode ierr;
3494 
3495   PetscFunctionBegin;
3496   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3497   if (ts->poststage) {
3498     PetscStackCallStandard((*ts->poststage),(ts,stagetime,stageindex,Y));
3499   }
3500   PetscFunctionReturn(0);
3501 }
3502 
3503 /*@
3504   TSPostEvaluate - Runs the user-defined post-evaluate function set using TSSetPostEvaluate()
3505 
3506   Collective on TS
3507 
3508   Input Parameters:
3509 . ts          - The TS context obtained from TSCreate()
3510 
3511   Notes:
3512   TSPostEvaluate() is typically used within time stepping implementations,
3513   most users would not generally call this routine themselves.
3514 
3515   Level: developer
3516 
3517 .keywords: TS, timestep
3518 .seealso: TSSetPostEvaluate(), TSSetPreStep(), TSPreStep(), TSPostStep()
3519 @*/
3520 PetscErrorCode  TSPostEvaluate(TS ts)
3521 {
3522   PetscErrorCode ierr;
3523 
3524   PetscFunctionBegin;
3525   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3526   if (ts->postevaluate) {
3527     PetscStackCallStandard((*ts->postevaluate),(ts));
3528   }
3529   PetscFunctionReturn(0);
3530 }
3531 
3532 /*@C
3533   TSSetPostStep - Sets the general-purpose function
3534   called once at the end of each time step.
3535 
3536   Logically Collective on TS
3537 
3538   Input Parameters:
3539 + ts   - The TS context obtained from TSCreate()
3540 - func - The function
3541 
3542   Calling sequence of func:
3543 $ func (TS ts);
3544 
3545   Notes:
3546   The function set by TSSetPostStep() is called after each successful step. The solution vector X
3547   obtained by TSGetSolution() may be different than that computed at the step end if the event handler
3548   locates an event and TSPostEvent() modifies it. Use TSSetPostEvaluate() if an unmodified solution is needed instead.
3549 
3550   Level: intermediate
3551 
3552 .keywords: TS, timestep
3553 .seealso: TSSetPreStep(), TSSetPreStage(), TSSetPostEvaluate(), TSGetTimeStep(), TSGetTimeStepNumber(), TSGetTime()
3554 @*/
3555 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
3556 {
3557   PetscFunctionBegin;
3558   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3559   ts->poststep = func;
3560   PetscFunctionReturn(0);
3561 }
3562 
3563 /*@
3564   TSPostStep - Runs the user-defined post-step function.
3565 
3566   Collective on TS
3567 
3568   Input Parameters:
3569 . ts   - The TS context obtained from TSCreate()
3570 
3571   Notes:
3572   TSPostStep() is typically used within time stepping implementations,
3573   so most users would not generally call this routine themselves.
3574 
3575   Level: developer
3576 
3577 .keywords: TS, timestep
3578 @*/
3579 PetscErrorCode  TSPostStep(TS ts)
3580 {
3581   PetscErrorCode ierr;
3582 
3583   PetscFunctionBegin;
3584   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3585   if (ts->poststep) {
3586     PetscStackCallStandard((*ts->poststep),(ts));
3587   }
3588   PetscFunctionReturn(0);
3589 }
3590 
3591 /* ------------ Routines to set performance monitoring options ----------- */
3592 
3593 /*@C
3594    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
3595    timestep to display the iteration's  progress.
3596 
3597    Logically Collective on TS
3598 
3599    Input Parameters:
3600 +  ts - the TS context obtained from TSCreate()
3601 .  monitor - monitoring routine
3602 .  mctx - [optional] user-defined context for private data for the
3603              monitor routine (use NULL if no context is desired)
3604 -  monitordestroy - [optional] routine that frees monitor context
3605           (may be NULL)
3606 
3607    Calling sequence of monitor:
3608 $    int monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
3609 
3610 +    ts - the TS context
3611 .    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)
3612 .    time - current time
3613 .    u - current iterate
3614 -    mctx - [optional] monitoring context
3615 
3616    Notes:
3617    This routine adds an additional monitor to the list of monitors that
3618    already has been loaded.
3619 
3620    Fortran notes: Only a single monitor function can be set for each TS object
3621 
3622    Level: intermediate
3623 
3624 .keywords: TS, timestep, set, monitor
3625 
3626 .seealso: TSMonitorDefault(), TSMonitorCancel()
3627 @*/
3628 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
3629 {
3630   PetscErrorCode ierr;
3631   PetscInt       i;
3632   PetscBool      identical;
3633 
3634   PetscFunctionBegin;
3635   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3636   for (i=0; i<ts->numbermonitors;i++) {
3637     ierr = PetscMonitorCompare((PetscErrorCode (*)(void))monitor,mctx,mdestroy,(PetscErrorCode (*)(void))ts->monitor[i],ts->monitorcontext[i],ts->monitordestroy[i],&identical);CHKERRQ(ierr);
3638     if (identical) PetscFunctionReturn(0);
3639   }
3640   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
3641   ts->monitor[ts->numbermonitors]          = monitor;
3642   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
3643   ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
3644   PetscFunctionReturn(0);
3645 }
3646 
3647 /*@C
3648    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
3649 
3650    Logically Collective on TS
3651 
3652    Input Parameters:
3653 .  ts - the TS context obtained from TSCreate()
3654 
3655    Notes:
3656    There is no way to remove a single, specific monitor.
3657 
3658    Level: intermediate
3659 
3660 .keywords: TS, timestep, set, monitor
3661 
3662 .seealso: TSMonitorDefault(), TSMonitorSet()
3663 @*/
3664 PetscErrorCode  TSMonitorCancel(TS ts)
3665 {
3666   PetscErrorCode ierr;
3667   PetscInt       i;
3668 
3669   PetscFunctionBegin;
3670   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3671   for (i=0; i<ts->numbermonitors; i++) {
3672     if (ts->monitordestroy[i]) {
3673       ierr = (*ts->monitordestroy[i])(&ts->monitorcontext[i]);CHKERRQ(ierr);
3674     }
3675   }
3676   ts->numbermonitors = 0;
3677   PetscFunctionReturn(0);
3678 }
3679 
3680 /*@C
3681    TSMonitorDefault - The Default monitor, prints the timestep and time for each step
3682 
3683    Level: intermediate
3684 
3685 .keywords: TS, set, monitor
3686 
3687 .seealso:  TSMonitorSet()
3688 @*/
3689 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscViewerAndFormat *vf)
3690 {
3691   PetscErrorCode ierr;
3692   PetscViewer    viewer =  vf->viewer;
3693   PetscBool      iascii,ibinary;
3694 
3695   PetscFunctionBegin;
3696   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
3697   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
3698   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
3699   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
3700   if (iascii) {
3701     ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3702     if (step == -1){ /* this indicates it is an interpolated solution */
3703       ierr = PetscViewerASCIIPrintf(viewer,"Interpolated solution at time %g between steps %D and %D\n",(double)ptime,ts->steps-1,ts->steps);CHKERRQ(ierr);
3704     } else {
3705       ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr);
3706     }
3707     ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3708   } else if (ibinary) {
3709     PetscMPIInt rank;
3710     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
3711     if (!rank) {
3712       PetscBool skipHeader;
3713       PetscInt  classid = REAL_FILE_CLASSID;
3714 
3715       ierr = PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);CHKERRQ(ierr);
3716       if (!skipHeader) {
3717          ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
3718        }
3719       ierr = PetscRealView(1,&ptime,viewer);CHKERRQ(ierr);
3720     } else {
3721       ierr = PetscRealView(0,&ptime,viewer);CHKERRQ(ierr);
3722     }
3723   }
3724   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
3725   PetscFunctionReturn(0);
3726 }
3727 
3728 /*@C
3729    TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every
3730    timestep to display the iteration's  progress.
3731 
3732    Logically Collective on TS
3733 
3734    Input Parameters:
3735 +  ts - the TS context obtained from TSCreate()
3736 .  adjointmonitor - monitoring routine
3737 .  adjointmctx - [optional] user-defined context for private data for the
3738              monitor routine (use NULL if no context is desired)
3739 -  adjointmonitordestroy - [optional] routine that frees monitor context
3740           (may be NULL)
3741 
3742    Calling sequence of monitor:
3743 $    int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx)
3744 
3745 +    ts - the TS context
3746 .    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
3747                                been interpolated to)
3748 .    time - current time
3749 .    u - current iterate
3750 .    numcost - number of cost functionos
3751 .    lambda - sensitivities to initial conditions
3752 .    mu - sensitivities to parameters
3753 -    adjointmctx - [optional] adjoint monitoring context
3754 
3755    Notes:
3756    This routine adds an additional monitor to the list of monitors that
3757    already has been loaded.
3758 
3759    Fortran notes: Only a single monitor function can be set for each TS object
3760 
3761    Level: intermediate
3762 
3763 .keywords: TS, timestep, set, adjoint, monitor
3764 
3765 .seealso: TSAdjointMonitorCancel()
3766 @*/
3767 PetscErrorCode  TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**))
3768 {
3769   PetscErrorCode ierr;
3770   PetscInt       i;
3771   PetscBool      identical;
3772 
3773   PetscFunctionBegin;
3774   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3775   for (i=0; i<ts->numbermonitors;i++) {
3776     ierr = PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical);CHKERRQ(ierr);
3777     if (identical) PetscFunctionReturn(0);
3778   }
3779   if (ts->numberadjointmonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set");
3780   ts->adjointmonitor[ts->numberadjointmonitors]          = adjointmonitor;
3781   ts->adjointmonitordestroy[ts->numberadjointmonitors]   = adjointmdestroy;
3782   ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx;
3783   PetscFunctionReturn(0);
3784 }
3785 
3786 /*@C
3787    TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object.
3788 
3789    Logically Collective on TS
3790 
3791    Input Parameters:
3792 .  ts - the TS context obtained from TSCreate()
3793 
3794    Notes:
3795    There is no way to remove a single, specific monitor.
3796 
3797    Level: intermediate
3798 
3799 .keywords: TS, timestep, set, adjoint, monitor
3800 
3801 .seealso: TSAdjointMonitorSet()
3802 @*/
3803 PetscErrorCode  TSAdjointMonitorCancel(TS ts)
3804 {
3805   PetscErrorCode ierr;
3806   PetscInt       i;
3807 
3808   PetscFunctionBegin;
3809   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3810   for (i=0; i<ts->numberadjointmonitors; i++) {
3811     if (ts->adjointmonitordestroy[i]) {
3812       ierr = (*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
3813     }
3814   }
3815   ts->numberadjointmonitors = 0;
3816   PetscFunctionReturn(0);
3817 }
3818 
3819 /*@C
3820    TSAdjointMonitorDefault - the default monitor of adjoint computations
3821 
3822    Level: intermediate
3823 
3824 .keywords: TS, set, monitor
3825 
3826 .seealso: TSAdjointMonitorSet()
3827 @*/
3828 PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
3829 {
3830   PetscErrorCode ierr;
3831   PetscViewer    viewer = vf->viewer;
3832 
3833   PetscFunctionBegin;
3834   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
3835   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
3836   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3837   ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr);
3838   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3839   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
3840   PetscFunctionReturn(0);
3841 }
3842 
3843 /*@
3844    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
3845 
3846    Collective on TS
3847 
3848    Input Argument:
3849 +  ts - time stepping context
3850 -  t - time to interpolate to
3851 
3852    Output Argument:
3853 .  U - state at given time
3854 
3855    Level: intermediate
3856 
3857    Developer Notes:
3858    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
3859 
3860 .keywords: TS, set
3861 
3862 .seealso: TSSetExactFinalTime(), TSSolve()
3863 @*/
3864 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
3865 {
3866   PetscErrorCode ierr;
3867 
3868   PetscFunctionBegin;
3869   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3870   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3871   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);
3872   if (!ts->ops->interpolate) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
3873   ierr = (*ts->ops->interpolate)(ts,t,U);CHKERRQ(ierr);
3874   PetscFunctionReturn(0);
3875 }
3876 
3877 /*@
3878    TSStep - Steps one time step
3879 
3880    Collective on TS
3881 
3882    Input Parameter:
3883 .  ts - the TS context obtained from TSCreate()
3884 
3885    Level: developer
3886 
3887    Notes:
3888    The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine.
3889 
3890    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
3891    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3892 
3893    This may over-step the final time provided in TSSetDuration() depending on the time-step used. TSSolve() interpolates to exactly the
3894    time provided in TSSetDuration(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
3895 
3896 .keywords: TS, timestep, solve
3897 
3898 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate()
3899 @*/
3900 PetscErrorCode  TSStep(TS ts)
3901 {
3902   PetscErrorCode   ierr;
3903   static PetscBool cite = PETSC_FALSE;
3904   PetscReal        ptime;
3905 
3906   PetscFunctionBegin;
3907   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3908   ierr = PetscCitationsRegister("@techreport{tspaper,\n"
3909                                 "  title       = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3910                                 "  author      = {Shrirang Abhyankar and Jed Brown and Emil Constantinescu and Debojyoti Ghosh and Barry F. Smith},\n"
3911                                 "  type        = {Preprint},\n"
3912                                 "  number      = {ANL/MCS-P5061-0114},\n"
3913                                 "  institution = {Argonne National Laboratory},\n"
3914                                 "  year        = {2014}\n}\n",&cite);CHKERRQ(ierr);
3915 
3916   ierr = TSSetUp(ts);CHKERRQ(ierr);
3917   ierr = TSTrajectorySetUp(ts->trajectory,ts);CHKERRQ(ierr);
3918 
3919   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()");
3920   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");
3921 
3922   if (!ts->steps) ts->ptime_prev = ts->ptime;
3923   ts->reason = TS_CONVERGED_ITERATING;
3924   ptime = ts->ptime; ts->ptime_prev_rollback = ts->ptime_prev;
3925   if (!ts->ops->step) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3926   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3927   ierr = (*ts->ops->step)(ts);CHKERRQ(ierr);
3928   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3929   ts->ptime_prev = ptime;
3930   ts->steps++; ts->total_steps++;
3931   ts->steprollback = PETSC_FALSE;
3932   ts->steprestart  = PETSC_FALSE;
3933 
3934   if (ts->reason < 0) {
3935     if (ts->errorifstepfailed) {
3936       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]);
3937       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
3938     }
3939   } else if (!ts->reason) {
3940     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
3941     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3942   }
3943   PetscFunctionReturn(0);
3944 }
3945 
3946 /*@
3947    TSAdjointStep - Steps one time step backward in the adjoint run
3948 
3949    Collective on TS
3950 
3951    Input Parameter:
3952 .  ts - the TS context obtained from TSCreate()
3953 
3954    Level: intermediate
3955 
3956 .keywords: TS, adjoint, step
3957 
3958 .seealso: TSAdjointSetUp(), TSAdjointSolve()
3959 @*/
3960 PetscErrorCode  TSAdjointStep(TS ts)
3961 {
3962   DM               dm;
3963   PetscErrorCode   ierr;
3964 
3965   PetscFunctionBegin;
3966   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3967   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3968   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
3969 
3970   ierr = VecViewFromOptions(ts->vec_sol,(PetscObject)ts,"-ts_view_solution");CHKERRQ(ierr);
3971 
3972   ts->reason = TS_CONVERGED_ITERATING;
3973   ts->ptime_prev = ts->ptime;
3974   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);
3975   ierr = PetscLogEventBegin(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
3976   ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr);
3977   ierr = PetscLogEventEnd(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
3978   ts->steps++; ts->total_steps--;
3979 
3980   if (ts->reason < 0) {
3981     if (ts->errorifstepfailed) {
3982       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]);
3983       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]);
3984       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
3985     }
3986   } else if (!ts->reason) {
3987     if (ts->steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
3988   }
3989   PetscFunctionReturn(0);
3990 }
3991 
3992 /*@
3993    TSEvaluateWLTE - Evaluate the weighted local truncation error norm
3994    at the end of a time step with a given order of accuracy.
3995 
3996    Collective on TS
3997 
3998    Input Arguments:
3999 +  ts - time stepping context
4000 .  wnormtype - norm type, either NORM_2 or NORM_INFINITY
4001 -  order - optional, desired order for the error evaluation or PETSC_DECIDE
4002 
4003    Output Arguments:
4004 +  order - optional, the actual order of the error evaluation
4005 -  wlte - the weighted local truncation error norm
4006 
4007    Level: advanced
4008 
4009    Notes:
4010    If the timestepper cannot evaluate the error in a particular step
4011    (eg. in the first step or restart steps after event handling),
4012    this routine returns wlte=-1.0 .
4013 
4014 .seealso: TSStep(), TSAdapt, TSErrorWeightedNorm()
4015 @*/
4016 PetscErrorCode TSEvaluateWLTE(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte)
4017 {
4018   PetscErrorCode ierr;
4019 
4020   PetscFunctionBegin;
4021   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4022   PetscValidType(ts,1);
4023   PetscValidLogicalCollectiveEnum(ts,wnormtype,4);
4024   if (order) PetscValidIntPointer(order,3);
4025   if (order) PetscValidLogicalCollectiveInt(ts,*order,3);
4026   PetscValidRealPointer(wlte,4);
4027   if (wnormtype != NORM_2 && wnormtype != NORM_INFINITY) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
4028   if (!ts->ops->evaluatewlte) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateWLTE not implemented for type '%s'",((PetscObject)ts)->type_name);
4029   ierr = (*ts->ops->evaluatewlte)(ts,wnormtype,order,wlte);CHKERRQ(ierr);
4030   PetscFunctionReturn(0);
4031 }
4032 
4033 /*@
4034    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
4035 
4036    Collective on TS
4037 
4038    Input Arguments:
4039 +  ts - time stepping context
4040 .  order - desired order of accuracy
4041 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
4042 
4043    Output Arguments:
4044 .  U - state at the end of the current step
4045 
4046    Level: advanced
4047 
4048    Notes:
4049    This function cannot be called until all stages have been evaluated.
4050    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.
4051 
4052 .seealso: TSStep(), TSAdapt
4053 @*/
4054 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
4055 {
4056   PetscErrorCode ierr;
4057 
4058   PetscFunctionBegin;
4059   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4060   PetscValidType(ts,1);
4061   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
4062   if (!ts->ops->evaluatestep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
4063   ierr = (*ts->ops->evaluatestep)(ts,order,U,done);CHKERRQ(ierr);
4064   PetscFunctionReturn(0);
4065 }
4066 
4067 /*@
4068  TSForwardCostIntegral - Evaluate the cost integral in the forward run.
4069 
4070  Collective on TS
4071 
4072  Input Arguments:
4073  .  ts - time stepping context
4074 
4075  Level: advanced
4076 
4077  Notes:
4078  This function cannot be called until TSStep() has been completed.
4079 
4080  .seealso: TSSolve(), TSAdjointCostIntegral()
4081  @*/
4082 PetscErrorCode TSForwardCostIntegral(TS ts)
4083 {
4084     PetscErrorCode ierr;
4085     PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4086     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);
4087     ierr = (*ts->ops->forwardintegral)(ts);CHKERRQ(ierr);
4088     PetscFunctionReturn(0);
4089 }
4090 
4091 /*@
4092    TSSolve - Steps the requested number of timesteps.
4093 
4094    Collective on TS
4095 
4096    Input Parameter:
4097 +  ts - the TS context obtained from TSCreate()
4098 -  u - the solution vector  (can be null if TSSetSolution() was used and TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP) was not used,
4099                              otherwise must contain the initial conditions and will contain the solution at the final requested time
4100 
4101    Level: beginner
4102 
4103    Notes:
4104    The final time returned by this function may be different from the time of the internally
4105    held state accessible by TSGetSolution() and TSGetTime() because the method may have
4106    stepped over the final time.
4107 
4108 .keywords: TS, timestep, solve
4109 
4110 .seealso: TSCreate(), TSSetSolution(), TSStep(), TSGetTime(), TSGetSolveTime()
4111 @*/
4112 PetscErrorCode TSSolve(TS ts,Vec u)
4113 {
4114   Vec               solution;
4115   PetscErrorCode    ierr;
4116 
4117   PetscFunctionBegin;
4118   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4119   if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2);
4120 
4121   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 */
4122     PetscValidHeaderSpecific(u,VEC_CLASSID,2);
4123     if (!ts->vec_sol || u == ts->vec_sol) {
4124       ierr = VecDuplicate(u,&solution);CHKERRQ(ierr);
4125       ierr = TSSetSolution(ts,solution);CHKERRQ(ierr);
4126       ierr = VecDestroy(&solution);CHKERRQ(ierr); /* grant ownership */
4127     }
4128     ierr = VecCopy(u,ts->vec_sol);CHKERRQ(ierr);
4129   } else if (u) {
4130     ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
4131   }
4132   ierr = TSSetUp(ts);CHKERRQ(ierr);
4133   ierr = TSTrajectorySetUp(ts->trajectory,ts);CHKERRQ(ierr);
4134 
4135   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()");
4136   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");
4137 
4138   /* reset number of steps only when the step is not restarted. ARKIMEX
4139      restarts the step after an event. Resetting these counters in such a case causes
4140      TSTrajectory to incorrectly save the output files
4141   */
4142 
4143   ts->steps             = 0;
4144   ts->ksp_its           = 0;
4145   ts->snes_its          = 0;
4146   ts->num_snes_failures = 0;
4147   ts->reject            = 0;
4148   ts->reason            = TS_CONVERGED_ITERATING;
4149 
4150   ierr = TSViewFromOptions(ts,NULL,"-ts_view_pre");CHKERRQ(ierr);
4151 
4152   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
4153     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
4154     if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
4155     ts->solvetime = ts->ptime;
4156     solution = ts->vec_sol;
4157   } else { /* Step the requested number of timesteps. */
4158     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
4159     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4160 
4161     ierr = TSTrajectorySet(ts->trajectory,ts,ts->total_steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4162     ierr = TSEventInitialize(ts->event,ts,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4163 
4164     ts->steprollback = PETSC_FALSE;
4165     ts->steprestart  = PETSC_TRUE;
4166 
4167     while (!ts->reason) {
4168       ierr = TSMonitor(ts,ts->total_steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4169       if (!ts->steprollback) {
4170         ierr = TSPreStep(ts);CHKERRQ(ierr);
4171       }
4172       ierr = TSStep(ts);CHKERRQ(ierr);
4173       if (ts->vec_costintegral && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
4174         ierr = TSForwardCostIntegral(ts);CHKERRQ(ierr);
4175       }
4176       ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
4177       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. */
4178       if (!ts->steprollback) {
4179         ierr = TSTrajectorySet(ts->trajectory,ts,ts->total_steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4180         ierr = TSPostStep(ts);CHKERRQ(ierr);
4181       }
4182     }
4183     ierr = TSMonitor(ts,ts->total_steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4184 
4185     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
4186       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
4187       ts->solvetime = ts->max_time;
4188       solution = u;
4189       ierr = TSMonitor(ts,-1,ts->solvetime,solution);CHKERRQ(ierr);
4190     } else {
4191       if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
4192       ts->solvetime = ts->ptime;
4193       solution = ts->vec_sol;
4194     }
4195   }
4196 
4197   ierr = TSViewFromOptions(ts,NULL,"-ts_view");CHKERRQ(ierr);
4198   ierr = VecViewFromOptions(solution,NULL,"-ts_view_solution");CHKERRQ(ierr);
4199   ierr = PetscObjectSAWsBlock((PetscObject)ts);CHKERRQ(ierr);
4200   if (ts->adjoint_solve) {
4201     ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
4202   }
4203   PetscFunctionReturn(0);
4204 }
4205 
4206 /*@
4207  TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run.
4208 
4209  Collective on TS
4210 
4211  Input Arguments:
4212  .  ts - time stepping context
4213 
4214  Level: advanced
4215 
4216  Notes:
4217  This function cannot be called until TSAdjointStep() has been completed.
4218 
4219  .seealso: TSAdjointSolve(), TSAdjointStep
4220  @*/
4221 PetscErrorCode TSAdjointCostIntegral(TS ts)
4222 {
4223     PetscErrorCode ierr;
4224     PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4225     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);
4226     ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr);
4227     PetscFunctionReturn(0);
4228 }
4229 
4230 /*@
4231    TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
4232 
4233    Collective on TS
4234 
4235    Input Parameter:
4236 .  ts - the TS context obtained from TSCreate()
4237 
4238    Options Database:
4239 . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial conditions
4240 
4241    Level: intermediate
4242 
4243    Notes:
4244    This must be called after a call to TSSolve() that solves the forward problem
4245 
4246    By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time
4247 
4248 .keywords: TS, timestep, solve
4249 
4250 .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep()
4251 @*/
4252 PetscErrorCode TSAdjointSolve(TS ts)
4253 {
4254   PetscErrorCode    ierr;
4255 
4256   PetscFunctionBegin;
4257   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4258   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
4259 
4260   /* reset time step and iteration counters */
4261   ts->steps             = 0;
4262   ts->ksp_its           = 0;
4263   ts->snes_its          = 0;
4264   ts->num_snes_failures = 0;
4265   ts->reject            = 0;
4266   ts->reason            = TS_CONVERGED_ITERATING;
4267 
4268   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->total_steps;
4269 
4270   if (ts->steps >= ts->adjoint_max_steps)     ts->reason = TS_CONVERGED_ITS;
4271   while (!ts->reason) {
4272     ierr = TSTrajectoryGet(ts->trajectory,ts,ts->total_steps,&ts->ptime);CHKERRQ(ierr);
4273     ierr = TSAdjointMonitor(ts,ts->total_steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
4274     ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr);
4275     ierr = TSAdjointStep(ts);CHKERRQ(ierr);
4276     if (ts->vec_costintegral && !ts->costintegralfwd) {
4277       ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr);
4278     }
4279   }
4280   ierr = TSTrajectoryGet(ts->trajectory,ts,ts->total_steps,&ts->ptime);CHKERRQ(ierr);
4281   ierr = TSAdjointMonitor(ts,ts->total_steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
4282   ts->solvetime = ts->ptime;
4283   ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr);
4284   ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr);
4285   PetscFunctionReturn(0);
4286 }
4287 
4288 /*@C
4289    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
4290 
4291    Collective on TS
4292 
4293    Input Parameters:
4294 +  ts - time stepping context obtained from TSCreate()
4295 .  step - step number that has just completed
4296 .  ptime - model time of the state
4297 -  u - state at the current model time
4298 
4299    Notes:
4300    TSMonitor() is typically used automatically within the time stepping implementations.
4301    Users would almost never call this routine directly.
4302 
4303    A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
4304 
4305    Level: developer
4306 
4307 .keywords: TS, timestep
4308 @*/
4309 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
4310 {
4311   DM             dm;
4312   PetscInt       i,n = ts->numbermonitors;
4313   PetscErrorCode ierr;
4314 
4315   PetscFunctionBegin;
4316   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4317   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4318 
4319   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4320   ierr = DMSetOutputSequenceNumber(dm,step,ptime);CHKERRQ(ierr);
4321 
4322   ierr = VecLockPush(u);CHKERRQ(ierr);
4323   for (i=0; i<n; i++) {
4324     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
4325   }
4326   ierr = VecLockPop(u);CHKERRQ(ierr);
4327   PetscFunctionReturn(0);
4328 }
4329 
4330 /*@C
4331    TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet()
4332 
4333    Collective on TS
4334 
4335    Input Parameters:
4336 +  ts - time stepping context obtained from TSCreate()
4337 .  step - step number that has just completed
4338 .  ptime - model time of the state
4339 .  u - state at the current model time
4340 .  numcost - number of cost functions (dimension of lambda  or mu)
4341 .  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
4342 -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
4343 
4344    Notes:
4345    TSAdjointMonitor() is typically used automatically within the time stepping implementations.
4346    Users would almost never call this routine directly.
4347 
4348    Level: developer
4349 
4350 .keywords: TS, timestep
4351 @*/
4352 PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu)
4353 {
4354   PetscErrorCode ierr;
4355   PetscInt       i,n = ts->numberadjointmonitors;
4356 
4357   PetscFunctionBegin;
4358   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4359   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4360   ierr = VecLockPush(u);CHKERRQ(ierr);
4361   for (i=0; i<n; i++) {
4362     ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
4363   }
4364   ierr = VecLockPop(u);CHKERRQ(ierr);
4365   PetscFunctionReturn(0);
4366 }
4367 
4368 /* ------------------------------------------------------------------------*/
4369 /*@C
4370    TSMonitorLGCtxCreate - Creates a TSMonitorLGCtx context for use with
4371    TS to monitor the solution process graphically in various ways
4372 
4373    Collective on TS
4374 
4375    Input Parameters:
4376 +  host - the X display to open, or null for the local machine
4377 .  label - the title to put in the title bar
4378 .  x, y - the screen coordinates of the upper left coordinate of the window
4379 .  m, n - the screen width and height in pixels
4380 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
4381 
4382    Output Parameter:
4383 .  ctx - the context
4384 
4385    Options Database Key:
4386 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
4387 .  -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling TSMonitorLGSetDisplayVariables() or TSMonitorLGCtxSetDisplayVariables())
4388 .  -ts_monitor_lg_error -  monitor the error
4389 .  -ts_monitor_lg_ksp_iterations - monitor the number of KSP iterations needed for each timestep
4390 .  -ts_monitor_lg_snes_iterations - monitor the number of SNES iterations needed for each timestep
4391 -  -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
4392 
4393    Notes:
4394    Use TSMonitorLGCtxDestroy() to destroy.
4395 
4396    One can provide a function that transforms the solution before plotting it with TSMonitorLGCtxSetTransform() or TSMonitorLGSetTransform()
4397 
4398    Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a TS object as the
4399    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
4400    as the first argument.
4401 
4402    One can control the names displayed for each solution or error variable with TSMonitorLGCtxSetVariableNames() or TSMonitorLGSetVariableNames()
4403 
4404 
4405    Level: intermediate
4406 
4407 .keywords: TS, monitor, line graph, residual
4408 
4409 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError(), TSMonitorDefault(), VecView(),
4410            TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
4411            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
4412            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
4413            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
4414 
4415 @*/
4416 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
4417 {
4418   PetscDraw      draw;
4419   PetscErrorCode ierr;
4420 
4421   PetscFunctionBegin;
4422   ierr = PetscNew(ctx);CHKERRQ(ierr);
4423   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&draw);CHKERRQ(ierr);
4424   ierr = PetscDrawSetFromOptions(draw);CHKERRQ(ierr);
4425   ierr = PetscDrawLGCreate(draw,1,&(*ctx)->lg);CHKERRQ(ierr);
4426   ierr = PetscDrawLGSetFromOptions((*ctx)->lg);CHKERRQ(ierr);
4427   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
4428   (*ctx)->howoften = howoften;
4429   PetscFunctionReturn(0);
4430 }
4431 
4432 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
4433 {
4434   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4435   PetscReal      x   = ptime,y;
4436   PetscErrorCode ierr;
4437 
4438   PetscFunctionBegin;
4439   if (step < 0) PetscFunctionReturn(0); /* -1 indicates an interpolated solution */
4440   if (!step) {
4441     PetscDrawAxis axis;
4442     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4443     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time","Time Step");CHKERRQ(ierr);
4444     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4445   }
4446   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
4447   y =  PetscLog10Real(y);
4448   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4449   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4450     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4451     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
4452   }
4453   PetscFunctionReturn(0);
4454 }
4455 
4456 /*@C
4457    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
4458    with TSMonitorLGCtxCreate().
4459 
4460    Collective on TSMonitorLGCtx
4461 
4462    Input Parameter:
4463 .  ctx - the monitor context
4464 
4465    Level: intermediate
4466 
4467 .keywords: TS, monitor, line graph, destroy
4468 
4469 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
4470 @*/
4471 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
4472 {
4473   PetscErrorCode ierr;
4474 
4475   PetscFunctionBegin;
4476   if ((*ctx)->transformdestroy) {
4477     ierr = ((*ctx)->transformdestroy)((*ctx)->transformctx);CHKERRQ(ierr);
4478   }
4479   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
4480   ierr = PetscStrArrayDestroy(&(*ctx)->names);CHKERRQ(ierr);
4481   ierr = PetscStrArrayDestroy(&(*ctx)->displaynames);CHKERRQ(ierr);
4482   ierr = PetscFree((*ctx)->displayvariables);CHKERRQ(ierr);
4483   ierr = PetscFree((*ctx)->displayvalues);CHKERRQ(ierr);
4484   ierr = PetscFree(*ctx);CHKERRQ(ierr);
4485   PetscFunctionReturn(0);
4486 }
4487 
4488 /*@
4489    TSGetTime - Gets the time of the most recently completed step.
4490 
4491    Not Collective
4492 
4493    Input Parameter:
4494 .  ts - the TS context obtained from TSCreate()
4495 
4496    Output Parameter:
4497 .  t  - the current time. This time may not corresponds to the final time set with TSSetDuration(), use TSGetSolveTime().
4498 
4499    Level: beginner
4500 
4501    Note:
4502    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
4503    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
4504 
4505 .seealso: TSSetInitialTimeStep(), TSGetTimeStep(), TSGetSolveTime()
4506 
4507 .keywords: TS, get, time
4508 @*/
4509 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
4510 {
4511   PetscFunctionBegin;
4512   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4513   PetscValidRealPointer(t,2);
4514   *t = ts->ptime;
4515   PetscFunctionReturn(0);
4516 }
4517 
4518 /*@
4519    TSGetPrevTime - Gets the starting time of the previously completed step.
4520 
4521    Not Collective
4522 
4523    Input Parameter:
4524 .  ts - the TS context obtained from TSCreate()
4525 
4526    Output Parameter:
4527 .  t  - the previous time
4528 
4529    Level: beginner
4530 
4531 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
4532 
4533 .keywords: TS, get, time
4534 @*/
4535 PetscErrorCode  TSGetPrevTime(TS ts,PetscReal *t)
4536 {
4537   PetscFunctionBegin;
4538   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4539   PetscValidRealPointer(t,2);
4540   *t = ts->ptime_prev;
4541   PetscFunctionReturn(0);
4542 }
4543 
4544 /*@
4545    TSSetTime - Allows one to reset the time.
4546 
4547    Logically Collective on TS
4548 
4549    Input Parameters:
4550 +  ts - the TS context obtained from TSCreate()
4551 -  time - the time
4552 
4553    Level: intermediate
4554 
4555 .seealso: TSGetTime(), TSSetDuration()
4556 
4557 .keywords: TS, set, time
4558 @*/
4559 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
4560 {
4561   PetscFunctionBegin;
4562   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4563   PetscValidLogicalCollectiveReal(ts,t,2);
4564   ts->ptime = t;
4565   PetscFunctionReturn(0);
4566 }
4567 
4568 /*@C
4569    TSSetOptionsPrefix - Sets the prefix used for searching for all
4570    TS options in the database.
4571 
4572    Logically Collective on TS
4573 
4574    Input Parameter:
4575 +  ts     - The TS context
4576 -  prefix - The prefix to prepend to all option names
4577 
4578    Notes:
4579    A hyphen (-) must NOT be given at the beginning of the prefix name.
4580    The first character of all runtime options is AUTOMATICALLY the
4581    hyphen.
4582 
4583    Level: advanced
4584 
4585 .keywords: TS, set, options, prefix, database
4586 
4587 .seealso: TSSetFromOptions()
4588 
4589 @*/
4590 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
4591 {
4592   PetscErrorCode ierr;
4593   SNES           snes;
4594 
4595   PetscFunctionBegin;
4596   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4597   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4598   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4599   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4600   PetscFunctionReturn(0);
4601 }
4602 
4603 
4604 /*@C
4605    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4606    TS options in the database.
4607 
4608    Logically Collective on TS
4609 
4610    Input Parameter:
4611 +  ts     - The TS context
4612 -  prefix - The prefix to prepend to all option names
4613 
4614    Notes:
4615    A hyphen (-) must NOT be given at the beginning of the prefix name.
4616    The first character of all runtime options is AUTOMATICALLY the
4617    hyphen.
4618 
4619    Level: advanced
4620 
4621 .keywords: TS, append, options, prefix, database
4622 
4623 .seealso: TSGetOptionsPrefix()
4624 
4625 @*/
4626 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
4627 {
4628   PetscErrorCode ierr;
4629   SNES           snes;
4630 
4631   PetscFunctionBegin;
4632   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4633   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4634   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4635   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4636   PetscFunctionReturn(0);
4637 }
4638 
4639 /*@C
4640    TSGetOptionsPrefix - Sets the prefix used for searching for all
4641    TS options in the database.
4642 
4643    Not Collective
4644 
4645    Input Parameter:
4646 .  ts - The TS context
4647 
4648    Output Parameter:
4649 .  prefix - A pointer to the prefix string used
4650 
4651    Notes: On the fortran side, the user should pass in a string 'prifix' of
4652    sufficient length to hold the prefix.
4653 
4654    Level: intermediate
4655 
4656 .keywords: TS, get, options, prefix, database
4657 
4658 .seealso: TSAppendOptionsPrefix()
4659 @*/
4660 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
4661 {
4662   PetscErrorCode ierr;
4663 
4664   PetscFunctionBegin;
4665   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4666   PetscValidPointer(prefix,2);
4667   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4668   PetscFunctionReturn(0);
4669 }
4670 
4671 /*@C
4672    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4673 
4674    Not Collective, but parallel objects are returned if TS is parallel
4675 
4676    Input Parameter:
4677 .  ts  - The TS context obtained from TSCreate()
4678 
4679    Output Parameters:
4680 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
4681 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
4682 .  func - Function to compute the Jacobian of the RHS  (or NULL)
4683 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
4684 
4685    Notes: You can pass in NULL for any return argument you do not need.
4686 
4687    Level: intermediate
4688 
4689 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
4690 
4691 .keywords: TS, timestep, get, matrix, Jacobian
4692 @*/
4693 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
4694 {
4695   PetscErrorCode ierr;
4696   DM             dm;
4697 
4698   PetscFunctionBegin;
4699   if (Amat || Pmat) {
4700     SNES snes;
4701     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4702     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4703     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4704   }
4705   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4706   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
4707   PetscFunctionReturn(0);
4708 }
4709 
4710 /*@C
4711    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4712 
4713    Not Collective, but parallel objects are returned if TS is parallel
4714 
4715    Input Parameter:
4716 .  ts  - The TS context obtained from TSCreate()
4717 
4718    Output Parameters:
4719 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
4720 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
4721 .  f   - The function to compute the matrices
4722 - ctx - User-defined context for Jacobian evaluation routine
4723 
4724    Notes: You can pass in NULL for any return argument you do not need.
4725 
4726    Level: advanced
4727 
4728 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
4729 
4730 .keywords: TS, timestep, get, matrix, Jacobian
4731 @*/
4732 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
4733 {
4734   PetscErrorCode ierr;
4735   DM             dm;
4736 
4737   PetscFunctionBegin;
4738   if (Amat || Pmat) {
4739     SNES snes;
4740     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4741     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4742     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4743   }
4744   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4745   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
4746   PetscFunctionReturn(0);
4747 }
4748 
4749 
4750 /*@C
4751    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
4752    VecView() for the solution at each timestep
4753 
4754    Collective on TS
4755 
4756    Input Parameters:
4757 +  ts - the TS context
4758 .  step - current time-step
4759 .  ptime - current time
4760 -  dummy - either a viewer or NULL
4761 
4762    Options Database:
4763 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
4764 
4765    Notes: the initial solution and current solution are not display with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
4766        will look bad
4767 
4768    Level: intermediate
4769 
4770 .keywords: TS,  vector, monitor, view
4771 
4772 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4773 @*/
4774 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4775 {
4776   PetscErrorCode   ierr;
4777   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
4778   PetscDraw        draw;
4779 
4780   PetscFunctionBegin;
4781   if (!step && ictx->showinitial) {
4782     if (!ictx->initialsolution) {
4783       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
4784     }
4785     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
4786   }
4787   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4788 
4789   if (ictx->showinitial) {
4790     PetscReal pause;
4791     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
4792     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
4793     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
4794     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
4795     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
4796   }
4797   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
4798   if (ictx->showtimestepandtime) {
4799     PetscReal xl,yl,xr,yr,h;
4800     char      time[32];
4801 
4802     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4803     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4804     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4805     h    = yl + .95*(yr - yl);
4806     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4807     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4808   }
4809 
4810   if (ictx->showinitial) {
4811     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
4812   }
4813   PetscFunctionReturn(0);
4814 }
4815 
4816 /*@C
4817    TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling
4818    VecView() for the sensitivities to initial states at each timestep
4819 
4820    Collective on TS
4821 
4822    Input Parameters:
4823 +  ts - the TS context
4824 .  step - current time-step
4825 .  ptime - current time
4826 .  u - current state
4827 .  numcost - number of cost functions
4828 .  lambda - sensitivities to initial conditions
4829 .  mu - sensitivities to parameters
4830 -  dummy - either a viewer or NULL
4831 
4832    Level: intermediate
4833 
4834 .keywords: TS,  vector, adjoint, monitor, view
4835 
4836 .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView()
4837 @*/
4838 PetscErrorCode  TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy)
4839 {
4840   PetscErrorCode   ierr;
4841   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
4842   PetscDraw        draw;
4843   PetscReal        xl,yl,xr,yr,h;
4844   char             time[32];
4845 
4846   PetscFunctionBegin;
4847   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4848 
4849   ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr);
4850   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4851   ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4852   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4853   h    = yl + .95*(yr - yl);
4854   ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4855   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4856   PetscFunctionReturn(0);
4857 }
4858 
4859 /*@C
4860    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
4861 
4862    Collective on TS
4863 
4864    Input Parameters:
4865 +  ts - the TS context
4866 .  step - current time-step
4867 .  ptime - current time
4868 -  dummy - either a viewer or NULL
4869 
4870    Level: intermediate
4871 
4872 .keywords: TS,  vector, monitor, view
4873 
4874 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4875 @*/
4876 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4877 {
4878   PetscErrorCode    ierr;
4879   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
4880   PetscDraw         draw;
4881   PetscDrawAxis     axis;
4882   PetscInt          n;
4883   PetscMPIInt       size;
4884   PetscReal         U0,U1,xl,yl,xr,yr,h;
4885   char              time[32];
4886   const PetscScalar *U;
4887 
4888   PetscFunctionBegin;
4889   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)ts),&size);CHKERRQ(ierr);
4890   if (size != 1) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only allowed for sequential runs");
4891   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
4892   if (n != 2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only for ODEs with two unknowns");
4893 
4894   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4895   ierr = PetscViewerDrawGetDrawAxis(ictx->viewer,0,&axis);CHKERRQ(ierr);
4896   ierr = PetscDrawAxisGetLimits(axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
4897   if (!step) {
4898     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
4899     ierr = PetscDrawAxisDraw(axis);CHKERRQ(ierr);
4900   }
4901 
4902   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
4903   U0 = PetscRealPart(U[0]);
4904   U1 = PetscRealPart(U[1]);
4905   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
4906   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(0);
4907 
4908   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
4909   ierr = PetscDrawPoint(draw,U0,U1,PETSC_DRAW_BLACK);CHKERRQ(ierr);
4910   if (ictx->showtimestepandtime) {
4911     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4912     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4913     h    = yl + .95*(yr - yl);
4914     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4915   }
4916   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
4917   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4918   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
4919   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
4920   PetscFunctionReturn(0);
4921 }
4922 
4923 
4924 /*@C
4925    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
4926 
4927    Collective on TS
4928 
4929    Input Parameters:
4930 .    ctx - the monitor context
4931 
4932    Level: intermediate
4933 
4934 .keywords: TS,  vector, monitor, view
4935 
4936 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
4937 @*/
4938 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
4939 {
4940   PetscErrorCode ierr;
4941 
4942   PetscFunctionBegin;
4943   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
4944   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
4945   ierr = PetscFree(*ictx);CHKERRQ(ierr);
4946   PetscFunctionReturn(0);
4947 }
4948 
4949 /*@C
4950    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
4951 
4952    Collective on TS
4953 
4954    Input Parameter:
4955 .    ts - time-step context
4956 
4957    Output Patameter:
4958 .    ctx - the monitor context
4959 
4960    Options Database:
4961 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
4962 
4963    Level: intermediate
4964 
4965 .keywords: TS,  vector, monitor, view
4966 
4967 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
4968 @*/
4969 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
4970 {
4971   PetscErrorCode   ierr;
4972 
4973   PetscFunctionBegin;
4974   ierr = PetscNew(ctx);CHKERRQ(ierr);
4975   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
4976   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
4977 
4978   (*ctx)->howoften    = howoften;
4979   (*ctx)->showinitial = PETSC_FALSE;
4980   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
4981 
4982   (*ctx)->showtimestepandtime = PETSC_FALSE;
4983   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
4984   PetscFunctionReturn(0);
4985 }
4986 
4987 /*@C
4988    TSMonitorDrawError - Monitors progress of the TS solvers by calling
4989    VecView() for the error at each timestep
4990 
4991    Collective on TS
4992 
4993    Input Parameters:
4994 +  ts - the TS context
4995 .  step - current time-step
4996 .  ptime - current time
4997 -  dummy - either a viewer or NULL
4998 
4999    Level: intermediate
5000 
5001 .keywords: TS,  vector, monitor, view
5002 
5003 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5004 @*/
5005 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5006 {
5007   PetscErrorCode   ierr;
5008   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
5009   PetscViewer      viewer = ctx->viewer;
5010   Vec              work;
5011 
5012   PetscFunctionBegin;
5013   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
5014   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
5015   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
5016   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
5017   ierr = VecView(work,viewer);CHKERRQ(ierr);
5018   ierr = VecDestroy(&work);CHKERRQ(ierr);
5019   PetscFunctionReturn(0);
5020 }
5021 
5022 #include <petsc/private/dmimpl.h>
5023 /*@
5024    TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS
5025 
5026    Logically Collective on TS and DM
5027 
5028    Input Parameters:
5029 +  ts - the ODE integrator object
5030 -  dm - the dm, cannot be NULL
5031 
5032    Level: intermediate
5033 
5034 
5035 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
5036 @*/
5037 PetscErrorCode  TSSetDM(TS ts,DM dm)
5038 {
5039   PetscErrorCode ierr;
5040   SNES           snes;
5041   DMTS           tsdm;
5042 
5043   PetscFunctionBegin;
5044   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5045   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
5046   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
5047   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
5048     if (ts->dm->dmts && !dm->dmts) {
5049       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
5050       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
5051       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
5052         tsdm->originaldm = dm;
5053       }
5054     }
5055     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
5056   }
5057   ts->dm = dm;
5058 
5059   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
5060   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
5061   PetscFunctionReturn(0);
5062 }
5063 
5064 /*@
5065    TSGetDM - Gets the DM that may be used by some preconditioners
5066 
5067    Not Collective
5068 
5069    Input Parameter:
5070 . ts - the preconditioner context
5071 
5072    Output Parameter:
5073 .  dm - the dm
5074 
5075    Level: intermediate
5076 
5077 
5078 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
5079 @*/
5080 PetscErrorCode  TSGetDM(TS ts,DM *dm)
5081 {
5082   PetscErrorCode ierr;
5083 
5084   PetscFunctionBegin;
5085   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5086   if (!ts->dm) {
5087     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
5088     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
5089   }
5090   *dm = ts->dm;
5091   PetscFunctionReturn(0);
5092 }
5093 
5094 /*@
5095    SNESTSFormFunction - Function to evaluate nonlinear residual
5096 
5097    Logically Collective on SNES
5098 
5099    Input Parameter:
5100 + snes - nonlinear solver
5101 . U - the current state at which to evaluate the residual
5102 - ctx - user context, must be a TS
5103 
5104    Output Parameter:
5105 . F - the nonlinear residual
5106 
5107    Notes:
5108    This function is not normally called by users and is automatically registered with the SNES used by TS.
5109    It is most frequently passed to MatFDColoringSetFunction().
5110 
5111    Level: advanced
5112 
5113 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
5114 @*/
5115 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
5116 {
5117   TS             ts = (TS)ctx;
5118   PetscErrorCode ierr;
5119 
5120   PetscFunctionBegin;
5121   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
5122   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5123   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
5124   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
5125   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
5126   PetscFunctionReturn(0);
5127 }
5128 
5129 /*@
5130    SNESTSFormJacobian - Function to evaluate the Jacobian
5131 
5132    Collective on SNES
5133 
5134    Input Parameter:
5135 + snes - nonlinear solver
5136 . U - the current state at which to evaluate the residual
5137 - ctx - user context, must be a TS
5138 
5139    Output Parameter:
5140 + A - the Jacobian
5141 . B - the preconditioning matrix (may be the same as A)
5142 - flag - indicates any structure change in the matrix
5143 
5144    Notes:
5145    This function is not normally called by users and is automatically registered with the SNES used by TS.
5146 
5147    Level: developer
5148 
5149 .seealso: SNESSetJacobian()
5150 @*/
5151 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
5152 {
5153   TS             ts = (TS)ctx;
5154   PetscErrorCode ierr;
5155 
5156   PetscFunctionBegin;
5157   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
5158   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5159   PetscValidPointer(A,3);
5160   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
5161   PetscValidPointer(B,4);
5162   PetscValidHeaderSpecific(B,MAT_CLASSID,4);
5163   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
5164   ierr = (ts->ops->snesjacobian)(snes,U,A,B,ts);CHKERRQ(ierr);
5165   PetscFunctionReturn(0);
5166 }
5167 
5168 /*@C
5169    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only
5170 
5171    Collective on TS
5172 
5173    Input Arguments:
5174 +  ts - time stepping context
5175 .  t - time at which to evaluate
5176 .  U - state at which to evaluate
5177 -  ctx - context
5178 
5179    Output Arguments:
5180 .  F - right hand side
5181 
5182    Level: intermediate
5183 
5184    Notes:
5185    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
5186    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
5187 
5188 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
5189 @*/
5190 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
5191 {
5192   PetscErrorCode ierr;
5193   Mat            Arhs,Brhs;
5194 
5195   PetscFunctionBegin;
5196   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
5197   ierr = TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);CHKERRQ(ierr);
5198   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
5199   PetscFunctionReturn(0);
5200 }
5201 
5202 /*@C
5203    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
5204 
5205    Collective on TS
5206 
5207    Input Arguments:
5208 +  ts - time stepping context
5209 .  t - time at which to evaluate
5210 .  U - state at which to evaluate
5211 -  ctx - context
5212 
5213    Output Arguments:
5214 +  A - pointer to operator
5215 .  B - pointer to preconditioning matrix
5216 -  flg - matrix structure flag
5217 
5218    Level: intermediate
5219 
5220    Notes:
5221    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
5222 
5223 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
5224 @*/
5225 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
5226 {
5227   PetscFunctionBegin;
5228   PetscFunctionReturn(0);
5229 }
5230 
5231 /*@C
5232    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
5233 
5234    Collective on TS
5235 
5236    Input Arguments:
5237 +  ts - time stepping context
5238 .  t - time at which to evaluate
5239 .  U - state at which to evaluate
5240 .  Udot - time derivative of state vector
5241 -  ctx - context
5242 
5243    Output Arguments:
5244 .  F - left hand side
5245 
5246    Level: intermediate
5247 
5248    Notes:
5249    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
5250    user is required to write their own TSComputeIFunction.
5251    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
5252    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
5253 
5254    Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U
5255 
5256 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant(), TSComputeRHSFunctionLinear()
5257 @*/
5258 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
5259 {
5260   PetscErrorCode ierr;
5261   Mat            A,B;
5262 
5263   PetscFunctionBegin;
5264   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
5265   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE);CHKERRQ(ierr);
5266   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
5267   PetscFunctionReturn(0);
5268 }
5269 
5270 /*@C
5271    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
5272 
5273    Collective on TS
5274 
5275    Input Arguments:
5276 +  ts - time stepping context
5277 .  t - time at which to evaluate
5278 .  U - state at which to evaluate
5279 .  Udot - time derivative of state vector
5280 .  shift - shift to apply
5281 -  ctx - context
5282 
5283    Output Arguments:
5284 +  A - pointer to operator
5285 .  B - pointer to preconditioning matrix
5286 -  flg - matrix structure flag
5287 
5288    Level: advanced
5289 
5290    Notes:
5291    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
5292 
5293    It is only appropriate for problems of the form
5294 
5295 $     M Udot = F(U,t)
5296 
5297   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
5298   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
5299   an implicit operator of the form
5300 
5301 $    shift*M + J
5302 
5303   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
5304   a copy of M or reassemble it when requested.
5305 
5306 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
5307 @*/
5308 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
5309 {
5310   PetscErrorCode ierr;
5311 
5312   PetscFunctionBegin;
5313   ierr = MatScale(A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
5314   ts->ijacobian.shift = shift;
5315   PetscFunctionReturn(0);
5316 }
5317 
5318 /*@
5319    TSGetEquationType - Gets the type of the equation that TS is solving.
5320 
5321    Not Collective
5322 
5323    Input Parameter:
5324 .  ts - the TS context
5325 
5326    Output Parameter:
5327 .  equation_type - see TSEquationType
5328 
5329    Level: beginner
5330 
5331 .keywords: TS, equation type
5332 
5333 .seealso: TSSetEquationType(), TSEquationType
5334 @*/
5335 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
5336 {
5337   PetscFunctionBegin;
5338   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5339   PetscValidPointer(equation_type,2);
5340   *equation_type = ts->equation_type;
5341   PetscFunctionReturn(0);
5342 }
5343 
5344 /*@
5345    TSSetEquationType - Sets the type of the equation that TS is solving.
5346 
5347    Not Collective
5348 
5349    Input Parameter:
5350 +  ts - the TS context
5351 -  equation_type - see TSEquationType
5352 
5353    Level: advanced
5354 
5355 .keywords: TS, equation type
5356 
5357 .seealso: TSGetEquationType(), TSEquationType
5358 @*/
5359 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
5360 {
5361   PetscFunctionBegin;
5362   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5363   ts->equation_type = equation_type;
5364   PetscFunctionReturn(0);
5365 }
5366 
5367 /*@
5368    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
5369 
5370    Not Collective
5371 
5372    Input Parameter:
5373 .  ts - the TS context
5374 
5375    Output Parameter:
5376 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5377             manual pages for the individual convergence tests for complete lists
5378 
5379    Level: beginner
5380 
5381    Notes:
5382    Can only be called after the call to TSSolve() is complete.
5383 
5384 .keywords: TS, nonlinear, set, convergence, test
5385 
5386 .seealso: TSSetConvergenceTest(), TSConvergedReason
5387 @*/
5388 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
5389 {
5390   PetscFunctionBegin;
5391   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5392   PetscValidPointer(reason,2);
5393   *reason = ts->reason;
5394   PetscFunctionReturn(0);
5395 }
5396 
5397 /*@
5398    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
5399 
5400    Not Collective
5401 
5402    Input Parameter:
5403 +  ts - the TS context
5404 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5405             manual pages for the individual convergence tests for complete lists
5406 
5407    Level: advanced
5408 
5409    Notes:
5410    Can only be called during TSSolve() is active.
5411 
5412 .keywords: TS, nonlinear, set, convergence, test
5413 
5414 .seealso: TSConvergedReason
5415 @*/
5416 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
5417 {
5418   PetscFunctionBegin;
5419   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5420   ts->reason = reason;
5421   PetscFunctionReturn(0);
5422 }
5423 
5424 /*@
5425    TSGetSolveTime - Gets the time after a call to TSSolve()
5426 
5427    Not Collective
5428 
5429    Input Parameter:
5430 .  ts - the TS context
5431 
5432    Output Parameter:
5433 .  ftime - the final time. This time corresponds to the final time set with TSSetDuration()
5434 
5435    Level: beginner
5436 
5437    Notes:
5438    Can only be called after the call to TSSolve() is complete.
5439 
5440 .keywords: TS, nonlinear, set, convergence, test
5441 
5442 .seealso: TSSetConvergenceTest(), TSConvergedReason
5443 @*/
5444 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
5445 {
5446   PetscFunctionBegin;
5447   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5448   PetscValidPointer(ftime,2);
5449   *ftime = ts->solvetime;
5450   PetscFunctionReturn(0);
5451 }
5452 
5453 /*@
5454    TSGetTotalSteps - Gets the total number of steps done since the last call to TSSetUp() or TSCreate()
5455 
5456    Not Collective
5457 
5458    Input Parameter:
5459 .  ts - the TS context
5460 
5461    Output Parameter:
5462 .  steps - the number of steps
5463 
5464    Level: beginner
5465 
5466    Notes:
5467    Includes the number of steps for all calls to TSSolve() since TSSetUp() was called
5468 
5469 .keywords: TS, nonlinear, set, convergence, test
5470 
5471 .seealso: TSSetConvergenceTest(), TSConvergedReason
5472 @*/
5473 PetscErrorCode  TSGetTotalSteps(TS ts,PetscInt *steps)
5474 {
5475   PetscFunctionBegin;
5476   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5477   PetscValidPointer(steps,2);
5478   *steps = ts->total_steps;
5479   PetscFunctionReturn(0);
5480 }
5481 
5482 /*@
5483    TSGetSNESIterations - Gets the total number of nonlinear iterations
5484    used by the time integrator.
5485 
5486    Not Collective
5487 
5488    Input Parameter:
5489 .  ts - TS context
5490 
5491    Output Parameter:
5492 .  nits - number of nonlinear iterations
5493 
5494    Notes:
5495    This counter is reset to zero for each successive call to TSSolve().
5496 
5497    Level: intermediate
5498 
5499 .keywords: TS, get, number, nonlinear, iterations
5500 
5501 .seealso:  TSGetKSPIterations()
5502 @*/
5503 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
5504 {
5505   PetscFunctionBegin;
5506   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5507   PetscValidIntPointer(nits,2);
5508   *nits = ts->snes_its;
5509   PetscFunctionReturn(0);
5510 }
5511 
5512 /*@
5513    TSGetKSPIterations - Gets the total number of linear iterations
5514    used by the time integrator.
5515 
5516    Not Collective
5517 
5518    Input Parameter:
5519 .  ts - TS context
5520 
5521    Output Parameter:
5522 .  lits - number of linear iterations
5523 
5524    Notes:
5525    This counter is reset to zero for each successive call to TSSolve().
5526 
5527    Level: intermediate
5528 
5529 .keywords: TS, get, number, linear, iterations
5530 
5531 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
5532 @*/
5533 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
5534 {
5535   PetscFunctionBegin;
5536   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5537   PetscValidIntPointer(lits,2);
5538   *lits = ts->ksp_its;
5539   PetscFunctionReturn(0);
5540 }
5541 
5542 /*@
5543    TSGetStepRejections - Gets the total number of rejected steps.
5544 
5545    Not Collective
5546 
5547    Input Parameter:
5548 .  ts - TS context
5549 
5550    Output Parameter:
5551 .  rejects - number of steps rejected
5552 
5553    Notes:
5554    This counter is reset to zero for each successive call to TSSolve().
5555 
5556    Level: intermediate
5557 
5558 .keywords: TS, get, number
5559 
5560 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
5561 @*/
5562 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
5563 {
5564   PetscFunctionBegin;
5565   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5566   PetscValidIntPointer(rejects,2);
5567   *rejects = ts->reject;
5568   PetscFunctionReturn(0);
5569 }
5570 
5571 /*@
5572    TSGetSNESFailures - Gets the total number of failed SNES solves
5573 
5574    Not Collective
5575 
5576    Input Parameter:
5577 .  ts - TS context
5578 
5579    Output Parameter:
5580 .  fails - number of failed nonlinear solves
5581 
5582    Notes:
5583    This counter is reset to zero for each successive call to TSSolve().
5584 
5585    Level: intermediate
5586 
5587 .keywords: TS, get, number
5588 
5589 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
5590 @*/
5591 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
5592 {
5593   PetscFunctionBegin;
5594   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5595   PetscValidIntPointer(fails,2);
5596   *fails = ts->num_snes_failures;
5597   PetscFunctionReturn(0);
5598 }
5599 
5600 /*@
5601    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
5602 
5603    Not Collective
5604 
5605    Input Parameter:
5606 +  ts - TS context
5607 -  rejects - maximum number of rejected steps, pass -1 for unlimited
5608 
5609    Notes:
5610    The counter is reset to zero for each step
5611 
5612    Options Database Key:
5613  .  -ts_max_reject - Maximum number of step rejections before a step fails
5614 
5615    Level: intermediate
5616 
5617 .keywords: TS, set, maximum, number
5618 
5619 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5620 @*/
5621 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
5622 {
5623   PetscFunctionBegin;
5624   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5625   ts->max_reject = rejects;
5626   PetscFunctionReturn(0);
5627 }
5628 
5629 /*@
5630    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
5631 
5632    Not Collective
5633 
5634    Input Parameter:
5635 +  ts - TS context
5636 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
5637 
5638    Notes:
5639    The counter is reset to zero for each successive call to TSSolve().
5640 
5641    Options Database Key:
5642  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
5643 
5644    Level: intermediate
5645 
5646 .keywords: TS, set, maximum, number
5647 
5648 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
5649 @*/
5650 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
5651 {
5652   PetscFunctionBegin;
5653   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5654   ts->max_snes_failures = fails;
5655   PetscFunctionReturn(0);
5656 }
5657 
5658 /*@
5659    TSSetErrorIfStepFails - Error if no step succeeds
5660 
5661    Not Collective
5662 
5663    Input Parameter:
5664 +  ts - TS context
5665 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
5666 
5667    Options Database Key:
5668  .  -ts_error_if_step_fails - Error if no step succeeds
5669 
5670    Level: intermediate
5671 
5672 .keywords: TS, set, error
5673 
5674 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5675 @*/
5676 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
5677 {
5678   PetscFunctionBegin;
5679   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5680   ts->errorifstepfailed = err;
5681   PetscFunctionReturn(0);
5682 }
5683 
5684 /*@C
5685    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
5686 
5687    Collective on TS
5688 
5689    Input Parameters:
5690 +  ts - the TS context
5691 .  step - current time-step
5692 .  ptime - current time
5693 .  u - current state
5694 -  vf - viewer and its format
5695 
5696    Level: intermediate
5697 
5698 .keywords: TS,  vector, monitor, view
5699 
5700 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5701 @*/
5702 PetscErrorCode  TSMonitorSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
5703 {
5704   PetscErrorCode ierr;
5705 
5706   PetscFunctionBegin;
5707   ierr = PetscViewerPushFormat(vf->viewer,vf->format);CHKERRQ(ierr);
5708   ierr = VecView(u,vf->viewer);CHKERRQ(ierr);
5709   ierr = PetscViewerPopFormat(vf->viewer);CHKERRQ(ierr);
5710   PetscFunctionReturn(0);
5711 }
5712 
5713 /*@C
5714    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
5715 
5716    Collective on TS
5717 
5718    Input Parameters:
5719 +  ts - the TS context
5720 .  step - current time-step
5721 .  ptime - current time
5722 .  u - current state
5723 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5724 
5725    Level: intermediate
5726 
5727    Notes:
5728    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.
5729    These are named according to the file name template.
5730 
5731    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
5732 
5733 .keywords: TS,  vector, monitor, view
5734 
5735 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5736 @*/
5737 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
5738 {
5739   PetscErrorCode ierr;
5740   char           filename[PETSC_MAX_PATH_LEN];
5741   PetscViewer    viewer;
5742 
5743   PetscFunctionBegin;
5744   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
5745   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
5746   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
5747   ierr = VecView(u,viewer);CHKERRQ(ierr);
5748   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5749   PetscFunctionReturn(0);
5750 }
5751 
5752 /*@C
5753    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
5754 
5755    Collective on TS
5756 
5757    Input Parameters:
5758 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5759 
5760    Level: intermediate
5761 
5762    Note:
5763    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
5764 
5765 .keywords: TS,  vector, monitor, view
5766 
5767 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
5768 @*/
5769 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
5770 {
5771   PetscErrorCode ierr;
5772 
5773   PetscFunctionBegin;
5774   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
5775   PetscFunctionReturn(0);
5776 }
5777 
5778 /*@
5779    TSGetAdapt - Get the adaptive controller context for the current method
5780 
5781    Collective on TS if controller has not been created yet
5782 
5783    Input Arguments:
5784 .  ts - time stepping context
5785 
5786    Output Arguments:
5787 .  adapt - adaptive controller
5788 
5789    Level: intermediate
5790 
5791 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
5792 @*/
5793 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
5794 {
5795   PetscErrorCode ierr;
5796 
5797   PetscFunctionBegin;
5798   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5799   PetscValidPointer(adapt,2);
5800   if (!ts->adapt) {
5801     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
5802     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt);CHKERRQ(ierr);
5803     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
5804   }
5805   *adapt = ts->adapt;
5806   PetscFunctionReturn(0);
5807 }
5808 
5809 /*@
5810    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
5811 
5812    Logically Collective
5813 
5814    Input Arguments:
5815 +  ts - time integration context
5816 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
5817 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
5818 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
5819 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
5820 
5821    Options Database keys:
5822 +  -ts_rtol <rtol> - relative tolerance for local truncation error
5823 -  -ts_atol <atol> Absolute tolerance for local truncation error
5824 
5825    Notes:
5826    With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5827    (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5828    computed only for the differential or the algebraic part then this can be done using the vector of
5829    tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5830    differential part and infinity for the algebraic part, the LTE calculation will include only the
5831    differential variables.
5832 
5833    Level: beginner
5834 
5835 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
5836 @*/
5837 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
5838 {
5839   PetscErrorCode ierr;
5840 
5841   PetscFunctionBegin;
5842   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
5843   if (vatol) {
5844     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
5845     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
5846     ts->vatol = vatol;
5847   }
5848   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
5849   if (vrtol) {
5850     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
5851     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
5852     ts->vrtol = vrtol;
5853   }
5854   PetscFunctionReturn(0);
5855 }
5856 
5857 /*@
5858    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
5859 
5860    Logically Collective
5861 
5862    Input Arguments:
5863 .  ts - time integration context
5864 
5865    Output Arguments:
5866 +  atol - scalar absolute tolerances, NULL to ignore
5867 .  vatol - vector of absolute tolerances, NULL to ignore
5868 .  rtol - scalar relative tolerances, NULL to ignore
5869 -  vrtol - vector of relative tolerances, NULL to ignore
5870 
5871    Level: beginner
5872 
5873 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
5874 @*/
5875 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
5876 {
5877   PetscFunctionBegin;
5878   if (atol)  *atol  = ts->atol;
5879   if (vatol) *vatol = ts->vatol;
5880   if (rtol)  *rtol  = ts->rtol;
5881   if (vrtol) *vrtol = ts->vrtol;
5882   PetscFunctionReturn(0);
5883 }
5884 
5885 /*@
5886    TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors
5887 
5888    Collective on TS
5889 
5890    Input Arguments:
5891 +  ts - time stepping context
5892 .  U - state vector, usually ts->vec_sol
5893 -  Y - state vector to be compared to U
5894 
5895    Output Arguments:
5896 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5897 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5898 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5899 
5900    Level: developer
5901 
5902 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNormInfinity()
5903 @*/
5904 PetscErrorCode TSErrorWeightedNorm2(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5905 {
5906   PetscErrorCode    ierr;
5907   PetscInt          i,n,N,rstart;
5908   PetscInt          n_loc,na_loc,nr_loc;
5909   PetscReal         n_glb,na_glb,nr_glb;
5910   const PetscScalar *u,*y;
5911   PetscReal         sum,suma,sumr,gsum,gsuma,gsumr,diff;
5912   PetscReal         tol,tola,tolr;
5913   PetscReal         err_loc[6],err_glb[6];
5914 
5915   PetscFunctionBegin;
5916   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5917   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5918   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
5919   PetscValidType(U,2);
5920   PetscValidType(Y,3);
5921   PetscCheckSameComm(U,2,Y,3);
5922   PetscValidPointer(norm,4);
5923   PetscValidPointer(norma,5);
5924   PetscValidPointer(normr,6);
5925   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
5926 
5927   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
5928   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
5929   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
5930   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5931   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5932   sum  = 0.; n_loc  = 0;
5933   suma = 0.; na_loc = 0;
5934   sumr = 0.; nr_loc = 0;
5935   if (ts->vatol && ts->vrtol) {
5936     const PetscScalar *atol,*rtol;
5937     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5938     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5939     for (i=0; i<n; i++) {
5940       diff = PetscAbsScalar(y[i] - u[i]);
5941       tola = PetscRealPart(atol[i]);
5942       if(tola>0.){
5943         suma  += PetscSqr(diff/tola);
5944         na_loc++;
5945       }
5946       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5947       if(tolr>0.){
5948         sumr  += PetscSqr(diff/tolr);
5949         nr_loc++;
5950       }
5951       tol=tola+tolr;
5952       if(tol>0.){
5953         sum  += PetscSqr(diff/tol);
5954         n_loc++;
5955       }
5956     }
5957     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5958     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5959   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5960     const PetscScalar *atol;
5961     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5962     for (i=0; i<n; i++) {
5963       diff = PetscAbsScalar(y[i] - u[i]);
5964       tola = PetscRealPart(atol[i]);
5965       if(tola>0.){
5966         suma  += PetscSqr(diff/tola);
5967         na_loc++;
5968       }
5969       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5970       if(tolr>0.){
5971         sumr  += PetscSqr(diff/tolr);
5972         nr_loc++;
5973       }
5974       tol=tola+tolr;
5975       if(tol>0.){
5976         sum  += PetscSqr(diff/tol);
5977         n_loc++;
5978       }
5979     }
5980     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5981   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5982     const PetscScalar *rtol;
5983     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5984     for (i=0; i<n; i++) {
5985       diff = PetscAbsScalar(y[i] - u[i]);
5986       tola = ts->atol;
5987       if(tola>0.){
5988         suma  += PetscSqr(diff/tola);
5989         na_loc++;
5990       }
5991       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5992       if(tolr>0.){
5993         sumr  += PetscSqr(diff/tolr);
5994         nr_loc++;
5995       }
5996       tol=tola+tolr;
5997       if(tol>0.){
5998         sum  += PetscSqr(diff/tol);
5999         n_loc++;
6000       }
6001     }
6002     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6003   } else {                      /* scalar atol, scalar rtol */
6004     for (i=0; i<n; i++) {
6005       diff = PetscAbsScalar(y[i] - u[i]);
6006      tola = ts->atol;
6007       if(tola>0.){
6008         suma  += PetscSqr(diff/tola);
6009         na_loc++;
6010       }
6011       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6012       if(tolr>0.){
6013         sumr  += PetscSqr(diff/tolr);
6014         nr_loc++;
6015       }
6016       tol=tola+tolr;
6017       if(tol>0.){
6018         sum  += PetscSqr(diff/tol);
6019         n_loc++;
6020       }
6021     }
6022   }
6023   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6024   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6025 
6026   err_loc[0] = sum;
6027   err_loc[1] = suma;
6028   err_loc[2] = sumr;
6029   err_loc[3] = (PetscReal)n_loc;
6030   err_loc[4] = (PetscReal)na_loc;
6031   err_loc[5] = (PetscReal)nr_loc;
6032 
6033   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6034 
6035   gsum   = err_glb[0];
6036   gsuma  = err_glb[1];
6037   gsumr  = err_glb[2];
6038   n_glb  = err_glb[3];
6039   na_glb = err_glb[4];
6040   nr_glb = err_glb[5];
6041 
6042   *norm  = 0.;
6043   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
6044   *norma = 0.;
6045   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
6046   *normr = 0.;
6047   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
6048 
6049   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6050   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6051   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6052   PetscFunctionReturn(0);
6053 }
6054 
6055 /*@
6056    TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors
6057 
6058    Collective on TS
6059 
6060    Input Arguments:
6061 +  ts - time stepping context
6062 .  U - state vector, usually ts->vec_sol
6063 -  Y - state vector to be compared to U
6064 
6065    Output Arguments:
6066 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6067 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6068 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6069 
6070    Level: developer
6071 
6072 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNorm2()
6073 @*/
6074 PetscErrorCode TSErrorWeightedNormInfinity(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6075 {
6076   PetscErrorCode    ierr;
6077   PetscInt          i,n,N,rstart;
6078   const PetscScalar *u,*y;
6079   PetscReal         max,gmax,maxa,gmaxa,maxr,gmaxr;
6080   PetscReal         tol,tola,tolr,diff;
6081   PetscReal         err_loc[3],err_glb[3];
6082 
6083   PetscFunctionBegin;
6084   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6085   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
6086   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
6087   PetscValidType(U,2);
6088   PetscValidType(Y,3);
6089   PetscCheckSameComm(U,2,Y,3);
6090   PetscValidPointer(norm,4);
6091   PetscValidPointer(norma,5);
6092   PetscValidPointer(normr,6);
6093   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
6094 
6095   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
6096   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
6097   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
6098   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6099   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6100 
6101   max=0.;
6102   maxa=0.;
6103   maxr=0.;
6104 
6105   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
6106     const PetscScalar *atol,*rtol;
6107     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6108     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6109 
6110     for (i=0; i<n; i++) {
6111       diff = PetscAbsScalar(y[i] - u[i]);
6112       tola = PetscRealPart(atol[i]);
6113       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6114       tol  = tola+tolr;
6115       if(tola>0.){
6116         maxa = PetscMax(maxa,diff / tola);
6117       }
6118       if(tolr>0.){
6119         maxr = PetscMax(maxr,diff / tolr);
6120       }
6121       if(tol>0.){
6122         max = PetscMax(max,diff / tol);
6123       }
6124     }
6125     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6126     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6127   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6128     const PetscScalar *atol;
6129     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6130     for (i=0; i<n; i++) {
6131       diff = PetscAbsScalar(y[i] - u[i]);
6132       tola = PetscRealPart(atol[i]);
6133       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6134       tol  = tola+tolr;
6135       if(tola>0.){
6136         maxa = PetscMax(maxa,diff / tola);
6137       }
6138       if(tolr>0.){
6139         maxr = PetscMax(maxr,diff / tolr);
6140       }
6141       if(tol>0.){
6142         max = PetscMax(max,diff / tol);
6143       }
6144     }
6145     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6146   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6147     const PetscScalar *rtol;
6148     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6149 
6150     for (i=0; i<n; i++) {
6151       diff = PetscAbsScalar(y[i] - u[i]);
6152       tola = ts->atol;
6153       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6154       tol  = tola+tolr;
6155       if(tola>0.){
6156         maxa = PetscMax(maxa,diff / tola);
6157       }
6158       if(tolr>0.){
6159         maxr = PetscMax(maxr,diff / tolr);
6160       }
6161       if(tol>0.){
6162         max = PetscMax(max,diff / tol);
6163       }
6164     }
6165     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6166   } else {                      /* scalar atol, scalar rtol */
6167 
6168     for (i=0; i<n; i++) {
6169       diff = PetscAbsScalar(y[i] - u[i]);
6170       tola = ts->atol;
6171       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6172       tol  = tola+tolr;
6173       if(tola>0.){
6174         maxa = PetscMax(maxa,diff / tola);
6175       }
6176       if(tolr>0.){
6177         maxr = PetscMax(maxr,diff / tolr);
6178       }
6179       if(tol>0.){
6180         max = PetscMax(max,diff / tol);
6181       }
6182     }
6183   }
6184   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6185   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6186   err_loc[0] = max;
6187   err_loc[1] = maxa;
6188   err_loc[2] = maxr;
6189   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6190   gmax   = err_glb[0];
6191   gmaxa  = err_glb[1];
6192   gmaxr  = err_glb[2];
6193 
6194   *norm = gmax;
6195   *norma = gmaxa;
6196   *normr = gmaxr;
6197   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6198     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6199     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6200   PetscFunctionReturn(0);
6201 }
6202 
6203 /*@
6204    TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
6205 
6206    Collective on TS
6207 
6208    Input Arguments:
6209 +  ts - time stepping context
6210 .  U - state vector, usually ts->vec_sol
6211 .  Y - state vector to be compared to U
6212 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6213 
6214    Output Arguments:
6215 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6216 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6217 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6218 
6219    Options Database Keys:
6220 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6221 
6222    Level: developer
6223 
6224 .seealso: TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2(), TSErrorWeightedENorm
6225 @*/
6226 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6227 {
6228   PetscErrorCode ierr;
6229 
6230   PetscFunctionBegin;
6231   if (wnormtype == NORM_2) {
6232     ierr = TSErrorWeightedNorm2(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
6233   } else if(wnormtype == NORM_INFINITY) {
6234     ierr = TSErrorWeightedNormInfinity(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
6235   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6236   PetscFunctionReturn(0);
6237 }
6238 
6239 
6240 /*@
6241    TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances
6242 
6243    Collective on TS
6244 
6245    Input Arguments:
6246 +  ts - time stepping context
6247 .  E - error vector
6248 .  U - state vector, usually ts->vec_sol
6249 -  Y - state vector, previous time step
6250 
6251    Output Arguments:
6252 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6253 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6254 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6255 
6256    Level: developer
6257 
6258 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENormInfinity()
6259 @*/
6260 PetscErrorCode TSErrorWeightedENorm2(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6261 {
6262   PetscErrorCode    ierr;
6263   PetscInt          i,n,N,rstart;
6264   PetscInt          n_loc,na_loc,nr_loc;
6265   PetscReal         n_glb,na_glb,nr_glb;
6266   const PetscScalar *e,*u,*y;
6267   PetscReal         err,sum,suma,sumr,gsum,gsuma,gsumr;
6268   PetscReal         tol,tola,tolr;
6269   PetscReal         err_loc[6],err_glb[6];
6270 
6271   PetscFunctionBegin;
6272   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6273   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
6274   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
6275   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
6276   PetscValidType(E,2);
6277   PetscValidType(U,3);
6278   PetscValidType(Y,4);
6279   PetscCheckSameComm(E,2,U,3);
6280   PetscCheckSameComm(U,2,Y,3);
6281   PetscValidPointer(norm,5);
6282   PetscValidPointer(norma,6);
6283   PetscValidPointer(normr,7);
6284 
6285   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
6286   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
6287   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
6288   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
6289   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6290   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6291   sum  = 0.; n_loc  = 0;
6292   suma = 0.; na_loc = 0;
6293   sumr = 0.; nr_loc = 0;
6294   if (ts->vatol && ts->vrtol) {
6295     const PetscScalar *atol,*rtol;
6296     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6297     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6298     for (i=0; i<n; i++) {
6299       err = PetscAbsScalar(e[i]);
6300       tola = PetscRealPart(atol[i]);
6301       if(tola>0.){
6302         suma  += PetscSqr(err/tola);
6303         na_loc++;
6304       }
6305       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6306       if(tolr>0.){
6307         sumr  += PetscSqr(err/tolr);
6308         nr_loc++;
6309       }
6310       tol=tola+tolr;
6311       if(tol>0.){
6312         sum  += PetscSqr(err/tol);
6313         n_loc++;
6314       }
6315     }
6316     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6317     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6318   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6319     const PetscScalar *atol;
6320     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6321     for (i=0; i<n; i++) {
6322       err = PetscAbsScalar(e[i]);
6323       tola = PetscRealPart(atol[i]);
6324       if(tola>0.){
6325         suma  += PetscSqr(err/tola);
6326         na_loc++;
6327       }
6328       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6329       if(tolr>0.){
6330         sumr  += PetscSqr(err/tolr);
6331         nr_loc++;
6332       }
6333       tol=tola+tolr;
6334       if(tol>0.){
6335         sum  += PetscSqr(err/tol);
6336         n_loc++;
6337       }
6338     }
6339     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6340   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6341     const PetscScalar *rtol;
6342     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6343     for (i=0; i<n; i++) {
6344       err = PetscAbsScalar(e[i]);
6345       tola = ts->atol;
6346       if(tola>0.){
6347         suma  += PetscSqr(err/tola);
6348         na_loc++;
6349       }
6350       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6351       if(tolr>0.){
6352         sumr  += PetscSqr(err/tolr);
6353         nr_loc++;
6354       }
6355       tol=tola+tolr;
6356       if(tol>0.){
6357         sum  += PetscSqr(err/tol);
6358         n_loc++;
6359       }
6360     }
6361     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6362   } else {                      /* scalar atol, scalar rtol */
6363     for (i=0; i<n; i++) {
6364       err = PetscAbsScalar(e[i]);
6365      tola = ts->atol;
6366       if(tola>0.){
6367         suma  += PetscSqr(err/tola);
6368         na_loc++;
6369       }
6370       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6371       if(tolr>0.){
6372         sumr  += PetscSqr(err/tolr);
6373         nr_loc++;
6374       }
6375       tol=tola+tolr;
6376       if(tol>0.){
6377         sum  += PetscSqr(err/tol);
6378         n_loc++;
6379       }
6380     }
6381   }
6382   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6383   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6384   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6385 
6386   err_loc[0] = sum;
6387   err_loc[1] = suma;
6388   err_loc[2] = sumr;
6389   err_loc[3] = (PetscReal)n_loc;
6390   err_loc[4] = (PetscReal)na_loc;
6391   err_loc[5] = (PetscReal)nr_loc;
6392 
6393   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6394 
6395   gsum   = err_glb[0];
6396   gsuma  = err_glb[1];
6397   gsumr  = err_glb[2];
6398   n_glb  = err_glb[3];
6399   na_glb = err_glb[4];
6400   nr_glb = err_glb[5];
6401 
6402   *norm  = 0.;
6403   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
6404   *norma = 0.;
6405   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
6406   *normr = 0.;
6407   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
6408 
6409   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6410   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6411   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6412   PetscFunctionReturn(0);
6413 }
6414 
6415 /*@
6416    TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances
6417    Collective on TS
6418 
6419    Input Arguments:
6420 +  ts - time stepping context
6421 .  E - error vector
6422 .  U - state vector, usually ts->vec_sol
6423 -  Y - state vector, previous time step
6424 
6425    Output Arguments:
6426 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6427 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6428 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6429 
6430    Level: developer
6431 
6432 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENorm2()
6433 @*/
6434 PetscErrorCode TSErrorWeightedENormInfinity(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6435 {
6436   PetscErrorCode    ierr;
6437   PetscInt          i,n,N,rstart;
6438   const PetscScalar *e,*u,*y;
6439   PetscReal         err,max,gmax,maxa,gmaxa,maxr,gmaxr;
6440   PetscReal         tol,tola,tolr;
6441   PetscReal         err_loc[3],err_glb[3];
6442 
6443   PetscFunctionBegin;
6444   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6445   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
6446   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
6447   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
6448   PetscValidType(E,2);
6449   PetscValidType(U,3);
6450   PetscValidType(Y,4);
6451   PetscCheckSameComm(E,2,U,3);
6452   PetscCheckSameComm(U,2,Y,3);
6453   PetscValidPointer(norm,5);
6454   PetscValidPointer(norma,6);
6455   PetscValidPointer(normr,7);
6456 
6457   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
6458   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
6459   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
6460   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
6461   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6462   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6463 
6464   max=0.;
6465   maxa=0.;
6466   maxr=0.;
6467 
6468   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
6469     const PetscScalar *atol,*rtol;
6470     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6471     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6472 
6473     for (i=0; i<n; i++) {
6474       err = PetscAbsScalar(e[i]);
6475       tola = PetscRealPart(atol[i]);
6476       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6477       tol  = tola+tolr;
6478       if(tola>0.){
6479         maxa = PetscMax(maxa,err / tola);
6480       }
6481       if(tolr>0.){
6482         maxr = PetscMax(maxr,err / tolr);
6483       }
6484       if(tol>0.){
6485         max = PetscMax(max,err / tol);
6486       }
6487     }
6488     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6489     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6490   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6491     const PetscScalar *atol;
6492     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6493     for (i=0; i<n; i++) {
6494       err = PetscAbsScalar(e[i]);
6495       tola = PetscRealPart(atol[i]);
6496       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6497       tol  = tola+tolr;
6498       if(tola>0.){
6499         maxa = PetscMax(maxa,err / tola);
6500       }
6501       if(tolr>0.){
6502         maxr = PetscMax(maxr,err / tolr);
6503       }
6504       if(tol>0.){
6505         max = PetscMax(max,err / tol);
6506       }
6507     }
6508     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6509   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6510     const PetscScalar *rtol;
6511     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6512 
6513     for (i=0; i<n; i++) {
6514       err = PetscAbsScalar(e[i]);
6515       tola = ts->atol;
6516       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6517       tol  = tola+tolr;
6518       if(tola>0.){
6519         maxa = PetscMax(maxa,err / tola);
6520       }
6521       if(tolr>0.){
6522         maxr = PetscMax(maxr,err / tolr);
6523       }
6524       if(tol>0.){
6525         max = PetscMax(max,err / tol);
6526       }
6527     }
6528     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6529   } else {                      /* scalar atol, scalar rtol */
6530 
6531     for (i=0; i<n; i++) {
6532       err = PetscAbsScalar(e[i]);
6533       tola = ts->atol;
6534       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6535       tol  = tola+tolr;
6536       if(tola>0.){
6537         maxa = PetscMax(maxa,err / tola);
6538       }
6539       if(tolr>0.){
6540         maxr = PetscMax(maxr,err / tolr);
6541       }
6542       if(tol>0.){
6543         max = PetscMax(max,err / tol);
6544       }
6545     }
6546   }
6547   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6548   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6549   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6550   err_loc[0] = max;
6551   err_loc[1] = maxa;
6552   err_loc[2] = maxr;
6553   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6554   gmax   = err_glb[0];
6555   gmaxa  = err_glb[1];
6556   gmaxr  = err_glb[2];
6557 
6558   *norm = gmax;
6559   *norma = gmaxa;
6560   *normr = gmaxr;
6561   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6562     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6563     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6564   PetscFunctionReturn(0);
6565 }
6566 
6567 /*@
6568    TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
6569 
6570    Collective on TS
6571 
6572    Input Arguments:
6573 +  ts - time stepping context
6574 .  E - error vector
6575 .  U - state vector, usually ts->vec_sol
6576 .  Y - state vector, previous time step
6577 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6578 
6579    Output Arguments:
6580 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6581 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6582 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6583 
6584    Options Database Keys:
6585 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6586 
6587    Level: developer
6588 
6589 .seealso: TSErrorWeightedENormInfinity(), TSErrorWeightedENorm2(), TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2()
6590 @*/
6591 PetscErrorCode TSErrorWeightedENorm(TS ts,Vec E,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6592 {
6593   PetscErrorCode ierr;
6594 
6595   PetscFunctionBegin;
6596   if (wnormtype == NORM_2) {
6597     ierr = TSErrorWeightedENorm2(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6598   } else if(wnormtype == NORM_INFINITY) {
6599     ierr = TSErrorWeightedENormInfinity(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6600   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6601   PetscFunctionReturn(0);
6602 }
6603 
6604 
6605 /*@
6606    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
6607 
6608    Logically Collective on TS
6609 
6610    Input Arguments:
6611 +  ts - time stepping context
6612 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
6613 
6614    Note:
6615    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
6616 
6617    Level: intermediate
6618 
6619 .seealso: TSGetCFLTime(), TSADAPTCFL
6620 @*/
6621 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
6622 {
6623   PetscFunctionBegin;
6624   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6625   ts->cfltime_local = cfltime;
6626   ts->cfltime       = -1.;
6627   PetscFunctionReturn(0);
6628 }
6629 
6630 /*@
6631    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
6632 
6633    Collective on TS
6634 
6635    Input Arguments:
6636 .  ts - time stepping context
6637 
6638    Output Arguments:
6639 .  cfltime - maximum stable time step for forward Euler
6640 
6641    Level: advanced
6642 
6643 .seealso: TSSetCFLTimeLocal()
6644 @*/
6645 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
6646 {
6647   PetscErrorCode ierr;
6648 
6649   PetscFunctionBegin;
6650   if (ts->cfltime < 0) {
6651     ierr = MPIU_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6652   }
6653   *cfltime = ts->cfltime;
6654   PetscFunctionReturn(0);
6655 }
6656 
6657 /*@
6658    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
6659 
6660    Input Parameters:
6661 .  ts   - the TS context.
6662 .  xl   - lower bound.
6663 .  xu   - upper bound.
6664 
6665    Notes:
6666    If this routine is not called then the lower and upper bounds are set to
6667    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
6668 
6669    Level: advanced
6670 
6671 @*/
6672 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
6673 {
6674   PetscErrorCode ierr;
6675   SNES           snes;
6676 
6677   PetscFunctionBegin;
6678   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
6679   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
6680   PetscFunctionReturn(0);
6681 }
6682 
6683 #if defined(PETSC_HAVE_MATLAB_ENGINE)
6684 #include <mex.h>
6685 
6686 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
6687 
6688 /*
6689    TSComputeFunction_Matlab - Calls the function that has been set with
6690                          TSSetFunctionMatlab().
6691 
6692    Collective on TS
6693 
6694    Input Parameters:
6695 +  snes - the TS context
6696 -  u - input vector
6697 
6698    Output Parameter:
6699 .  y - function vector, as set by TSSetFunction()
6700 
6701    Notes:
6702    TSComputeFunction() is typically used within nonlinear solvers
6703    implementations, so most users would not generally call this routine
6704    themselves.
6705 
6706    Level: developer
6707 
6708 .keywords: TS, nonlinear, compute, function
6709 
6710 .seealso: TSSetFunction(), TSGetFunction()
6711 */
6712 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
6713 {
6714   PetscErrorCode  ierr;
6715   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6716   int             nlhs  = 1,nrhs = 7;
6717   mxArray         *plhs[1],*prhs[7];
6718   long long int   lx = 0,lxdot = 0,ly = 0,ls = 0;
6719 
6720   PetscFunctionBegin;
6721   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
6722   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
6723   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
6724   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
6725   PetscCheckSameComm(snes,1,u,3);
6726   PetscCheckSameComm(snes,1,y,5);
6727 
6728   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
6729   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6730   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
6731   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
6732 
6733   prhs[0] =  mxCreateDoubleScalar((double)ls);
6734   prhs[1] =  mxCreateDoubleScalar(time);
6735   prhs[2] =  mxCreateDoubleScalar((double)lx);
6736   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
6737   prhs[4] =  mxCreateDoubleScalar((double)ly);
6738   prhs[5] =  mxCreateString(sctx->funcname);
6739   prhs[6] =  sctx->ctx;
6740   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
6741   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6742   mxDestroyArray(prhs[0]);
6743   mxDestroyArray(prhs[1]);
6744   mxDestroyArray(prhs[2]);
6745   mxDestroyArray(prhs[3]);
6746   mxDestroyArray(prhs[4]);
6747   mxDestroyArray(prhs[5]);
6748   mxDestroyArray(plhs[0]);
6749   PetscFunctionReturn(0);
6750 }
6751 
6752 
6753 /*
6754    TSSetFunctionMatlab - Sets the function evaluation routine and function
6755    vector for use by the TS routines in solving ODEs
6756    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
6757 
6758    Logically Collective on TS
6759 
6760    Input Parameters:
6761 +  ts - the TS context
6762 -  func - function evaluation routine
6763 
6764    Calling sequence of func:
6765 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
6766 
6767    Level: beginner
6768 
6769 .keywords: TS, nonlinear, set, function
6770 
6771 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6772 */
6773 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
6774 {
6775   PetscErrorCode  ierr;
6776   TSMatlabContext *sctx;
6777 
6778   PetscFunctionBegin;
6779   /* currently sctx is memory bleed */
6780   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6781   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6782   /*
6783      This should work, but it doesn't
6784   sctx->ctx = ctx;
6785   mexMakeArrayPersistent(sctx->ctx);
6786   */
6787   sctx->ctx = mxDuplicateArray(ctx);
6788 
6789   ierr = TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
6790   PetscFunctionReturn(0);
6791 }
6792 
6793 /*
6794    TSComputeJacobian_Matlab - Calls the function that has been set with
6795                          TSSetJacobianMatlab().
6796 
6797    Collective on TS
6798 
6799    Input Parameters:
6800 +  ts - the TS context
6801 .  u - input vector
6802 .  A, B - the matrices
6803 -  ctx - user context
6804 
6805    Level: developer
6806 
6807 .keywords: TS, nonlinear, compute, function
6808 
6809 .seealso: TSSetFunction(), TSGetFunction()
6810 @*/
6811 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat A,Mat B,void *ctx)
6812 {
6813   PetscErrorCode  ierr;
6814   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6815   int             nlhs  = 2,nrhs = 9;
6816   mxArray         *plhs[2],*prhs[9];
6817   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
6818 
6819   PetscFunctionBegin;
6820   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6821   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
6822 
6823   /* call Matlab function in ctx with arguments u and y */
6824 
6825   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
6826   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6827   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
6828   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
6829   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
6830 
6831   prhs[0] =  mxCreateDoubleScalar((double)ls);
6832   prhs[1] =  mxCreateDoubleScalar((double)time);
6833   prhs[2] =  mxCreateDoubleScalar((double)lx);
6834   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
6835   prhs[4] =  mxCreateDoubleScalar((double)shift);
6836   prhs[5] =  mxCreateDoubleScalar((double)lA);
6837   prhs[6] =  mxCreateDoubleScalar((double)lB);
6838   prhs[7] =  mxCreateString(sctx->funcname);
6839   prhs[8] =  sctx->ctx;
6840   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
6841   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6842   mxDestroyArray(prhs[0]);
6843   mxDestroyArray(prhs[1]);
6844   mxDestroyArray(prhs[2]);
6845   mxDestroyArray(prhs[3]);
6846   mxDestroyArray(prhs[4]);
6847   mxDestroyArray(prhs[5]);
6848   mxDestroyArray(prhs[6]);
6849   mxDestroyArray(prhs[7]);
6850   mxDestroyArray(plhs[0]);
6851   mxDestroyArray(plhs[1]);
6852   PetscFunctionReturn(0);
6853 }
6854 
6855 
6856 /*
6857    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
6858    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
6859 
6860    Logically Collective on TS
6861 
6862    Input Parameters:
6863 +  ts - the TS context
6864 .  A,B - Jacobian matrices
6865 .  func - function evaluation routine
6866 -  ctx - user context
6867 
6868    Calling sequence of func:
6869 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
6870 
6871 
6872    Level: developer
6873 
6874 .keywords: TS, nonlinear, set, function
6875 
6876 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6877 */
6878 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
6879 {
6880   PetscErrorCode  ierr;
6881   TSMatlabContext *sctx;
6882 
6883   PetscFunctionBegin;
6884   /* currently sctx is memory bleed */
6885   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6886   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6887   /*
6888      This should work, but it doesn't
6889   sctx->ctx = ctx;
6890   mexMakeArrayPersistent(sctx->ctx);
6891   */
6892   sctx->ctx = mxDuplicateArray(ctx);
6893 
6894   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
6895   PetscFunctionReturn(0);
6896 }
6897 
6898 /*
6899    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
6900 
6901    Collective on TS
6902 
6903 .seealso: TSSetFunction(), TSGetFunction()
6904 @*/
6905 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
6906 {
6907   PetscErrorCode  ierr;
6908   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6909   int             nlhs  = 1,nrhs = 6;
6910   mxArray         *plhs[1],*prhs[6];
6911   long long int   lx = 0,ls = 0;
6912 
6913   PetscFunctionBegin;
6914   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6915   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
6916 
6917   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
6918   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6919 
6920   prhs[0] =  mxCreateDoubleScalar((double)ls);
6921   prhs[1] =  mxCreateDoubleScalar((double)it);
6922   prhs[2] =  mxCreateDoubleScalar((double)time);
6923   prhs[3] =  mxCreateDoubleScalar((double)lx);
6924   prhs[4] =  mxCreateString(sctx->funcname);
6925   prhs[5] =  sctx->ctx;
6926   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
6927   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6928   mxDestroyArray(prhs[0]);
6929   mxDestroyArray(prhs[1]);
6930   mxDestroyArray(prhs[2]);
6931   mxDestroyArray(prhs[3]);
6932   mxDestroyArray(prhs[4]);
6933   mxDestroyArray(plhs[0]);
6934   PetscFunctionReturn(0);
6935 }
6936 
6937 
6938 /*
6939    TSMonitorSetMatlab - Sets the monitor function from Matlab
6940 
6941    Level: developer
6942 
6943 .keywords: TS, nonlinear, set, function
6944 
6945 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6946 */
6947 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
6948 {
6949   PetscErrorCode  ierr;
6950   TSMatlabContext *sctx;
6951 
6952   PetscFunctionBegin;
6953   /* currently sctx is memory bleed */
6954   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6955   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6956   /*
6957      This should work, but it doesn't
6958   sctx->ctx = ctx;
6959   mexMakeArrayPersistent(sctx->ctx);
6960   */
6961   sctx->ctx = mxDuplicateArray(ctx);
6962 
6963   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);CHKERRQ(ierr);
6964   PetscFunctionReturn(0);
6965 }
6966 #endif
6967 
6968 /*@C
6969    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
6970        in a time based line graph
6971 
6972    Collective on TS
6973 
6974    Input Parameters:
6975 +  ts - the TS context
6976 .  step - current time-step
6977 .  ptime - current time
6978 .  u - current solution
6979 -  dctx - the TSMonitorLGCtx object that contains all the options for the monitoring, this is created with TSMonitorLGCtxCreate()
6980 
6981    Options Database:
6982 .   -ts_monitor_lg_solution_variables
6983 
6984    Level: intermediate
6985 
6986    Notes: Each process in a parallel run displays its component solutions in a separate window
6987 
6988 .keywords: TS,  vector, monitor, view
6989 
6990 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
6991            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
6992            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
6993            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
6994 @*/
6995 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
6996 {
6997   PetscErrorCode    ierr;
6998   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dctx;
6999   const PetscScalar *yy;
7000   Vec               v;
7001 
7002   PetscFunctionBegin;
7003   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7004   if (!step) {
7005     PetscDrawAxis axis;
7006     PetscInt      dim;
7007     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7008     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
7009     if (!ctx->names) {
7010       PetscBool flg;
7011       /* user provides names of variables to plot but no names has been set so assume names are integer values */
7012       ierr = PetscOptionsHasName(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",&flg);CHKERRQ(ierr);
7013       if (flg) {
7014         PetscInt i,n;
7015         char     **names;
7016         ierr = VecGetSize(u,&n);CHKERRQ(ierr);
7017         ierr = PetscMalloc1(n+1,&names);CHKERRQ(ierr);
7018         for (i=0; i<n; i++) {
7019           ierr = PetscMalloc1(5,&names[i]);CHKERRQ(ierr);
7020           ierr = PetscSNPrintf(names[i],5,"%D",i);CHKERRQ(ierr);
7021         }
7022         names[n] = NULL;
7023         ctx->names = names;
7024       }
7025     }
7026     if (ctx->names && !ctx->displaynames) {
7027       char      **displaynames;
7028       PetscBool flg;
7029       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7030       ierr = PetscMalloc1(dim+1,&displaynames);CHKERRQ(ierr);
7031       ierr = PetscMemzero(displaynames,(dim+1)*sizeof(char*));CHKERRQ(ierr);
7032       ierr = PetscOptionsGetStringArray(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",displaynames,&dim,&flg);CHKERRQ(ierr);
7033       if (flg) {
7034         ierr = TSMonitorLGCtxSetDisplayVariables(ctx,(const char *const *)displaynames);CHKERRQ(ierr);
7035       }
7036       ierr = PetscStrArrayDestroy(&displaynames);CHKERRQ(ierr);
7037     }
7038     if (ctx->displaynames) {
7039       ierr = PetscDrawLGSetDimension(ctx->lg,ctx->ndisplayvariables);CHKERRQ(ierr);
7040       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->displaynames);CHKERRQ(ierr);
7041     } else if (ctx->names) {
7042       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7043       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
7044       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->names);CHKERRQ(ierr);
7045     } else {
7046       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7047       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
7048     }
7049     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7050   }
7051 
7052   if (!ctx->transform) v = u;
7053   else {ierr = (*ctx->transform)(ctx->transformctx,u,&v);CHKERRQ(ierr);}
7054   ierr = VecGetArrayRead(v,&yy);CHKERRQ(ierr);
7055   if (ctx->displaynames) {
7056     PetscInt i;
7057     for (i=0; i<ctx->ndisplayvariables; i++)
7058       ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
7059     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,ctx->displayvalues);CHKERRQ(ierr);
7060   } else {
7061 #if defined(PETSC_USE_COMPLEX)
7062     PetscInt  i,n;
7063     PetscReal *yreal;
7064     ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
7065     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
7066     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
7067     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
7068     ierr = PetscFree(yreal);CHKERRQ(ierr);
7069 #else
7070     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
7071 #endif
7072   }
7073   ierr = VecRestoreArrayRead(v,&yy);CHKERRQ(ierr);
7074   if (ctx->transform) {ierr = VecDestroy(&v);CHKERRQ(ierr);}
7075 
7076   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
7077     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7078     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7079   }
7080   PetscFunctionReturn(0);
7081 }
7082 
7083 
7084 /*@C
7085    TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
7086 
7087    Collective on TS
7088 
7089    Input Parameters:
7090 +  ts - the TS context
7091 -  names - the names of the components, final string must be NULL
7092 
7093    Level: intermediate
7094 
7095    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7096 
7097 .keywords: TS,  vector, monitor, view
7098 
7099 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetVariableNames()
7100 @*/
7101 PetscErrorCode  TSMonitorLGSetVariableNames(TS ts,const char * const *names)
7102 {
7103   PetscErrorCode    ierr;
7104   PetscInt          i;
7105 
7106   PetscFunctionBegin;
7107   for (i=0; i<ts->numbermonitors; i++) {
7108     if (ts->monitor[i] == TSMonitorLGSolution) {
7109       ierr = TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i],names);CHKERRQ(ierr);
7110       break;
7111     }
7112   }
7113   PetscFunctionReturn(0);
7114 }
7115 
7116 /*@C
7117    TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
7118 
7119    Collective on TS
7120 
7121    Input Parameters:
7122 +  ts - the TS context
7123 -  names - the names of the components, final string must be NULL
7124 
7125    Level: intermediate
7126 
7127 .keywords: TS,  vector, monitor, view
7128 
7129 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGSetVariableNames()
7130 @*/
7131 PetscErrorCode  TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx,const char * const *names)
7132 {
7133   PetscErrorCode    ierr;
7134 
7135   PetscFunctionBegin;
7136   ierr = PetscStrArrayDestroy(&ctx->names);CHKERRQ(ierr);
7137   ierr = PetscStrArrayallocpy(names,&ctx->names);CHKERRQ(ierr);
7138   PetscFunctionReturn(0);
7139 }
7140 
7141 /*@C
7142    TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
7143 
7144    Collective on TS
7145 
7146    Input Parameter:
7147 .  ts - the TS context
7148 
7149    Output Parameter:
7150 .  names - the names of the components, final string must be NULL
7151 
7152    Level: intermediate
7153 
7154    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7155 
7156 .keywords: TS,  vector, monitor, view
7157 
7158 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
7159 @*/
7160 PetscErrorCode  TSMonitorLGGetVariableNames(TS ts,const char *const **names)
7161 {
7162   PetscInt       i;
7163 
7164   PetscFunctionBegin;
7165   *names = NULL;
7166   for (i=0; i<ts->numbermonitors; i++) {
7167     if (ts->monitor[i] == TSMonitorLGSolution) {
7168       TSMonitorLGCtx  ctx = (TSMonitorLGCtx) ts->monitorcontext[i];
7169       *names = (const char *const *)ctx->names;
7170       break;
7171     }
7172   }
7173   PetscFunctionReturn(0);
7174 }
7175 
7176 /*@C
7177    TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
7178 
7179    Collective on TS
7180 
7181    Input Parameters:
7182 +  ctx - the TSMonitorLG context
7183 .  displaynames - the names of the components, final string must be NULL
7184 
7185    Level: intermediate
7186 
7187 .keywords: TS,  vector, monitor, view
7188 
7189 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
7190 @*/
7191 PetscErrorCode  TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx,const char * const *displaynames)
7192 {
7193   PetscInt          j = 0,k;
7194   PetscErrorCode    ierr;
7195 
7196   PetscFunctionBegin;
7197   if (!ctx->names) PetscFunctionReturn(0);
7198   ierr = PetscStrArrayDestroy(&ctx->displaynames);CHKERRQ(ierr);
7199   ierr = PetscStrArrayallocpy(displaynames,&ctx->displaynames);CHKERRQ(ierr);
7200   while (displaynames[j]) j++;
7201   ctx->ndisplayvariables = j;
7202   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvariables);CHKERRQ(ierr);
7203   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvalues);CHKERRQ(ierr);
7204   j = 0;
7205   while (displaynames[j]) {
7206     k = 0;
7207     while (ctx->names[k]) {
7208       PetscBool flg;
7209       ierr = PetscStrcmp(displaynames[j],ctx->names[k],&flg);CHKERRQ(ierr);
7210       if (flg) {
7211         ctx->displayvariables[j] = k;
7212         break;
7213       }
7214       k++;
7215     }
7216     j++;
7217   }
7218   PetscFunctionReturn(0);
7219 }
7220 
7221 
7222 /*@C
7223    TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
7224 
7225    Collective on TS
7226 
7227    Input Parameters:
7228 +  ts - the TS context
7229 .  displaynames - the names of the components, final string must be NULL
7230 
7231    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7232 
7233    Level: intermediate
7234 
7235 .keywords: TS,  vector, monitor, view
7236 
7237 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
7238 @*/
7239 PetscErrorCode  TSMonitorLGSetDisplayVariables(TS ts,const char * const *displaynames)
7240 {
7241   PetscInt          i;
7242   PetscErrorCode    ierr;
7243 
7244   PetscFunctionBegin;
7245   for (i=0; i<ts->numbermonitors; i++) {
7246     if (ts->monitor[i] == TSMonitorLGSolution) {
7247       ierr = TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i],displaynames);CHKERRQ(ierr);
7248       break;
7249     }
7250   }
7251   PetscFunctionReturn(0);
7252 }
7253 
7254 /*@C
7255    TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
7256 
7257    Collective on TS
7258 
7259    Input Parameters:
7260 +  ts - the TS context
7261 .  transform - the transform function
7262 .  destroy - function to destroy the optional context
7263 -  ctx - optional context used by transform function
7264 
7265    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7266 
7267    Level: intermediate
7268 
7269 .keywords: TS,  vector, monitor, view
7270 
7271 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGCtxSetTransform()
7272 @*/
7273 PetscErrorCode  TSMonitorLGSetTransform(TS ts,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
7274 {
7275   PetscInt          i;
7276   PetscErrorCode    ierr;
7277 
7278   PetscFunctionBegin;
7279   for (i=0; i<ts->numbermonitors; i++) {
7280     if (ts->monitor[i] == TSMonitorLGSolution) {
7281       ierr = TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i],transform,destroy,tctx);CHKERRQ(ierr);
7282     }
7283   }
7284   PetscFunctionReturn(0);
7285 }
7286 
7287 /*@C
7288    TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
7289 
7290    Collective on TSLGCtx
7291 
7292    Input Parameters:
7293 +  ts - the TS context
7294 .  transform - the transform function
7295 .  destroy - function to destroy the optional context
7296 -  ctx - optional context used by transform function
7297 
7298    Level: intermediate
7299 
7300 .keywords: TS,  vector, monitor, view
7301 
7302 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGSetTransform()
7303 @*/
7304 PetscErrorCode  TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
7305 {
7306   PetscFunctionBegin;
7307   ctx->transform    = transform;
7308   ctx->transformdestroy = destroy;
7309   ctx->transformctx = tctx;
7310   PetscFunctionReturn(0);
7311 }
7312 
7313 /*@C
7314    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the solution vector
7315        in a time based line graph
7316 
7317    Collective on TS
7318 
7319    Input Parameters:
7320 +  ts - the TS context
7321 .  step - current time-step
7322 .  ptime - current time
7323 .  u - current solution
7324 -  dctx - TSMonitorLGCtx object created with TSMonitorLGCtxCreate()
7325 
7326    Level: intermediate
7327 
7328    Notes: Each process in a parallel run displays its component errors in a separate window
7329 
7330    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
7331 
7332    Options Database Keys:
7333 .  -ts_monitor_lg_error - create a graphical monitor of error history
7334 
7335 .keywords: TS,  vector, monitor, view
7336 
7337 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
7338 @*/
7339 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
7340 {
7341   PetscErrorCode    ierr;
7342   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
7343   const PetscScalar *yy;
7344   Vec               y;
7345 
7346   PetscFunctionBegin;
7347   if (!step) {
7348     PetscDrawAxis axis;
7349     PetscInt      dim;
7350     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7351     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Solution");CHKERRQ(ierr);
7352     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7353     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
7354     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7355   }
7356   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
7357   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
7358   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
7359   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
7360 #if defined(PETSC_USE_COMPLEX)
7361   {
7362     PetscReal *yreal;
7363     PetscInt  i,n;
7364     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
7365     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
7366     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
7367     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
7368     ierr = PetscFree(yreal);CHKERRQ(ierr);
7369   }
7370 #else
7371   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
7372 #endif
7373   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
7374   ierr = VecDestroy(&y);CHKERRQ(ierr);
7375   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
7376     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7377     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7378   }
7379   PetscFunctionReturn(0);
7380 }
7381 
7382 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
7383 {
7384   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7385   PetscReal      x   = ptime,y;
7386   PetscErrorCode ierr;
7387   PetscInt       its;
7388 
7389   PetscFunctionBegin;
7390   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7391   if (!n) {
7392     PetscDrawAxis axis;
7393     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7394     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
7395     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7396     ctx->snes_its = 0;
7397   }
7398   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
7399   y    = its - ctx->snes_its;
7400   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7401   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7402     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7403     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7404   }
7405   ctx->snes_its = its;
7406   PetscFunctionReturn(0);
7407 }
7408 
7409 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
7410 {
7411   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7412   PetscReal      x   = ptime,y;
7413   PetscErrorCode ierr;
7414   PetscInt       its;
7415 
7416   PetscFunctionBegin;
7417   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7418   if (!n) {
7419     PetscDrawAxis axis;
7420     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7421     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
7422     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7423     ctx->ksp_its = 0;
7424   }
7425   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
7426   y    = its - ctx->ksp_its;
7427   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7428   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7429     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7430     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7431   }
7432   ctx->ksp_its = its;
7433   PetscFunctionReturn(0);
7434 }
7435 
7436 /*@
7437    TSComputeLinearStability - computes the linear stability function at a point
7438 
7439    Collective on TS and Vec
7440 
7441    Input Parameters:
7442 +  ts - the TS context
7443 -  xr,xi - real and imaginary part of input arguments
7444 
7445    Output Parameters:
7446 .  yr,yi - real and imaginary part of function value
7447 
7448    Level: developer
7449 
7450 .keywords: TS, compute
7451 
7452 .seealso: TSSetRHSFunction(), TSComputeIFunction()
7453 @*/
7454 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
7455 {
7456   PetscErrorCode ierr;
7457 
7458   PetscFunctionBegin;
7459   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7460   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
7461   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
7462   PetscFunctionReturn(0);
7463 }
7464 
7465 /* ------------------------------------------------------------------------*/
7466 /*@C
7467    TSMonitorEnvelopeCtxCreate - Creates a context for use with TSMonitorEnvelope()
7468 
7469    Collective on TS
7470 
7471    Input Parameters:
7472 .  ts  - the ODE solver object
7473 
7474    Output Parameter:
7475 .  ctx - the context
7476 
7477    Level: intermediate
7478 
7479 .keywords: TS, monitor, line graph, residual, seealso
7480 
7481 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
7482 
7483 @*/
7484 PetscErrorCode  TSMonitorEnvelopeCtxCreate(TS ts,TSMonitorEnvelopeCtx *ctx)
7485 {
7486   PetscErrorCode ierr;
7487 
7488   PetscFunctionBegin;
7489   ierr = PetscNew(ctx);CHKERRQ(ierr);
7490   PetscFunctionReturn(0);
7491 }
7492 
7493 /*@C
7494    TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
7495 
7496    Collective on TS
7497 
7498    Input Parameters:
7499 +  ts - the TS context
7500 .  step - current time-step
7501 .  ptime - current time
7502 .  u  - current solution
7503 -  dctx - the envelope context
7504 
7505    Options Database:
7506 .  -ts_monitor_envelope
7507 
7508    Level: intermediate
7509 
7510    Notes: after a solve you can use TSMonitorEnvelopeGetBounds() to access the envelope
7511 
7512 .keywords: TS,  vector, monitor, view
7513 
7514 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxCreate()
7515 @*/
7516 PetscErrorCode  TSMonitorEnvelope(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
7517 {
7518   PetscErrorCode       ierr;
7519   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
7520 
7521   PetscFunctionBegin;
7522   if (!ctx->max) {
7523     ierr = VecDuplicate(u,&ctx->max);CHKERRQ(ierr);
7524     ierr = VecDuplicate(u,&ctx->min);CHKERRQ(ierr);
7525     ierr = VecCopy(u,ctx->max);CHKERRQ(ierr);
7526     ierr = VecCopy(u,ctx->min);CHKERRQ(ierr);
7527   } else {
7528     ierr = VecPointwiseMax(ctx->max,u,ctx->max);CHKERRQ(ierr);
7529     ierr = VecPointwiseMin(ctx->min,u,ctx->min);CHKERRQ(ierr);
7530   }
7531   PetscFunctionReturn(0);
7532 }
7533 
7534 
7535 /*@C
7536    TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
7537 
7538    Collective on TS
7539 
7540    Input Parameter:
7541 .  ts - the TS context
7542 
7543    Output Parameter:
7544 +  max - the maximum values
7545 -  min - the minimum values
7546 
7547    Notes: If the TS does not have a TSMonitorEnvelopeCtx associated with it then this function is ignored
7548 
7549    Level: intermediate
7550 
7551 .keywords: TS,  vector, monitor, view
7552 
7553 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
7554 @*/
7555 PetscErrorCode  TSMonitorEnvelopeGetBounds(TS ts,Vec *max,Vec *min)
7556 {
7557   PetscInt i;
7558 
7559   PetscFunctionBegin;
7560   if (max) *max = NULL;
7561   if (min) *min = NULL;
7562   for (i=0; i<ts->numbermonitors; i++) {
7563     if (ts->monitor[i] == TSMonitorEnvelope) {
7564       TSMonitorEnvelopeCtx  ctx = (TSMonitorEnvelopeCtx) ts->monitorcontext[i];
7565       if (max) *max = ctx->max;
7566       if (min) *min = ctx->min;
7567       break;
7568     }
7569   }
7570   PetscFunctionReturn(0);
7571 }
7572 
7573 /*@C
7574    TSMonitorEnvelopeCtxDestroy - Destroys a context that was created  with TSMonitorEnvelopeCtxCreate().
7575 
7576    Collective on TSMonitorEnvelopeCtx
7577 
7578    Input Parameter:
7579 .  ctx - the monitor context
7580 
7581    Level: intermediate
7582 
7583 .keywords: TS, monitor, line graph, destroy
7584 
7585 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep()
7586 @*/
7587 PetscErrorCode  TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
7588 {
7589   PetscErrorCode ierr;
7590 
7591   PetscFunctionBegin;
7592   ierr = VecDestroy(&(*ctx)->min);CHKERRQ(ierr);
7593   ierr = VecDestroy(&(*ctx)->max);CHKERRQ(ierr);
7594   ierr = PetscFree(*ctx);CHKERRQ(ierr);
7595   PetscFunctionReturn(0);
7596 }
7597 
7598 /*@
7599    TSRollBack - Rolls back one time step
7600 
7601    Collective on TS
7602 
7603    Input Parameter:
7604 .  ts - the TS context obtained from TSCreate()
7605 
7606    Level: advanced
7607 
7608 .keywords: TS, timestep, rollback
7609 
7610 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
7611 @*/
7612 PetscErrorCode  TSRollBack(TS ts)
7613 {
7614   PetscErrorCode ierr;
7615 
7616   PetscFunctionBegin;
7617   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7618   if (ts->steprollback) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"TSRollBack already called");
7619   if (!ts->ops->rollback) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
7620   ierr = (*ts->ops->rollback)(ts);CHKERRQ(ierr);
7621   ts->time_step = ts->ptime - ts->ptime_prev;
7622   ts->ptime = ts->ptime_prev;
7623   ts->ptime_prev = ts->ptime_prev_rollback;
7624   ts->steps--; ts->total_steps--;
7625   ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
7626   ts->steprollback = PETSC_TRUE;
7627   PetscFunctionReturn(0);
7628 }
7629 
7630 /*@
7631    TSGetStages - Get the number of stages and stage values
7632 
7633    Input Parameter:
7634 .  ts - the TS context obtained from TSCreate()
7635 
7636    Level: advanced
7637 
7638 .keywords: TS, getstages
7639 
7640 .seealso: TSCreate()
7641 @*/
7642 PetscErrorCode  TSGetStages(TS ts,PetscInt *ns,Vec **Y)
7643 {
7644   PetscErrorCode ierr;
7645 
7646   PetscFunctionBegin;
7647   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7648   PetscValidPointer(ns,2);
7649 
7650   if (!ts->ops->getstages) *ns=0;
7651   else {
7652     ierr = (*ts->ops->getstages)(ts,ns,Y);CHKERRQ(ierr);
7653   }
7654   PetscFunctionReturn(0);
7655 }
7656 
7657 /*@C
7658   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
7659 
7660   Collective on SNES
7661 
7662   Input Parameters:
7663 + ts - the TS context
7664 . t - current timestep
7665 . U - state vector
7666 . Udot - time derivative of state vector
7667 . shift - shift to apply, see note below
7668 - ctx - an optional user context
7669 
7670   Output Parameters:
7671 + J - Jacobian matrix (not altered in this routine)
7672 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
7673 
7674   Level: intermediate
7675 
7676   Notes:
7677   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
7678 
7679   dF/dU + shift*dF/dUdot
7680 
7681   Most users should not need to explicitly call this routine, as it
7682   is used internally within the nonlinear solvers.
7683 
7684   This will first try to get the coloring from the DM.  If the DM type has no coloring
7685   routine, then it will try to get the coloring from the matrix.  This requires that the
7686   matrix have nonzero entries precomputed.
7687 
7688 .keywords: TS, finite differences, Jacobian, coloring, sparse
7689 .seealso: TSSetIJacobian(), MatFDColoringCreate(), MatFDColoringSetFunction()
7690 @*/
7691 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat J,Mat B,void *ctx)
7692 {
7693   SNES           snes;
7694   MatFDColoring  color;
7695   PetscBool      hascolor, matcolor = PETSC_FALSE;
7696   PetscErrorCode ierr;
7697 
7698   PetscFunctionBegin;
7699   ierr = PetscOptionsGetBool(((PetscObject)ts)->options,((PetscObject) ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL);CHKERRQ(ierr);
7700   ierr = PetscObjectQuery((PetscObject) B, "TSMatFDColoring", (PetscObject *) &color);CHKERRQ(ierr);
7701   if (!color) {
7702     DM         dm;
7703     ISColoring iscoloring;
7704 
7705     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
7706     ierr = DMHasColoring(dm, &hascolor);CHKERRQ(ierr);
7707     if (hascolor && !matcolor) {
7708       ierr = DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring);CHKERRQ(ierr);
7709       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7710       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7711       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7712       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7713       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7714     } else {
7715       MatColoring mc;
7716 
7717       ierr = MatColoringCreate(B, &mc);CHKERRQ(ierr);
7718       ierr = MatColoringSetDistance(mc, 2);CHKERRQ(ierr);
7719       ierr = MatColoringSetType(mc, MATCOLORINGSL);CHKERRQ(ierr);
7720       ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr);
7721       ierr = MatColoringApply(mc, &iscoloring);CHKERRQ(ierr);
7722       ierr = MatColoringDestroy(&mc);CHKERRQ(ierr);
7723       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7724       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7725       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7726       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7727       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7728     }
7729     ierr = PetscObjectCompose((PetscObject) B, "TSMatFDColoring", (PetscObject) color);CHKERRQ(ierr);
7730     ierr = PetscObjectDereference((PetscObject) color);CHKERRQ(ierr);
7731   }
7732   ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
7733   ierr = MatFDColoringApply(B, color, U, snes);CHKERRQ(ierr);
7734   if (J != B) {
7735     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7736     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7737   }
7738   PetscFunctionReturn(0);
7739 }
7740 
7741 /*@
7742     TSSetFunctionDomainError - Set the function testing if the current state vector is valid
7743 
7744     Input Parameters:
7745     ts - the TS context
7746     func - function called within TSFunctionDomainError
7747 
7748     Level: intermediate
7749 
7750 .keywords: TS, state, domain
7751 .seealso: TSAdaptCheckStage(), TSFunctionDomainError()
7752 @*/
7753 
7754 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS,PetscReal,Vec,PetscBool*))
7755 {
7756   PetscFunctionBegin;
7757   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7758   ts->functiondomainerror = func;
7759   PetscFunctionReturn(0);
7760 }
7761 
7762 /*@
7763     TSFunctionDomainError - Check if the current state is valid
7764 
7765     Input Parameters:
7766     ts - the TS context
7767     stagetime - time of the simulation
7768     Y - state vector to check.
7769 
7770     Output Parameter:
7771     accept - Set to PETSC_FALSE if the current state vector is valid.
7772 
7773     Note:
7774     This function should be used to ensure the state is in a valid part of the space.
7775     For example, one can ensure here all values are positive.
7776 
7777     Level: advanced
7778 @*/
7779 PetscErrorCode TSFunctionDomainError(TS ts,PetscReal stagetime,Vec Y,PetscBool* accept)
7780 {
7781   PetscErrorCode ierr;
7782 
7783   PetscFunctionBegin;
7784 
7785   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7786   *accept = PETSC_TRUE;
7787   if (ts->functiondomainerror) {
7788     PetscStackCallStandard((*ts->functiondomainerror),(ts,stagetime,Y,accept));
7789   }
7790   PetscFunctionReturn(0);
7791 }
7792 
7793 /*@C
7794   TSClone - This function clones a time step object.
7795 
7796   Collective on MPI_Comm
7797 
7798   Input Parameter:
7799 . tsin    - The input TS
7800 
7801   Output Parameter:
7802 . tsout   - The output TS (cloned)
7803 
7804   Notes:
7805   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.
7806 
7807   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);
7808 
7809   Level: developer
7810 
7811 .keywords: TS, clone
7812 .seealso: TSCreate(), TSSetType(), TSSetUp(), TSDestroy(), TSSetProblemType()
7813 @*/
7814 PetscErrorCode  TSClone(TS tsin, TS *tsout)
7815 {
7816   TS             t;
7817   PetscErrorCode ierr;
7818   SNES           snes_start;
7819   DM             dm;
7820   TSType         type;
7821 
7822   PetscFunctionBegin;
7823   PetscValidPointer(tsin,1);
7824   *tsout = NULL;
7825 
7826   ierr = PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView);CHKERRQ(ierr);
7827 
7828   /* General TS description */
7829   t->numbermonitors    = 0;
7830   t->setupcalled       = 0;
7831   t->ksp_its           = 0;
7832   t->snes_its          = 0;
7833   t->nwork             = 0;
7834   t->rhsjacobian.time  = -1e20;
7835   t->rhsjacobian.scale = 1.;
7836   t->ijacobian.shift   = 1.;
7837 
7838   ierr = TSGetSNES(tsin,&snes_start);CHKERRQ(ierr);
7839   ierr = TSSetSNES(t,snes_start);CHKERRQ(ierr);
7840 
7841   ierr = TSGetDM(tsin,&dm);CHKERRQ(ierr);
7842   ierr = TSSetDM(t,dm);CHKERRQ(ierr);
7843 
7844   t->adapt = tsin->adapt;
7845   ierr = PetscObjectReference((PetscObject)t->adapt);CHKERRQ(ierr);
7846 
7847   t->trajectory = tsin->trajectory;
7848   ierr = PetscObjectReference((PetscObject)t->trajectory);CHKERRQ(ierr);
7849 
7850   t->event = tsin->event;
7851   if (t->event) t->event->refct++;
7852 
7853   t->problem_type      = tsin->problem_type;
7854   t->ptime             = tsin->ptime;
7855   t->ptime_prev        = tsin->ptime_prev;
7856   t->time_step         = tsin->time_step;
7857   t->max_time          = tsin->max_time;
7858   t->steps             = tsin->steps;
7859   t->total_steps       = tsin->total_steps;
7860   t->max_steps         = tsin->max_steps;
7861   t->equation_type     = tsin->equation_type;
7862   t->atol              = tsin->atol;
7863   t->rtol              = tsin->rtol;
7864   t->max_snes_failures = tsin->max_snes_failures;
7865   t->max_reject        = tsin->max_reject;
7866   t->errorifstepfailed = tsin->errorifstepfailed;
7867 
7868   ierr = TSGetType(tsin,&type);CHKERRQ(ierr);
7869   ierr = TSSetType(t,type);CHKERRQ(ierr);
7870 
7871   t->vec_sol           = NULL;
7872 
7873   t->cfltime          = tsin->cfltime;
7874   t->cfltime_local    = tsin->cfltime_local;
7875   t->exact_final_time = tsin->exact_final_time;
7876 
7877   ierr = PetscMemcpy(t->ops,tsin->ops,sizeof(struct _TSOps));CHKERRQ(ierr);
7878 
7879   if (((PetscObject)tsin)->fortran_func_pointers) {
7880     PetscInt i;
7881     ierr = PetscMalloc((10)*sizeof(void(*)(void)),&((PetscObject)t)->fortran_func_pointers);CHKERRQ(ierr);
7882     for (i=0; i<10; i++) {
7883       ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
7884     }
7885   }
7886   *tsout = t;
7887   PetscFunctionReturn(0);
7888 }
7889