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