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