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