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