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