xref: /petsc/src/ts/interface/ts.c (revision 7619abb3ef4f3fc87061a89a3a6e42d1f6232146)
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_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;
11 
12 const char *const TSExactFinalTimeOptions[] = {"STEPOVER","INTERPOLATE","MATCHSTEP","TSExactFinalTimeOption","TS_EXACTFINALTIME_",0};
13 
14 #undef __FUNCT__
15 #define __FUNCT__ "TSSetTypeFromOptions"
16 /*
17   TSSetTypeFromOptions - Sets the type of ts from user options.
18 
19   Collective on TS
20 
21   Input Parameter:
22 . ts - The ts
23 
24   Level: intermediate
25 
26 .keywords: TS, set, options, database, type
27 .seealso: TSSetFromOptions(), TSSetType()
28 */
29 static PetscErrorCode TSSetTypeFromOptions(TS ts)
30 {
31   PetscBool      opt;
32   const char     *defaultType;
33   char           typeName[256];
34   PetscErrorCode ierr;
35 
36   PetscFunctionBegin;
37   if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name;
38   else defaultType = TSEULER;
39 
40   if (!TSRegisterAllCalled) {ierr = TSRegisterAll();CHKERRQ(ierr);}
41   ierr = PetscOptionsList("-ts_type", "TS method"," TSSetType", TSList, defaultType, typeName, 256, &opt);CHKERRQ(ierr);
42   if (opt) {
43     ierr = TSSetType(ts, typeName);CHKERRQ(ierr);
44   } else {
45     ierr = TSSetType(ts, defaultType);CHKERRQ(ierr);
46   }
47   PetscFunctionReturn(0);
48 }
49 
50 struct _n_TSMonitorDrawCtx {
51   PetscViewer   viewer;
52   PetscDrawAxis axis;
53   Vec           initialsolution;
54   PetscBool     showinitial;
55   PetscInt      howoften;  /* when > 0 uses step % howoften, when negative only final solution plotted */
56   PetscBool     showtimestepandtime;
57   int           color;
58 };
59 
60 #undef __FUNCT__
61 #define __FUNCT__ "TSSetFromOptions"
62 /*@
63    TSSetFromOptions - Sets various TS parameters from user options.
64 
65    Collective on TS
66 
67    Input Parameter:
68 .  ts - the TS context obtained from TSCreate()
69 
70    Options Database Keys:
71 +  -ts_type <type> - TSEULER, TSBEULER, TSSUNDIALS, TSPSEUDO, TSCN, TSRK, TSTHETA, TSGL, TSSSP
72 .  -ts_max_steps maxsteps - maximum number of time-steps to take
73 .  -ts_final_time time - maximum time to compute to
74 .  -ts_dt dt - initial time step
75 .  -ts_monitor - print information at each timestep
76 .  -ts_monitor_lg_timestep - Monitor timestep size graphically
77 .  -ts_monitor_lg_solution - Monitor solution graphically
78 .  -ts_monitor_lg_error - Monitor error graphically
79 .  -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically
80 .  -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically
81 .  -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically
82 .  -ts_monitor_draw_solution - Monitor solution graphically
83 .  -ts_monitor_draw_solution_phase - Monitor solution graphically with phase diagram
84 .  -ts_monitor_draw_error - Monitor error graphically
85 .  -ts_monitor_solution_binary <filename> - Save each solution to a binary file
86 -  -ts_monitor_solution_vtk <filename.vts> - Save each time step to a binary file, use filename-%%03D.vts
87 
88    Developer Note: We should unify all the -ts_monitor options in the way that -xxx_view has been unified
89 
90    Level: beginner
91 
92 .keywords: TS, timestep, set, options, database
93 
94 .seealso: TSGetType()
95 @*/
96 PetscErrorCode  TSSetFromOptions(TS ts)
97 {
98   PetscBool              opt,flg;
99   PetscErrorCode         ierr;
100   PetscViewer            monviewer;
101   char                   monfilename[PETSC_MAX_PATH_LEN];
102   SNES                   snes;
103   TSAdapt                adapt;
104   PetscReal              time_step;
105   TSExactFinalTimeOption eftopt;
106   char                   dir[16];
107 
108   PetscFunctionBegin;
109   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
110   ierr = PetscObjectOptionsBegin((PetscObject)ts);CHKERRQ(ierr);
111   /* Handle TS type options */
112   ierr = TSSetTypeFromOptions(ts);CHKERRQ(ierr);
113 
114   /* Handle generic TS options */
115   ierr = PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetDuration",ts->max_steps,&ts->max_steps,NULL);CHKERRQ(ierr);
116   ierr = PetscOptionsReal("-ts_final_time","Time to run to","TSSetDuration",ts->max_time,&ts->max_time,NULL);CHKERRQ(ierr);
117   ierr = PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,NULL);CHKERRQ(ierr);
118   ierr = PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&time_step,&flg);CHKERRQ(ierr);
119   if (flg) {
120     ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr);
121   }
122   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);
123   if (flg) {ierr = TSSetExactFinalTime(ts,eftopt);CHKERRQ(ierr);}
124   ierr = PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","TSSetMaxSNESFailures",ts->max_snes_failures,&ts->max_snes_failures,NULL);CHKERRQ(ierr);
125   ierr = PetscOptionsInt("-ts_max_reject","Maximum number of step rejections before step fails","TSSetMaxStepRejections",ts->max_reject,&ts->max_reject,NULL);CHKERRQ(ierr);
126   ierr = PetscOptionsBool("-ts_error_if_step_fails","Error if no step succeeds","TSSetErrorIfStepFails",ts->errorifstepfailed,&ts->errorifstepfailed,NULL);CHKERRQ(ierr);
127   ierr = PetscOptionsReal("-ts_rtol","Relative tolerance for local truncation error","TSSetTolerances",ts->rtol,&ts->rtol,NULL);CHKERRQ(ierr);
128   ierr = PetscOptionsReal("-ts_atol","Absolute tolerance for local truncation error","TSSetTolerances",ts->atol,&ts->atol,NULL);CHKERRQ(ierr);
129 
130   /* Monitor options */
131   ierr = PetscOptionsString("-ts_monitor","Monitor timestep size","TSMonitorDefault","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
132   if (flg) {
133     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ts),monfilename,&monviewer);CHKERRQ(ierr);
134     ierr = TSMonitorSet(ts,TSMonitorDefault,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr);
135   }
136   ierr = PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
137   if (flg) {ierr = PetscPythonMonitorSet((PetscObject)ts,monfilename);CHKERRQ(ierr);}
138 
139   ierr = PetscOptionsName("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",&opt);CHKERRQ(ierr);
140   if (opt) {
141     TSMonitorLGCtx ctx;
142     PetscInt       howoften = 1;
143 
144     ierr = PetscOptionsInt("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL);CHKERRQ(ierr);
145     ierr = TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
146     ierr = TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
147   }
148   ierr = PetscOptionsName("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",&opt);CHKERRQ(ierr);
149   if (opt) {
150     TSMonitorLGCtx ctx;
151     PetscInt       howoften = 1;
152 
153     ierr = PetscOptionsInt("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",howoften,&howoften,NULL);CHKERRQ(ierr);
154     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);CHKERRQ(ierr);
155     ierr = TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
156   }
157   ierr = PetscOptionsName("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",&opt);CHKERRQ(ierr);
158   if (opt) {
159     TSMonitorLGCtx ctx;
160     PetscInt       howoften = 1;
161 
162     ierr = PetscOptionsInt("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",howoften,&howoften,NULL);CHKERRQ(ierr);
163     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);CHKERRQ(ierr);
164     ierr = TSMonitorSet(ts,TSMonitorLGError,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
165   }
166   ierr = PetscOptionsName("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",&opt);CHKERRQ(ierr);
167   if (opt) {
168     TSMonitorLGCtx ctx;
169     PetscInt       howoften = 1;
170 
171     ierr = PetscOptionsInt("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",howoften,&howoften,NULL);CHKERRQ(ierr);
172     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
173     ierr = TSMonitorSet(ts,TSMonitorLGSNESIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
174   }
175   ierr = PetscOptionsName("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",&opt);CHKERRQ(ierr);
176   if (opt) {
177     TSMonitorLGCtx ctx;
178     PetscInt       howoften = 1;
179 
180     ierr = PetscOptionsInt("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",howoften,&howoften,NULL);CHKERRQ(ierr);
181     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
182     ierr = TSMonitorSet(ts,TSMonitorLGKSPIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
183   }
184   ierr = PetscOptionsName("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",&opt);CHKERRQ(ierr);
185   if (opt) {
186     TSMonitorSPEigCtx ctx;
187     PetscInt          howoften = 1;
188 
189     ierr = PetscOptionsInt("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",howoften,&howoften,NULL);CHKERRQ(ierr);
190     ierr = TSMonitorSPEigCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);CHKERRQ(ierr);
191     ierr = TSMonitorSet(ts,TSMonitorSPEig,ctx,(PetscErrorCode (*)(void**))TSMonitorSPEigCtxDestroy);CHKERRQ(ierr);
192   }
193   opt  = PETSC_FALSE;
194   ierr = PetscOptionsName("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",&opt);CHKERRQ(ierr);
195   if (opt) {
196     TSMonitorDrawCtx ctx;
197     PetscInt         howoften = 1;
198 
199     ierr = PetscOptionsInt("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",howoften,&howoften,NULL);CHKERRQ(ierr);
200     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);CHKERRQ(ierr);
201     ierr = TSMonitorSet(ts,TSMonitorDrawSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
202   }
203   opt  = PETSC_FALSE;
204   ierr = PetscOptionsName("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",&opt);CHKERRQ(ierr);
205   if (opt) {
206     TSMonitorDrawCtx ctx;
207     PetscReal        bounds[4];
208     PetscInt         n = 4;
209     PetscDraw        draw;
210 
211     ierr = PetscOptionsRealArray("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",bounds,&n,NULL);CHKERRQ(ierr);
212     if (n != 4) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Must provide bounding box of phase field");
213     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,1,&ctx);CHKERRQ(ierr);
214     ierr = PetscViewerDrawGetDraw(ctx->viewer,0,&draw);CHKERRQ(ierr);
215     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
216     ierr = PetscDrawAxisCreate(draw,&ctx->axis);CHKERRQ(ierr);
217     ierr = PetscDrawAxisSetLimits(ctx->axis,bounds[0],bounds[2],bounds[1],bounds[3]);CHKERRQ(ierr);
218     ierr = PetscDrawAxisSetLabels(ctx->axis,"Phase Diagram","Variable 1","Variable 2");CHKERRQ(ierr);
219     ierr = PetscDrawAxisDraw(ctx->axis);CHKERRQ(ierr);
220     /* ierr = PetscDrawSetCoordinates(draw,bounds[0],bounds[1],bounds[2],bounds[3]);CHKERRQ(ierr); */
221     ierr = TSMonitorSet(ts,TSMonitorDrawSolutionPhase,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
222   }
223   opt  = PETSC_FALSE;
224   ierr = PetscOptionsName("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",&opt);CHKERRQ(ierr);
225   if (opt) {
226     TSMonitorDrawCtx ctx;
227     PetscInt         howoften = 1;
228 
229     ierr = PetscOptionsInt("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",howoften,&howoften,NULL);CHKERRQ(ierr);
230     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);CHKERRQ(ierr);
231     ierr = TSMonitorSet(ts,TSMonitorDrawError,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
232   }
233   opt  = PETSC_FALSE;
234   ierr = PetscOptionsString("-ts_monitor_solution_binary","Save each solution to a binary file","TSMonitorSolutionBinary",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
235   if (flg) {
236     PetscViewer ctx;
237     if (monfilename[0]) {
238       ierr = PetscViewerBinaryOpen(PetscObjectComm((PetscObject)ts),monfilename,FILE_MODE_WRITE,&ctx);CHKERRQ(ierr);
239       ierr = TSMonitorSet(ts,TSMonitorSolutionBinary,ctx,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr);
240     } else {
241       ctx = PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)ts));
242       ierr = TSMonitorSet(ts,TSMonitorSolutionBinary,ctx,(PetscErrorCode (*)(void**))NULL);CHKERRQ(ierr);
243     }
244   }
245   opt  = PETSC_FALSE;
246   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);
247   if (flg) {
248     const char *ptr,*ptr2;
249     char       *filetemplate;
250     if (!monfilename[0]) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
251     /* Do some cursory validation of the input. */
252     ierr = PetscStrstr(monfilename,"%",(char**)&ptr);CHKERRQ(ierr);
253     if (!ptr) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
254     for (ptr++; ptr && *ptr; ptr++) {
255       ierr = PetscStrchr("DdiouxX",*ptr,(char**)&ptr2);CHKERRQ(ierr);
256       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");
257       if (ptr2) break;
258     }
259     ierr = PetscStrallocpy(monfilename,&filetemplate);CHKERRQ(ierr);
260     ierr = TSMonitorSet(ts,TSMonitorSolutionVTK,filetemplate,(PetscErrorCode (*)(void**))TSMonitorSolutionVTKDestroy);CHKERRQ(ierr);
261   }
262 
263   ierr = PetscOptionsString("-ts_monitor_dmda_ray","Display a ray of the solution","None","y=0",dir,16,&flg);CHKERRQ(ierr);
264   if (flg) {
265     TSMonitorDMDARayCtx *rayctx;
266     int                 ray = 0;
267     DMDADirection       ddir;
268     DM                  da;
269     PetscMPIInt         rank;
270 
271     if (dir[1] != '=') SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
272     if (dir[0] == 'x') ddir = DMDA_X;
273     else if (dir[0] == 'y') ddir = DMDA_Y;
274     else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
275     sscanf(dir+2,"%d",&ray);
276 
277     ierr = PetscInfo2(((PetscObject)ts),"Displaying DMDA ray %c = %D\n",dir[0],ray);CHKERRQ(ierr);
278     ierr = PetscNew(TSMonitorDMDARayCtx,&rayctx);CHKERRQ(ierr);
279     ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
280     ierr = DMDAGetRay(da,ddir,ray,&rayctx->ray,&rayctx->scatter);CHKERRQ(ierr);
281     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)ts),&rank);CHKERRQ(ierr);
282     if (!rank) {
283       ierr = PetscViewerDrawOpen(PETSC_COMM_SELF,0,0,0,0,600,300,&rayctx->viewer);CHKERRQ(ierr);
284     }
285     ierr = TSMonitorSet(ts,TSMonitorDMDARay,rayctx,TSMonitorDMDARayDestroy);CHKERRQ(ierr);
286   }
287 
288   ierr = TSGetTSAdapt(ts,&adapt);CHKERRQ(ierr);
289   ierr = TSAdaptSetFromOptions(adapt);CHKERRQ(ierr);
290 
291   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
292   if (ts->problem_type == TS_LINEAR) {ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);}
293 
294   /* Handle specific TS options */
295   if (ts->ops->setfromoptions) {
296     ierr = (*ts->ops->setfromoptions)(ts);CHKERRQ(ierr);
297   }
298 
299   /* process any options handlers added with PetscObjectAddOptionsHandler() */
300   ierr = PetscObjectProcessOptionsHandlers((PetscObject)ts);CHKERRQ(ierr);
301   ierr = PetscOptionsEnd();CHKERRQ(ierr);
302   PetscFunctionReturn(0);
303 }
304 
305 #undef __FUNCT__
306 #undef __FUNCT__
307 #define __FUNCT__ "TSComputeRHSJacobian"
308 /*@
309    TSComputeRHSJacobian - Computes the Jacobian matrix that has been
310       set with TSSetRHSJacobian().
311 
312    Collective on TS and Vec
313 
314    Input Parameters:
315 +  ts - the TS context
316 .  t - current timestep
317 -  U - input vector
318 
319    Output Parameters:
320 +  A - Jacobian matrix
321 .  B - optional preconditioning matrix
322 -  flag - flag indicating matrix structure
323 
324    Notes:
325    Most users should not need to explicitly call this routine, as it
326    is used internally within the nonlinear solvers.
327 
328    See KSPSetOperators() for important information about setting the
329    flag parameter.
330 
331    Level: developer
332 
333 .keywords: SNES, compute, Jacobian, matrix
334 
335 .seealso:  TSSetRHSJacobian(), KSPSetOperators()
336 @*/
337 PetscErrorCode  TSComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat *A,Mat *B,MatStructure *flg)
338 {
339   PetscErrorCode ierr;
340   PetscInt       Ustate;
341   DM             dm;
342   DMTS           tsdm;
343   TSRHSJacobian  rhsjacobianfunc;
344   void           *ctx;
345   TSIJacobian    ijacobianfunc;
346 
347   PetscFunctionBegin;
348   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
349   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
350   PetscCheckSameComm(ts,1,U,3);
351   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
352   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
353   ierr = DMTSGetRHSJacobian(dm,&rhsjacobianfunc,&ctx);CHKERRQ(ierr);
354   ierr = DMTSGetIJacobian(dm,&ijacobianfunc,NULL);CHKERRQ(ierr);
355   ierr = PetscObjectStateQuery((PetscObject)U,&Ustate);CHKERRQ(ierr);
356   if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.X == U && ts->rhsjacobian.Xstate == Ustate))) {
357     *flg = ts->rhsjacobian.mstructure;
358     PetscFunctionReturn(0);
359   }
360 
361   if (!rhsjacobianfunc && !ijacobianfunc) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
362 
363   if (rhsjacobianfunc) {
364     ierr = PetscLogEventBegin(TS_JacobianEval,ts,U,*A,*B);CHKERRQ(ierr);
365     *flg = DIFFERENT_NONZERO_PATTERN;
366     PetscStackPush("TS user Jacobian function");
367     ierr = (*rhsjacobianfunc)(ts,t,U,A,B,flg,ctx);CHKERRQ(ierr);
368     PetscStackPop;
369     ierr = PetscLogEventEnd(TS_JacobianEval,ts,U,*A,*B);CHKERRQ(ierr);
370     /* make sure user returned a correct Jacobian and preconditioner */
371     PetscValidHeaderSpecific(*A,MAT_CLASSID,4);
372     PetscValidHeaderSpecific(*B,MAT_CLASSID,5);
373   } else {
374     ierr = MatZeroEntries(*A);CHKERRQ(ierr);
375     if (*A != *B) {ierr = MatZeroEntries(*B);CHKERRQ(ierr);}
376     *flg = SAME_NONZERO_PATTERN;
377   }
378   ts->rhsjacobian.time       = t;
379   ts->rhsjacobian.X          = U;
380   ierr                       = PetscObjectStateQuery((PetscObject)U,&ts->rhsjacobian.Xstate);CHKERRQ(ierr);
381   ts->rhsjacobian.mstructure = *flg;
382   PetscFunctionReturn(0);
383 }
384 
385 #undef __FUNCT__
386 #define __FUNCT__ "TSComputeRHSFunction"
387 /*@
388    TSComputeRHSFunction - Evaluates the right-hand-side function.
389 
390    Collective on TS and Vec
391 
392    Input Parameters:
393 +  ts - the TS context
394 .  t - current time
395 -  U - state vector
396 
397    Output Parameter:
398 .  y - right hand side
399 
400    Note:
401    Most users should not need to explicitly call this routine, as it
402    is used internally within the nonlinear solvers.
403 
404    Level: developer
405 
406 .keywords: TS, compute
407 
408 .seealso: TSSetRHSFunction(), TSComputeIFunction()
409 @*/
410 PetscErrorCode TSComputeRHSFunction(TS ts,PetscReal t,Vec U,Vec y)
411 {
412   PetscErrorCode ierr;
413   TSRHSFunction  rhsfunction;
414   TSIFunction    ifunction;
415   void           *ctx;
416   DM             dm;
417 
418   PetscFunctionBegin;
419   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
420   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
421   PetscValidHeaderSpecific(y,VEC_CLASSID,4);
422   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
423   ierr = DMTSGetRHSFunction(dm,&rhsfunction,&ctx);CHKERRQ(ierr);
424   ierr = DMTSGetIFunction(dm,&ifunction,NULL);CHKERRQ(ierr);
425 
426   if (!rhsfunction && !ifunction) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
427 
428   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,y,0);CHKERRQ(ierr);
429   if (rhsfunction) {
430     PetscStackPush("TS user right-hand-side function");
431     ierr = (*rhsfunction)(ts,t,U,y,ctx);CHKERRQ(ierr);
432     PetscStackPop;
433   } else {
434     ierr = VecZeroEntries(y);CHKERRQ(ierr);
435   }
436 
437   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,y,0);CHKERRQ(ierr);
438   PetscFunctionReturn(0);
439 }
440 
441 #undef __FUNCT__
442 #define __FUNCT__ "TSComputeSolutionFunction"
443 /*@
444    TSComputeSolutionFunction - Evaluates the solution function.
445 
446    Collective on TS and Vec
447 
448    Input Parameters:
449 +  ts - the TS context
450 -  t - current time
451 
452    Output Parameter:
453 .  U - the solution
454 
455    Note:
456    Most users should not need to explicitly call this routine, as it
457    is used internally within the nonlinear solvers.
458 
459    Level: developer
460 
461 .keywords: TS, compute
462 
463 .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction()
464 @*/
465 PetscErrorCode TSComputeSolutionFunction(TS ts,PetscReal t,Vec U)
466 {
467   PetscErrorCode     ierr;
468   TSSolutionFunction solutionfunction;
469   void               *ctx;
470   DM                 dm;
471 
472   PetscFunctionBegin;
473   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
474   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
475   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
476   ierr = DMTSGetSolutionFunction(dm,&solutionfunction,&ctx);CHKERRQ(ierr);
477 
478   if (solutionfunction) {
479     PetscStackPush("TS user solution function");
480     ierr = (*solutionfunction)(ts,t,U,ctx);CHKERRQ(ierr);
481     PetscStackPop;
482   }
483   PetscFunctionReturn(0);
484 }
485 #undef __FUNCT__
486 #define __FUNCT__ "TSComputeForcingFunction"
487 /*@
488    TSComputeForcingFunction - Evaluates the forcing function.
489 
490    Collective on TS and Vec
491 
492    Input Parameters:
493 +  ts - the TS context
494 -  t - current time
495 
496    Output Parameter:
497 .  U - the function value
498 
499    Note:
500    Most users should not need to explicitly call this routine, as it
501    is used internally within the nonlinear solvers.
502 
503    Level: developer
504 
505 .keywords: TS, compute
506 
507 .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction()
508 @*/
509 PetscErrorCode TSComputeForcingFunction(TS ts,PetscReal t,Vec U)
510 {
511   PetscErrorCode     ierr, (*forcing)(TS,PetscReal,Vec,void*);
512   void               *ctx;
513   DM                 dm;
514 
515   PetscFunctionBegin;
516   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
517   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
518   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
519   ierr = DMTSGetForcingFunction(dm,&forcing,&ctx);CHKERRQ(ierr);
520 
521   if (forcing) {
522     PetscStackPush("TS user forcing function");
523     ierr = (*forcing)(ts,t,U,ctx);CHKERRQ(ierr);
524     PetscStackPop;
525   }
526   PetscFunctionReturn(0);
527 }
528 
529 #undef __FUNCT__
530 #define __FUNCT__ "TSGetRHSVec_Private"
531 static PetscErrorCode TSGetRHSVec_Private(TS ts,Vec *Frhs)
532 {
533   Vec            F;
534   PetscErrorCode ierr;
535 
536   PetscFunctionBegin;
537   *Frhs = NULL;
538   ierr  = TSGetIFunction(ts,&F,NULL,NULL);CHKERRQ(ierr);
539   if (!ts->Frhs) {
540     ierr = VecDuplicate(F,&ts->Frhs);CHKERRQ(ierr);
541   }
542   *Frhs = ts->Frhs;
543   PetscFunctionReturn(0);
544 }
545 
546 #undef __FUNCT__
547 #define __FUNCT__ "TSGetRHSMats_Private"
548 static PetscErrorCode TSGetRHSMats_Private(TS ts,Mat *Arhs,Mat *Brhs)
549 {
550   Mat            A,B;
551   PetscErrorCode ierr;
552 
553   PetscFunctionBegin;
554   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
555   if (Arhs) {
556     if (!ts->Arhs) {
557       ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&ts->Arhs);CHKERRQ(ierr);
558     }
559     *Arhs = ts->Arhs;
560   }
561   if (Brhs) {
562     if (!ts->Brhs) {
563       ierr = MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&ts->Brhs);CHKERRQ(ierr);
564     }
565     *Brhs = ts->Brhs;
566   }
567   PetscFunctionReturn(0);
568 }
569 
570 #undef __FUNCT__
571 #define __FUNCT__ "TSComputeIFunction"
572 /*@
573    TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,U,Udot)=0
574 
575    Collective on TS and Vec
576 
577    Input Parameters:
578 +  ts - the TS context
579 .  t - current time
580 .  U - state vector
581 .  Udot - time derivative of state vector
582 -  imex - flag indicates if the method is IMEX so that the RHSFunction should be kept separate
583 
584    Output Parameter:
585 .  Y - right hand side
586 
587    Note:
588    Most users should not need to explicitly call this routine, as it
589    is used internally within the nonlinear solvers.
590 
591    If the user did did not write their equations in implicit form, this
592    function recasts them in implicit form.
593 
594    Level: developer
595 
596 .keywords: TS, compute
597 
598 .seealso: TSSetIFunction(), TSComputeRHSFunction()
599 @*/
600 PetscErrorCode TSComputeIFunction(TS ts,PetscReal t,Vec U,Vec Udot,Vec Y,PetscBool imex)
601 {
602   PetscErrorCode ierr;
603   TSIFunction    ifunction;
604   TSRHSFunction  rhsfunction;
605   void           *ctx;
606   DM             dm;
607 
608   PetscFunctionBegin;
609   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
610   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
611   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
612   PetscValidHeaderSpecific(Y,VEC_CLASSID,5);
613 
614   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
615   ierr = DMTSGetIFunction(dm,&ifunction,&ctx);CHKERRQ(ierr);
616   ierr = DMTSGetRHSFunction(dm,&rhsfunction,NULL);CHKERRQ(ierr);
617 
618   if (!rhsfunction && !ifunction) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
619 
620   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,Udot,Y);CHKERRQ(ierr);
621   if (ifunction) {
622     PetscStackPush("TS user implicit function");
623     ierr = (*ifunction)(ts,t,U,Udot,Y,ctx);CHKERRQ(ierr);
624     PetscStackPop;
625   }
626   if (imex) {
627     if (!ifunction) {
628       ierr = VecCopy(Udot,Y);CHKERRQ(ierr);
629     }
630   } else if (rhsfunction) {
631     if (ifunction) {
632       Vec Frhs;
633       ierr = TSGetRHSVec_Private(ts,&Frhs);CHKERRQ(ierr);
634       ierr = TSComputeRHSFunction(ts,t,U,Frhs);CHKERRQ(ierr);
635       ierr = VecAXPY(Y,-1,Frhs);CHKERRQ(ierr);
636     } else {
637       ierr = TSComputeRHSFunction(ts,t,U,Y);CHKERRQ(ierr);
638       ierr = VecAYPX(Y,-1,Udot);CHKERRQ(ierr);
639     }
640   }
641   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,Udot,Y);CHKERRQ(ierr);
642   PetscFunctionReturn(0);
643 }
644 
645 #undef __FUNCT__
646 #define __FUNCT__ "TSComputeIJacobian"
647 /*@
648    TSComputeIJacobian - Evaluates the Jacobian of the DAE
649 
650    Collective on TS and Vec
651 
652    Input
653       Input Parameters:
654 +  ts - the TS context
655 .  t - current timestep
656 .  U - state vector
657 .  Udot - time derivative of state vector
658 .  shift - shift to apply, see note below
659 -  imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate
660 
661    Output Parameters:
662 +  A - Jacobian matrix
663 .  B - optional preconditioning matrix
664 -  flag - flag indicating matrix structure
665 
666    Notes:
667    If F(t,U,Udot)=0 is the DAE, the required Jacobian is
668 
669    dF/dU + shift*dF/dUdot
670 
671    Most users should not need to explicitly call this routine, as it
672    is used internally within the nonlinear solvers.
673 
674    Level: developer
675 
676 .keywords: TS, compute, Jacobian, matrix
677 
678 .seealso:  TSSetIJacobian()
679 @*/
680 PetscErrorCode TSComputeIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat *A,Mat *B,MatStructure *flg,PetscBool imex)
681 {
682   PetscInt       Ustate, Udotstate;
683   PetscErrorCode ierr;
684   TSIJacobian    ijacobian;
685   TSRHSJacobian  rhsjacobian;
686   DM             dm;
687   void           *ctx;
688 
689   PetscFunctionBegin;
690   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
691   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
692   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
693   PetscValidPointer(A,6);
694   PetscValidHeaderSpecific(*A,MAT_CLASSID,6);
695   PetscValidPointer(B,7);
696   PetscValidHeaderSpecific(*B,MAT_CLASSID,7);
697   PetscValidPointer(flg,8);
698 
699   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
700   ierr = DMTSGetIJacobian(dm,&ijacobian,&ctx);CHKERRQ(ierr);
701   ierr = DMTSGetRHSJacobian(dm,&rhsjacobian,NULL);CHKERRQ(ierr);
702 
703   ierr = PetscObjectStateQuery((PetscObject)U,&Ustate);CHKERRQ(ierr);
704   ierr = PetscObjectStateQuery((PetscObject)Udot,&Udotstate);CHKERRQ(ierr);
705   if (ts->ijacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->ijacobian.X == U && ts->ijacobian.Xstate == Ustate && ts->ijacobian.Xdot == Udot && ts->ijacobian.Xdotstate == Udotstate && ts->ijacobian.imex == imex))) {
706     *flg = ts->ijacobian.mstructure;
707     ierr = MatScale(*A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
708     PetscFunctionReturn(0);
709   }
710 
711   if (!rhsjacobian && !ijacobian) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
712 
713   *flg = SAME_NONZERO_PATTERN;  /* In case we're solving a linear problem in which case it wouldn't get initialized below. */
714   ierr = PetscLogEventBegin(TS_JacobianEval,ts,U,*A,*B);CHKERRQ(ierr);
715   if (ijacobian) {
716     *flg = DIFFERENT_NONZERO_PATTERN;
717     PetscStackPush("TS user implicit Jacobian");
718     ierr = (*ijacobian)(ts,t,U,Udot,shift,A,B,flg,ctx);CHKERRQ(ierr);
719     PetscStackPop;
720     /* make sure user returned a correct Jacobian and preconditioner */
721     PetscValidHeaderSpecific(*A,MAT_CLASSID,4);
722     PetscValidHeaderSpecific(*B,MAT_CLASSID,5);
723   }
724   if (imex) {
725     if (!ijacobian) {  /* system was written as Udot = G(t,U) */
726       ierr = MatZeroEntries(*A);CHKERRQ(ierr);
727       ierr = MatShift(*A,shift);CHKERRQ(ierr);
728       if (*A != *B) {
729         ierr = MatZeroEntries(*B);CHKERRQ(ierr);
730         ierr = MatShift(*B,shift);CHKERRQ(ierr);
731       }
732       *flg = SAME_PRECONDITIONER;
733     }
734   } else {
735     if (!ijacobian) {
736       ierr = TSComputeRHSJacobian(ts,t,U,A,B,flg);CHKERRQ(ierr);
737       ierr = MatScale(*A,-1);CHKERRQ(ierr);
738       ierr = MatShift(*A,shift);CHKERRQ(ierr);
739       if (*A != *B) {
740         ierr = MatScale(*B,-1);CHKERRQ(ierr);
741         ierr = MatShift(*B,shift);CHKERRQ(ierr);
742       }
743     } else if (rhsjacobian) {
744       Mat          Arhs,Brhs;
745       MatStructure axpy,flg2 = DIFFERENT_NONZERO_PATTERN;
746       ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
747       ierr = TSComputeRHSJacobian(ts,t,U,&Arhs,&Brhs,&flg2);CHKERRQ(ierr);
748       axpy = (*flg == flg2) ? SAME_NONZERO_PATTERN : DIFFERENT_NONZERO_PATTERN;
749       ierr = MatAXPY(*A,-1,Arhs,axpy);CHKERRQ(ierr);
750       if (*A != *B) {
751         ierr = MatAXPY(*B,-1,Brhs,axpy);CHKERRQ(ierr);
752       }
753       *flg = PetscMin(*flg,flg2);
754     }
755   }
756 
757   ts->ijacobian.time = t;
758   ts->ijacobian.X    = U;
759   ts->ijacobian.Xdot = Udot;
760 
761   ierr = PetscObjectStateQuery((PetscObject)U,&ts->ijacobian.Xstate);CHKERRQ(ierr);
762   ierr = PetscObjectStateQuery((PetscObject)Udot,&ts->ijacobian.Xdotstate);CHKERRQ(ierr);
763 
764   ts->ijacobian.shift      = shift;
765   ts->ijacobian.imex       = imex;
766   ts->ijacobian.mstructure = *flg;
767 
768   ierr = PetscLogEventEnd(TS_JacobianEval,ts,U,*A,*B);CHKERRQ(ierr);
769   PetscFunctionReturn(0);
770 }
771 
772 #undef __FUNCT__
773 #define __FUNCT__ "TSSetRHSFunction"
774 /*@C
775     TSSetRHSFunction - Sets the routine for evaluating the function,
776     where U_t = G(t,u).
777 
778     Logically Collective on TS
779 
780     Input Parameters:
781 +   ts - the TS context obtained from TSCreate()
782 .   r - vector to put the computed right hand side (or NULL to have it created)
783 .   f - routine for evaluating the right-hand-side function
784 -   ctx - [optional] user-defined context for private data for the
785           function evaluation routine (may be NULL)
786 
787     Calling sequence of func:
788 $     func (TS ts,PetscReal t,Vec u,Vec F,void *ctx);
789 
790 +   t - current timestep
791 .   u - input vector
792 .   F - function vector
793 -   ctx - [optional] user-defined function context
794 
795     Level: beginner
796 
797 .keywords: TS, timestep, set, right-hand-side, function
798 
799 .seealso: TSSetRHSJacobian(), TSSetIJacobian()
800 @*/
801 PetscErrorCode  TSSetRHSFunction(TS ts,Vec r,PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*),void *ctx)
802 {
803   PetscErrorCode ierr;
804   SNES           snes;
805   Vec            ralloc = NULL;
806   DM             dm;
807 
808   PetscFunctionBegin;
809   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
810   if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2);
811 
812   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
813   ierr = DMTSSetRHSFunction(dm,f,ctx);CHKERRQ(ierr);
814   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
815   if (!r && !ts->dm && ts->vec_sol) {
816     ierr = VecDuplicate(ts->vec_sol,&ralloc);CHKERRQ(ierr);
817     r    = ralloc;
818   }
819   ierr = SNESSetFunction(snes,r,SNESTSFormFunction,ts);CHKERRQ(ierr);
820   ierr = VecDestroy(&ralloc);CHKERRQ(ierr);
821   PetscFunctionReturn(0);
822 }
823 
824 #undef __FUNCT__
825 #define __FUNCT__ "TSSetSolutionFunction"
826 /*@C
827     TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE
828 
829     Logically Collective on TS
830 
831     Input Parameters:
832 +   ts - the TS context obtained from TSCreate()
833 .   f - routine for evaluating the solution
834 -   ctx - [optional] user-defined context for private data for the
835           function evaluation routine (may be NULL)
836 
837     Calling sequence of func:
838 $     func (TS ts,PetscReal t,Vec u,void *ctx);
839 
840 +   t - current timestep
841 .   u - output vector
842 -   ctx - [optional] user-defined function context
843 
844     Notes:
845     This routine is used for testing accuracy of time integration schemes when you already know the solution.
846     If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to
847     create closed-form solutions with non-physical forcing terms.
848 
849     For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history.
850 
851     Level: beginner
852 
853 .keywords: TS, timestep, set, right-hand-side, function
854 
855 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetForcingFunction()
856 @*/
857 PetscErrorCode  TSSetSolutionFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx)
858 {
859   PetscErrorCode ierr;
860   DM             dm;
861 
862   PetscFunctionBegin;
863   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
864   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
865   ierr = DMTSSetSolutionFunction(dm,f,ctx);CHKERRQ(ierr);
866   PetscFunctionReturn(0);
867 }
868 
869 #undef __FUNCT__
870 #define __FUNCT__ "TSSetForcingFunction"
871 /*@C
872     TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE
873 
874     Logically Collective on TS
875 
876     Input Parameters:
877 +   ts - the TS context obtained from TSCreate()
878 .   f - routine for evaluating the forcing function
879 -   ctx - [optional] user-defined context for private data for the
880           function evaluation routine (may be NULL)
881 
882     Calling sequence of func:
883 $     func (TS ts,PetscReal t,Vec u,void *ctx);
884 
885 +   t - current timestep
886 .   u - output vector
887 -   ctx - [optional] user-defined function context
888 
889     Notes:
890     This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to
891     create closed-form solutions with a non-physical forcing term.
892 
893     For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history.
894 
895     Level: beginner
896 
897 .keywords: TS, timestep, set, right-hand-side, function
898 
899 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetSolutionFunction()
900 @*/
901 PetscErrorCode  TSSetForcingFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx)
902 {
903   PetscErrorCode ierr;
904   DM             dm;
905 
906   PetscFunctionBegin;
907   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
908   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
909   ierr = DMTSSetForcingFunction(dm,f,ctx);CHKERRQ(ierr);
910   PetscFunctionReturn(0);
911 }
912 
913 #undef __FUNCT__
914 #define __FUNCT__ "TSSetRHSJacobian"
915 /*@C
916    TSSetRHSJacobian - Sets the function to compute the Jacobian of F,
917    where U_t = G(U,t), as well as the location to store the matrix.
918 
919    Logically Collective on TS
920 
921    Input Parameters:
922 +  ts  - the TS context obtained from TSCreate()
923 .  Amat - (approximate) Jacobian matrix
924 .  Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
925 .  f   - the Jacobian evaluation routine
926 -  ctx - [optional] user-defined context for private data for the
927          Jacobian evaluation routine (may be NULL)
928 
929    Calling sequence of func:
930 $     func (TS ts,PetscReal t,Vec u,Mat *A,Mat *B,MatStructure *flag,void *ctx);
931 
932 +  t - current timestep
933 .  u - input vector
934 .  Amat - (approximate) Jacobian matrix
935 .  Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
936 .  flag - flag indicating information about the preconditioner matrix
937           structure (same as flag in KSPSetOperators())
938 -  ctx - [optional] user-defined context for matrix evaluation routine
939 
940    Notes:
941    See KSPSetOperators() for important information about setting the flag
942    output parameter in the routine func().  Be sure to read this information!
943 
944    The routine func() takes Mat * as the matrix arguments rather than Mat.
945    This allows the matrix evaluation routine to replace A and/or B with a
946    completely new matrix structure (not just different matrix elements)
947    when appropriate, for instance, if the nonzero structure is changing
948    throughout the global iterations.
949 
950    Level: beginner
951 
952 .keywords: TS, timestep, set, right-hand-side, Jacobian
953 
954 .seealso: SNESComputeJacobianDefaultColor(), TSSetRHSFunction()
955 
956 @*/
957 PetscErrorCode  TSSetRHSJacobian(TS ts,Mat Amat,Mat Pmat,TSRHSJacobian f,void *ctx)
958 {
959   PetscErrorCode ierr;
960   SNES           snes;
961   DM             dm;
962   TSIJacobian    ijacobian;
963 
964   PetscFunctionBegin;
965   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
966   if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
967   if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3);
968   if (Amat) PetscCheckSameComm(ts,1,Amat,2);
969   if (Pmat) PetscCheckSameComm(ts,1,Pmat,3);
970 
971   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
972   ierr = DMTSSetRHSJacobian(dm,f,ctx);CHKERRQ(ierr);
973   ierr = DMTSGetIJacobian(dm,&ijacobian,NULL);CHKERRQ(ierr);
974 
975   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
976   if (!ijacobian) {
977     ierr = SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts);CHKERRQ(ierr);
978   }
979   if (Amat) {
980     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
981     ierr = MatDestroy(&ts->Arhs);CHKERRQ(ierr);
982 
983     ts->Arhs = Amat;
984   }
985   if (Pmat) {
986     ierr = PetscObjectReference((PetscObject)Pmat);CHKERRQ(ierr);
987     ierr = MatDestroy(&ts->Brhs);CHKERRQ(ierr);
988 
989     ts->Brhs = Pmat;
990   }
991   PetscFunctionReturn(0);
992 }
993 
994 
995 #undef __FUNCT__
996 #define __FUNCT__ "TSSetIFunction"
997 /*@C
998    TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved.
999 
1000    Logically Collective on TS
1001 
1002    Input Parameters:
1003 +  ts  - the TS context obtained from TSCreate()
1004 .  r   - vector to hold the residual (or NULL to have it created internally)
1005 .  f   - the function evaluation routine
1006 -  ctx - user-defined context for private data for the function evaluation routine (may be NULL)
1007 
1008    Calling sequence of f:
1009 $  f(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx);
1010 
1011 +  t   - time at step/stage being solved
1012 .  u   - state vector
1013 .  u_t - time derivative of state vector
1014 .  F   - function vector
1015 -  ctx - [optional] user-defined context for matrix evaluation routine
1016 
1017    Important:
1018    The user MUST call either this routine, TSSetRHSFunction().  This routine must be used when not solving an ODE, for example a DAE.
1019 
1020    Level: beginner
1021 
1022 .keywords: TS, timestep, set, DAE, Jacobian
1023 
1024 .seealso: TSSetRHSJacobian(), TSSetRHSFunction(), TSSetIJacobian()
1025 @*/
1026 PetscErrorCode  TSSetIFunction(TS ts,Vec res,TSIFunction f,void *ctx)
1027 {
1028   PetscErrorCode ierr;
1029   SNES           snes;
1030   Vec            resalloc = NULL;
1031   DM             dm;
1032 
1033   PetscFunctionBegin;
1034   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1035   if (res) PetscValidHeaderSpecific(res,VEC_CLASSID,2);
1036 
1037   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1038   ierr = DMTSSetIFunction(dm,f,ctx);CHKERRQ(ierr);
1039 
1040   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1041   if (!res && !ts->dm && ts->vec_sol) {
1042     ierr = VecDuplicate(ts->vec_sol,&resalloc);CHKERRQ(ierr);
1043     res  = resalloc;
1044   }
1045   ierr = SNESSetFunction(snes,res,SNESTSFormFunction,ts);CHKERRQ(ierr);
1046   ierr = VecDestroy(&resalloc);CHKERRQ(ierr);
1047   PetscFunctionReturn(0);
1048 }
1049 
1050 #undef __FUNCT__
1051 #define __FUNCT__ "TSGetIFunction"
1052 /*@C
1053    TSGetIFunction - Returns the vector where the implicit residual is stored and the function/contex to compute it.
1054 
1055    Not Collective
1056 
1057    Input Parameter:
1058 .  ts - the TS context
1059 
1060    Output Parameter:
1061 +  r - vector to hold residual (or NULL)
1062 .  func - the function to compute residual (or NULL)
1063 -  ctx - the function context (or NULL)
1064 
1065    Level: advanced
1066 
1067 .keywords: TS, nonlinear, get, function
1068 
1069 .seealso: TSSetIFunction(), SNESGetFunction()
1070 @*/
1071 PetscErrorCode TSGetIFunction(TS ts,Vec *r,TSIFunction *func,void **ctx)
1072 {
1073   PetscErrorCode ierr;
1074   SNES           snes;
1075   DM             dm;
1076 
1077   PetscFunctionBegin;
1078   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1079   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1080   ierr = SNESGetFunction(snes,r,NULL,NULL);CHKERRQ(ierr);
1081   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1082   ierr = DMTSGetIFunction(dm,func,ctx);CHKERRQ(ierr);
1083   PetscFunctionReturn(0);
1084 }
1085 
1086 #undef __FUNCT__
1087 #define __FUNCT__ "TSGetRHSFunction"
1088 /*@C
1089    TSGetRHSFunction - Returns the vector where the right hand side is stored and the function/context to compute it.
1090 
1091    Not Collective
1092 
1093    Input Parameter:
1094 .  ts - the TS context
1095 
1096    Output Parameter:
1097 +  r - vector to hold computed right hand side (or NULL)
1098 .  func - the function to compute right hand side (or NULL)
1099 -  ctx - the function context (or NULL)
1100 
1101    Level: advanced
1102 
1103 .keywords: TS, nonlinear, get, function
1104 
1105 .seealso: TSSetRhsfunction(), SNESGetFunction()
1106 @*/
1107 PetscErrorCode TSGetRHSFunction(TS ts,Vec *r,TSRHSFunction *func,void **ctx)
1108 {
1109   PetscErrorCode ierr;
1110   SNES           snes;
1111   DM             dm;
1112 
1113   PetscFunctionBegin;
1114   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1115   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1116   ierr = SNESGetFunction(snes,r,NULL,NULL);CHKERRQ(ierr);
1117   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1118   ierr = DMTSGetRHSFunction(dm,func,ctx);CHKERRQ(ierr);
1119   PetscFunctionReturn(0);
1120 }
1121 
1122 #undef __FUNCT__
1123 #define __FUNCT__ "TSSetIJacobian"
1124 /*@C
1125    TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function
1126         you provided with TSSetIFunction().
1127 
1128    Logically Collective on TS
1129 
1130    Input Parameters:
1131 +  ts  - the TS context obtained from TSCreate()
1132 .  Amat - (approximate) Jacobian matrix
1133 .  Pmat - matrix used to compute preconditioner (usually the same as Amat)
1134 .  f   - the Jacobian evaluation routine
1135 -  ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL)
1136 
1137    Calling sequence of f:
1138 $  f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat *Amat,Mat *Pmat,MatStructure *flag,void *ctx);
1139 
1140 +  t    - time at step/stage being solved
1141 .  U    - state vector
1142 .  U_t  - time derivative of state vector
1143 .  a    - shift
1144 .  Amat - (approximate) Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
1145 .  Pmat - matrix used for constructing preconditioner, usually the same as Amat
1146 .  flag - flag indicating information about the preconditioner matrix
1147           structure (same as flag in KSPSetOperators())
1148 -  ctx  - [optional] user-defined context for matrix evaluation routine
1149 
1150    Notes:
1151    The matrices Amat and Pmat are exactly the matrices that are used by SNES for the nonlinear solve.
1152 
1153    The matrix dF/dU + a*dF/dU_t you provide turns out to be
1154    the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
1155    The time integrator internally approximates U_t by W+a*U where the positive "shift"
1156    a and vector W depend on the integration method, step size, and past states. For example with
1157    the backward Euler method a = 1/dt and W = -a*U(previous timestep) so
1158    W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt
1159 
1160    Level: beginner
1161 
1162 .keywords: TS, timestep, DAE, Jacobian
1163 
1164 .seealso: TSSetIFunction(), TSSetRHSJacobian(), SNESComputeJacobianDefaultColor(), SNESComputeJacobianDefault()
1165 
1166 @*/
1167 PetscErrorCode  TSSetIJacobian(TS ts,Mat Amat,Mat Pmat,TSIJacobian f,void *ctx)
1168 {
1169   PetscErrorCode ierr;
1170   SNES           snes;
1171   DM             dm;
1172 
1173   PetscFunctionBegin;
1174   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1175   if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
1176   if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3);
1177   if (Amat) PetscCheckSameComm(ts,1,Amat,2);
1178   if (Pmat) PetscCheckSameComm(ts,1,Pmat,3);
1179 
1180   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1181   ierr = DMTSSetIJacobian(dm,f,ctx);CHKERRQ(ierr);
1182 
1183   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1184   ierr = SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts);CHKERRQ(ierr);
1185   PetscFunctionReturn(0);
1186 }
1187 
1188 #undef __FUNCT__
1189 #define __FUNCT__ "TSLoad"
1190 /*@C
1191   TSLoad - Loads a KSP that has been stored in binary  with KSPView().
1192 
1193   Collective on PetscViewer
1194 
1195   Input Parameters:
1196 + newdm - the newly loaded TS, this needs to have been created with TSCreate() or
1197            some related function before a call to TSLoad().
1198 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen()
1199 
1200    Level: intermediate
1201 
1202   Notes:
1203    The type is determined by the data in the file, any type set into the TS before this call is ignored.
1204 
1205   Notes for advanced users:
1206   Most users should not need to know the details of the binary storage
1207   format, since TSLoad() and TSView() completely hide these details.
1208   But for anyone who's interested, the standard binary matrix storage
1209   format is
1210 .vb
1211      has not yet been determined
1212 .ve
1213 
1214 .seealso: PetscViewerBinaryOpen(), TSView(), MatLoad(), VecLoad()
1215 @*/
1216 PetscErrorCode  TSLoad(TS ts, PetscViewer viewer)
1217 {
1218   PetscErrorCode ierr;
1219   PetscBool      isbinary;
1220   PetscInt       classid;
1221   char           type[256];
1222   DMTS           sdm;
1223   DM             dm;
1224 
1225   PetscFunctionBegin;
1226   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1227   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1228   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1229   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
1230 
1231   ierr = PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);CHKERRQ(ierr);
1232   if (classid != TS_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Not TS next in file");
1233   ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr);
1234   ierr = TSSetType(ts, type);CHKERRQ(ierr);
1235   if (ts->ops->load) {
1236     ierr = (*ts->ops->load)(ts,viewer);CHKERRQ(ierr);
1237   }
1238   ierr = DMCreate(PetscObjectComm((PetscObject)ts),&dm);CHKERRQ(ierr);
1239   ierr = DMLoad(dm,viewer);CHKERRQ(ierr);
1240   ierr = TSSetDM(ts,dm);CHKERRQ(ierr);
1241   ierr = DMCreateGlobalVector(ts->dm,&ts->vec_sol);CHKERRQ(ierr);
1242   ierr = VecLoad(ts->vec_sol,viewer);CHKERRQ(ierr);
1243   ierr = DMGetDMTS(ts->dm,&sdm);CHKERRQ(ierr);
1244   ierr = DMTSLoad(sdm,viewer);CHKERRQ(ierr);
1245   PetscFunctionReturn(0);
1246 }
1247 
1248 #include <petscdraw.h>
1249 #if defined(PETSC_HAVE_AMS)
1250 #include <petscviewerams.h>
1251 #endif
1252 #undef __FUNCT__
1253 #define __FUNCT__ "TSView"
1254 /*@C
1255     TSView - Prints the TS data structure.
1256 
1257     Collective on TS
1258 
1259     Input Parameters:
1260 +   ts - the TS context obtained from TSCreate()
1261 -   viewer - visualization context
1262 
1263     Options Database Key:
1264 .   -ts_view - calls TSView() at end of TSStep()
1265 
1266     Notes:
1267     The available visualization contexts include
1268 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
1269 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1270          output where only the first processor opens
1271          the file.  All other processors send their
1272          data to the first processor to print.
1273 
1274     The user can open an alternative visualization context with
1275     PetscViewerASCIIOpen() - output to a specified file.
1276 
1277     Level: beginner
1278 
1279 .keywords: TS, timestep, view
1280 
1281 .seealso: PetscViewerASCIIOpen()
1282 @*/
1283 PetscErrorCode  TSView(TS ts,PetscViewer viewer)
1284 {
1285   PetscErrorCode ierr;
1286   TSType         type;
1287   PetscBool      iascii,isstring,isundials,isbinary,isdraw;
1288   DMTS           sdm;
1289 #if defined(PETSC_HAVE_AMS)
1290   PetscBool      isams;
1291 #endif
1292 
1293   PetscFunctionBegin;
1294   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1295   if (!viewer) {
1296     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts),&viewer);CHKERRQ(ierr);
1297   }
1298   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1299   PetscCheckSameComm(ts,1,viewer,2);
1300 
1301   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1302   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
1303   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1304   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1305 #if defined(PETSC_HAVE_AMS)
1306   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERAMS,&isams);CHKERRQ(ierr);
1307 #endif
1308   if (iascii) {
1309     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer,"TS Object");CHKERRQ(ierr);
1310     ierr = PetscViewerASCIIPrintf(viewer,"  maximum steps=%D\n",ts->max_steps);CHKERRQ(ierr);
1311     ierr = PetscViewerASCIIPrintf(viewer,"  maximum time=%G\n",ts->max_time);CHKERRQ(ierr);
1312     if (ts->problem_type == TS_NONLINEAR) {
1313       ierr = PetscViewerASCIIPrintf(viewer,"  total number of nonlinear solver iterations=%D\n",ts->snes_its);CHKERRQ(ierr);
1314       ierr = PetscViewerASCIIPrintf(viewer,"  total number of nonlinear solve failures=%D\n",ts->num_snes_failures);CHKERRQ(ierr);
1315     }
1316     ierr = PetscViewerASCIIPrintf(viewer,"  total number of linear solver iterations=%D\n",ts->ksp_its);CHKERRQ(ierr);
1317     ierr = PetscViewerASCIIPrintf(viewer,"  total number of rejected steps=%D\n",ts->reject);CHKERRQ(ierr);
1318     ierr = DMGetDMTS(ts->dm,&sdm);CHKERRQ(ierr);
1319     ierr = DMTSView(sdm,viewer);CHKERRQ(ierr);
1320     if (ts->ops->view) {
1321       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1322       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
1323       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1324     }
1325   } else if (isstring) {
1326     ierr = TSGetType(ts,&type);CHKERRQ(ierr);
1327     ierr = PetscViewerStringSPrintf(viewer," %-7.7s",type);CHKERRQ(ierr);
1328   } else if (isbinary) {
1329     PetscInt    classid = TS_FILE_CLASSID;
1330     MPI_Comm    comm;
1331     PetscMPIInt rank;
1332     char        type[256];
1333 
1334     ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
1335     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1336     if (!rank) {
1337       ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
1338       ierr = PetscStrncpy(type,((PetscObject)ts)->type_name,256);CHKERRQ(ierr);
1339       ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
1340     }
1341     if (ts->ops->view) {
1342       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
1343     }
1344     ierr = DMView(ts->dm,viewer);CHKERRQ(ierr);
1345     ierr = VecView(ts->vec_sol,viewer);CHKERRQ(ierr);
1346     ierr = DMGetDMTS(ts->dm,&sdm);CHKERRQ(ierr);
1347     ierr = DMTSView(sdm,viewer);CHKERRQ(ierr);
1348   } else if (isdraw) {
1349     PetscDraw draw;
1350     char      str[36];
1351     PetscReal x,y,bottom,h;
1352 
1353     ierr   = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1354     ierr   = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
1355     ierr   = PetscStrcpy(str,"TS: ");CHKERRQ(ierr);
1356     ierr   = PetscStrcat(str,((PetscObject)ts)->type_name);CHKERRQ(ierr);
1357     ierr   = PetscDrawBoxedString(draw,x,y,PETSC_DRAW_BLACK,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
1358     bottom = y - h;
1359     ierr   = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr);
1360     if (ts->ops->view) {
1361       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
1362     }
1363     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
1364 #if defined(PETSC_HAVE_AMS)
1365   } else if (isams) {
1366     if (((PetscObject)ts)->amsmem == -1) {
1367       ierr = PetscObjectViewAMS((PetscObject)ts,viewer);CHKERRQ(ierr);
1368       PetscStackCallAMS(AMS_Memory_take_access,(((PetscObject)ts)->amsmem));
1369       PetscStackCallAMS(AMS_Memory_add_field,(((PetscObject)ts)->amsmem,"time step",&ts->steps,1,AMS_INT,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF));
1370       PetscStackCallAMS(AMS_Memory_add_field,(((PetscObject)ts)->amsmem,"time",&ts->ptime,1,AMS_DOUBLE,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF));
1371       PetscStackCallAMS(AMS_Memory_grant_access,(((PetscObject)ts)->amsmem));
1372     }
1373     if (ts->ops->view) {
1374       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
1375     }
1376 #endif
1377   }
1378 
1379   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1380   ierr = PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials);CHKERRQ(ierr);
1381   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1382   PetscFunctionReturn(0);
1383 }
1384 
1385 
1386 #undef __FUNCT__
1387 #define __FUNCT__ "TSSetApplicationContext"
1388 /*@
1389    TSSetApplicationContext - Sets an optional user-defined context for
1390    the timesteppers.
1391 
1392    Logically Collective on TS
1393 
1394    Input Parameters:
1395 +  ts - the TS context obtained from TSCreate()
1396 -  usrP - optional user context
1397 
1398    Level: intermediate
1399 
1400 .keywords: TS, timestep, set, application, context
1401 
1402 .seealso: TSGetApplicationContext()
1403 @*/
1404 PetscErrorCode  TSSetApplicationContext(TS ts,void *usrP)
1405 {
1406   PetscFunctionBegin;
1407   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1408   ts->user = usrP;
1409   PetscFunctionReturn(0);
1410 }
1411 
1412 #undef __FUNCT__
1413 #define __FUNCT__ "TSGetApplicationContext"
1414 /*@
1415     TSGetApplicationContext - Gets the user-defined context for the
1416     timestepper.
1417 
1418     Not Collective
1419 
1420     Input Parameter:
1421 .   ts - the TS context obtained from TSCreate()
1422 
1423     Output Parameter:
1424 .   usrP - user context
1425 
1426     Level: intermediate
1427 
1428 .keywords: TS, timestep, get, application, context
1429 
1430 .seealso: TSSetApplicationContext()
1431 @*/
1432 PetscErrorCode  TSGetApplicationContext(TS ts,void *usrP)
1433 {
1434   PetscFunctionBegin;
1435   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1436   *(void**)usrP = ts->user;
1437   PetscFunctionReturn(0);
1438 }
1439 
1440 #undef __FUNCT__
1441 #define __FUNCT__ "TSGetTimeStepNumber"
1442 /*@
1443    TSGetTimeStepNumber - Gets the number of time steps completed.
1444 
1445    Not Collective
1446 
1447    Input Parameter:
1448 .  ts - the TS context obtained from TSCreate()
1449 
1450    Output Parameter:
1451 .  iter - number of steps completed so far
1452 
1453    Level: intermediate
1454 
1455 .keywords: TS, timestep, get, iteration, number
1456 .seealso: TSGetTime(), TSGetTimeStep(), TSSetPreStep(), TSSetPreStage(), TSSetPostStep()
1457 @*/
1458 PetscErrorCode  TSGetTimeStepNumber(TS ts,PetscInt *iter)
1459 {
1460   PetscFunctionBegin;
1461   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1462   PetscValidIntPointer(iter,2);
1463   *iter = ts->steps;
1464   PetscFunctionReturn(0);
1465 }
1466 
1467 #undef __FUNCT__
1468 #define __FUNCT__ "TSSetInitialTimeStep"
1469 /*@
1470    TSSetInitialTimeStep - Sets the initial timestep to be used,
1471    as well as the initial time.
1472 
1473    Logically Collective on TS
1474 
1475    Input Parameters:
1476 +  ts - the TS context obtained from TSCreate()
1477 .  initial_time - the initial time
1478 -  time_step - the size of the timestep
1479 
1480    Level: intermediate
1481 
1482 .seealso: TSSetTimeStep(), TSGetTimeStep()
1483 
1484 .keywords: TS, set, initial, timestep
1485 @*/
1486 PetscErrorCode  TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step)
1487 {
1488   PetscErrorCode ierr;
1489 
1490   PetscFunctionBegin;
1491   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1492   ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr);
1493   ierr = TSSetTime(ts,initial_time);CHKERRQ(ierr);
1494   PetscFunctionReturn(0);
1495 }
1496 
1497 #undef __FUNCT__
1498 #define __FUNCT__ "TSSetTimeStep"
1499 /*@
1500    TSSetTimeStep - Allows one to reset the timestep at any time,
1501    useful for simple pseudo-timestepping codes.
1502 
1503    Logically Collective on TS
1504 
1505    Input Parameters:
1506 +  ts - the TS context obtained from TSCreate()
1507 -  time_step - the size of the timestep
1508 
1509    Level: intermediate
1510 
1511 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1512 
1513 .keywords: TS, set, timestep
1514 @*/
1515 PetscErrorCode  TSSetTimeStep(TS ts,PetscReal time_step)
1516 {
1517   PetscFunctionBegin;
1518   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1519   PetscValidLogicalCollectiveReal(ts,time_step,2);
1520   ts->time_step      = time_step;
1521   ts->time_step_orig = time_step;
1522   PetscFunctionReturn(0);
1523 }
1524 
1525 #undef __FUNCT__
1526 #define __FUNCT__ "TSSetExactFinalTime"
1527 /*@
1528    TSSetExactFinalTime - Determines whether to adapt the final time step to
1529      match the exact final time, interpolate solution to the exact final time,
1530      or just return at the final time TS computed.
1531 
1532   Logically Collective on TS
1533 
1534    Input Parameter:
1535 +   ts - the time-step context
1536 -   eftopt - exact final time option
1537 
1538    Level: beginner
1539 
1540 .seealso: TSExactFinalTimeOption
1541 @*/
1542 PetscErrorCode  TSSetExactFinalTime(TS ts,TSExactFinalTimeOption eftopt)
1543 {
1544   PetscFunctionBegin;
1545   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1546   PetscValidLogicalCollectiveEnum(ts,eftopt,2);
1547   ts->exact_final_time = eftopt;
1548   PetscFunctionReturn(0);
1549 }
1550 
1551 #undef __FUNCT__
1552 #define __FUNCT__ "TSGetTimeStep"
1553 /*@
1554    TSGetTimeStep - Gets the current timestep size.
1555 
1556    Not Collective
1557 
1558    Input Parameter:
1559 .  ts - the TS context obtained from TSCreate()
1560 
1561    Output Parameter:
1562 .  dt - the current timestep size
1563 
1564    Level: intermediate
1565 
1566 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1567 
1568 .keywords: TS, get, timestep
1569 @*/
1570 PetscErrorCode  TSGetTimeStep(TS ts,PetscReal *dt)
1571 {
1572   PetscFunctionBegin;
1573   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1574   PetscValidRealPointer(dt,2);
1575   *dt = ts->time_step;
1576   PetscFunctionReturn(0);
1577 }
1578 
1579 #undef __FUNCT__
1580 #define __FUNCT__ "TSGetSolution"
1581 /*@
1582    TSGetSolution - Returns the solution at the present timestep. It
1583    is valid to call this routine inside the function that you are evaluating
1584    in order to move to the new timestep. This vector not changed until
1585    the solution at the next timestep has been calculated.
1586 
1587    Not Collective, but Vec returned is parallel if TS is parallel
1588 
1589    Input Parameter:
1590 .  ts - the TS context obtained from TSCreate()
1591 
1592    Output Parameter:
1593 .  v - the vector containing the solution
1594 
1595    Level: intermediate
1596 
1597 .seealso: TSGetTimeStep()
1598 
1599 .keywords: TS, timestep, get, solution
1600 @*/
1601 PetscErrorCode  TSGetSolution(TS ts,Vec *v)
1602 {
1603   PetscFunctionBegin;
1604   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1605   PetscValidPointer(v,2);
1606   *v = ts->vec_sol;
1607   PetscFunctionReturn(0);
1608 }
1609 
1610 /* ----- Routines to initialize and destroy a timestepper ---- */
1611 #undef __FUNCT__
1612 #define __FUNCT__ "TSSetProblemType"
1613 /*@
1614   TSSetProblemType - Sets the type of problem to be solved.
1615 
1616   Not collective
1617 
1618   Input Parameters:
1619 + ts   - The TS
1620 - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1621 .vb
1622          U_t - A U = 0      (linear)
1623          U_t - A(t) U = 0   (linear)
1624          F(t,U,U_t) = 0     (nonlinear)
1625 .ve
1626 
1627    Level: beginner
1628 
1629 .keywords: TS, problem type
1630 .seealso: TSSetUp(), TSProblemType, TS
1631 @*/
1632 PetscErrorCode  TSSetProblemType(TS ts, TSProblemType type)
1633 {
1634   PetscErrorCode ierr;
1635 
1636   PetscFunctionBegin;
1637   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1638   ts->problem_type = type;
1639   if (type == TS_LINEAR) {
1640     SNES snes;
1641     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1642     ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);
1643   }
1644   PetscFunctionReturn(0);
1645 }
1646 
1647 #undef __FUNCT__
1648 #define __FUNCT__ "TSGetProblemType"
1649 /*@C
1650   TSGetProblemType - Gets the type of problem to be solved.
1651 
1652   Not collective
1653 
1654   Input Parameter:
1655 . ts   - The TS
1656 
1657   Output Parameter:
1658 . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1659 .vb
1660          M U_t = A U
1661          M(t) U_t = A(t) U
1662          F(t,U,U_t)
1663 .ve
1664 
1665    Level: beginner
1666 
1667 .keywords: TS, problem type
1668 .seealso: TSSetUp(), TSProblemType, TS
1669 @*/
1670 PetscErrorCode  TSGetProblemType(TS ts, TSProblemType *type)
1671 {
1672   PetscFunctionBegin;
1673   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1674   PetscValidIntPointer(type,2);
1675   *type = ts->problem_type;
1676   PetscFunctionReturn(0);
1677 }
1678 
1679 #undef __FUNCT__
1680 #define __FUNCT__ "TSSetUp"
1681 /*@
1682    TSSetUp - Sets up the internal data structures for the later use
1683    of a timestepper.
1684 
1685    Collective on TS
1686 
1687    Input Parameter:
1688 .  ts - the TS context obtained from TSCreate()
1689 
1690    Notes:
1691    For basic use of the TS solvers the user need not explicitly call
1692    TSSetUp(), since these actions will automatically occur during
1693    the call to TSStep().  However, if one wishes to control this
1694    phase separately, TSSetUp() should be called after TSCreate()
1695    and optional routines of the form TSSetXXX(), but before TSStep().
1696 
1697    Level: advanced
1698 
1699 .keywords: TS, timestep, setup
1700 
1701 .seealso: TSCreate(), TSStep(), TSDestroy()
1702 @*/
1703 PetscErrorCode  TSSetUp(TS ts)
1704 {
1705   PetscErrorCode ierr;
1706   DM             dm;
1707   PetscErrorCode (*func)(SNES,Vec,Vec,void*);
1708   PetscErrorCode (*jac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
1709   TSIJacobian    ijac;
1710   TSRHSJacobian  rhsjac;
1711 
1712   PetscFunctionBegin;
1713   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1714   if (ts->setupcalled) PetscFunctionReturn(0);
1715 
1716   if (!((PetscObject)ts)->type_name) {
1717     ierr = TSSetType(ts,TSEULER);CHKERRQ(ierr);
1718   }
1719 
1720   if (!ts->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first");
1721 
1722   ierr = TSGetTSAdapt(ts,&ts->adapt);CHKERRQ(ierr);
1723 
1724   if (ts->ops->setup) {
1725     ierr = (*ts->ops->setup)(ts);CHKERRQ(ierr);
1726   }
1727 
1728   /* in the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
1729    to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
1730    */
1731   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1732   ierr = DMSNESGetFunction(dm,&func,NULL);CHKERRQ(ierr);
1733   if (!func) {
1734     ierr =DMSNESSetFunction(dm,SNESTSFormFunction,ts);CHKERRQ(ierr);
1735   }
1736   /* if the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
1737      Otherwise, the SNES will use coloring internally to form the Jacobian.
1738    */
1739   ierr = DMSNESGetJacobian(dm,&jac,NULL);CHKERRQ(ierr);
1740   ierr = DMTSGetIJacobian(dm,&ijac,NULL);CHKERRQ(ierr);
1741   ierr = DMTSGetRHSJacobian(dm,&rhsjac,NULL);CHKERRQ(ierr);
1742   if (!jac && (ijac || rhsjac)) {
1743     ierr = DMSNESSetJacobian(dm,SNESTSFormJacobian,ts);CHKERRQ(ierr);
1744   }
1745   ts->setupcalled = PETSC_TRUE;
1746   PetscFunctionReturn(0);
1747 }
1748 
1749 #undef __FUNCT__
1750 #define __FUNCT__ "TSReset"
1751 /*@
1752    TSReset - Resets a TS context and removes any allocated Vecs and Mats.
1753 
1754    Collective on TS
1755 
1756    Input Parameter:
1757 .  ts - the TS context obtained from TSCreate()
1758 
1759    Level: beginner
1760 
1761 .keywords: TS, timestep, reset
1762 
1763 .seealso: TSCreate(), TSSetup(), TSDestroy()
1764 @*/
1765 PetscErrorCode  TSReset(TS ts)
1766 {
1767   PetscErrorCode ierr;
1768 
1769   PetscFunctionBegin;
1770   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1771   if (ts->ops->reset) {
1772     ierr = (*ts->ops->reset)(ts);CHKERRQ(ierr);
1773   }
1774   if (ts->snes) {ierr = SNESReset(ts->snes);CHKERRQ(ierr);}
1775 
1776   ierr = MatDestroy(&ts->Arhs);CHKERRQ(ierr);
1777   ierr = MatDestroy(&ts->Brhs);CHKERRQ(ierr);
1778   ierr = VecDestroy(&ts->Frhs);CHKERRQ(ierr);
1779   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
1780   ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
1781   ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
1782   ierr = VecDestroyVecs(ts->nwork,&ts->work);CHKERRQ(ierr);
1783   ierr = ISDestroy(&ts->is_diff);CHKERRQ(ierr);
1784 
1785   ts->setupcalled = PETSC_FALSE;
1786   PetscFunctionReturn(0);
1787 }
1788 
1789 #undef __FUNCT__
1790 #define __FUNCT__ "TSDestroy"
1791 /*@
1792    TSDestroy - Destroys the timestepper context that was created
1793    with TSCreate().
1794 
1795    Collective on TS
1796 
1797    Input Parameter:
1798 .  ts - the TS context obtained from TSCreate()
1799 
1800    Level: beginner
1801 
1802 .keywords: TS, timestepper, destroy
1803 
1804 .seealso: TSCreate(), TSSetUp(), TSSolve()
1805 @*/
1806 PetscErrorCode  TSDestroy(TS *ts)
1807 {
1808   PetscErrorCode ierr;
1809 
1810   PetscFunctionBegin;
1811   if (!*ts) PetscFunctionReturn(0);
1812   PetscValidHeaderSpecific((*ts),TS_CLASSID,1);
1813   if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; PetscFunctionReturn(0);}
1814 
1815   ierr = TSReset((*ts));CHKERRQ(ierr);
1816 
1817   /* if memory was published with AMS then destroy it */
1818   ierr = PetscObjectAMSViewOff((PetscObject)*ts);CHKERRQ(ierr);
1819   if ((*ts)->ops->destroy) {ierr = (*(*ts)->ops->destroy)((*ts));CHKERRQ(ierr);}
1820 
1821   ierr = TSAdaptDestroy(&(*ts)->adapt);CHKERRQ(ierr);
1822   ierr = SNESDestroy(&(*ts)->snes);CHKERRQ(ierr);
1823   ierr = DMDestroy(&(*ts)->dm);CHKERRQ(ierr);
1824   ierr = TSMonitorCancel((*ts));CHKERRQ(ierr);
1825 
1826   ierr = PetscHeaderDestroy(ts);CHKERRQ(ierr);
1827   PetscFunctionReturn(0);
1828 }
1829 
1830 #undef __FUNCT__
1831 #define __FUNCT__ "TSGetSNES"
1832 /*@
1833    TSGetSNES - Returns the SNES (nonlinear solver) associated with
1834    a TS (timestepper) context. Valid only for nonlinear problems.
1835 
1836    Not Collective, but SNES is parallel if TS is parallel
1837 
1838    Input Parameter:
1839 .  ts - the TS context obtained from TSCreate()
1840 
1841    Output Parameter:
1842 .  snes - the nonlinear solver context
1843 
1844    Notes:
1845    The user can then directly manipulate the SNES context to set various
1846    options, etc.  Likewise, the user can then extract and manipulate the
1847    KSP, KSP, and PC contexts as well.
1848 
1849    TSGetSNES() does not work for integrators that do not use SNES; in
1850    this case TSGetSNES() returns NULL in snes.
1851 
1852    Level: beginner
1853 
1854 .keywords: timestep, get, SNES
1855 @*/
1856 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
1857 {
1858   PetscErrorCode ierr;
1859 
1860   PetscFunctionBegin;
1861   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1862   PetscValidPointer(snes,2);
1863   if (!ts->snes) {
1864     ierr = SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes);CHKERRQ(ierr);
1865     ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
1866     ierr = PetscLogObjectParent(ts,ts->snes);CHKERRQ(ierr);
1867     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);CHKERRQ(ierr);
1868     if (ts->dm) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
1869     if (ts->problem_type == TS_LINEAR) {
1870       ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr);
1871     }
1872   }
1873   *snes = ts->snes;
1874   PetscFunctionReturn(0);
1875 }
1876 
1877 #undef __FUNCT__
1878 #define __FUNCT__ "TSSetSNES"
1879 /*@
1880    TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
1881 
1882    Collective
1883 
1884    Input Parameter:
1885 +  ts - the TS context obtained from TSCreate()
1886 -  snes - the nonlinear solver context
1887 
1888    Notes:
1889    Most users should have the TS created by calling TSGetSNES()
1890 
1891    Level: developer
1892 
1893 .keywords: timestep, set, SNES
1894 @*/
1895 PetscErrorCode TSSetSNES(TS ts,SNES snes)
1896 {
1897   PetscErrorCode ierr;
1898   PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
1899 
1900   PetscFunctionBegin;
1901   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1902   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
1903   ierr = PetscObjectReference((PetscObject)snes);CHKERRQ(ierr);
1904   ierr = SNESDestroy(&ts->snes);CHKERRQ(ierr);
1905 
1906   ts->snes = snes;
1907 
1908   ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
1909   ierr = SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL);CHKERRQ(ierr);
1910   if (func == SNESTSFormJacobian) {
1911     ierr = SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts);CHKERRQ(ierr);
1912   }
1913   PetscFunctionReturn(0);
1914 }
1915 
1916 #undef __FUNCT__
1917 #define __FUNCT__ "TSGetKSP"
1918 /*@
1919    TSGetKSP - Returns the KSP (linear solver) associated with
1920    a TS (timestepper) context.
1921 
1922    Not Collective, but KSP is parallel if TS is parallel
1923 
1924    Input Parameter:
1925 .  ts - the TS context obtained from TSCreate()
1926 
1927    Output Parameter:
1928 .  ksp - the nonlinear solver context
1929 
1930    Notes:
1931    The user can then directly manipulate the KSP context to set various
1932    options, etc.  Likewise, the user can then extract and manipulate the
1933    KSP and PC contexts as well.
1934 
1935    TSGetKSP() does not work for integrators that do not use KSP;
1936    in this case TSGetKSP() returns NULL in ksp.
1937 
1938    Level: beginner
1939 
1940 .keywords: timestep, get, KSP
1941 @*/
1942 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
1943 {
1944   PetscErrorCode ierr;
1945   SNES           snes;
1946 
1947   PetscFunctionBegin;
1948   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1949   PetscValidPointer(ksp,2);
1950   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
1951   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
1952   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1953   ierr = SNESGetKSP(snes,ksp);CHKERRQ(ierr);
1954   PetscFunctionReturn(0);
1955 }
1956 
1957 /* ----------- Routines to set solver parameters ---------- */
1958 
1959 #undef __FUNCT__
1960 #define __FUNCT__ "TSGetDuration"
1961 /*@
1962    TSGetDuration - Gets the maximum number of timesteps to use and
1963    maximum time for iteration.
1964 
1965    Not Collective
1966 
1967    Input Parameters:
1968 +  ts       - the TS context obtained from TSCreate()
1969 .  maxsteps - maximum number of iterations to use, or NULL
1970 -  maxtime  - final time to iterate to, or NULL
1971 
1972    Level: intermediate
1973 
1974 .keywords: TS, timestep, get, maximum, iterations, time
1975 @*/
1976 PetscErrorCode  TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
1977 {
1978   PetscFunctionBegin;
1979   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1980   if (maxsteps) {
1981     PetscValidIntPointer(maxsteps,2);
1982     *maxsteps = ts->max_steps;
1983   }
1984   if (maxtime) {
1985     PetscValidScalarPointer(maxtime,3);
1986     *maxtime = ts->max_time;
1987   }
1988   PetscFunctionReturn(0);
1989 }
1990 
1991 #undef __FUNCT__
1992 #define __FUNCT__ "TSSetDuration"
1993 /*@
1994    TSSetDuration - Sets the maximum number of timesteps to use and
1995    maximum time for iteration.
1996 
1997    Logically Collective on TS
1998 
1999    Input Parameters:
2000 +  ts - the TS context obtained from TSCreate()
2001 .  maxsteps - maximum number of iterations to use
2002 -  maxtime - final time to iterate to
2003 
2004    Options Database Keys:
2005 .  -ts_max_steps <maxsteps> - Sets maxsteps
2006 .  -ts_final_time <maxtime> - Sets maxtime
2007 
2008    Notes:
2009    The default maximum number of iterations is 5000. Default time is 5.0
2010 
2011    Level: intermediate
2012 
2013 .keywords: TS, timestep, set, maximum, iterations
2014 
2015 .seealso: TSSetExactFinalTime()
2016 @*/
2017 PetscErrorCode  TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
2018 {
2019   PetscFunctionBegin;
2020   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2021   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
2022   PetscValidLogicalCollectiveReal(ts,maxtime,2);
2023   if (maxsteps >= 0) ts->max_steps = maxsteps;
2024   if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
2025   PetscFunctionReturn(0);
2026 }
2027 
2028 #undef __FUNCT__
2029 #define __FUNCT__ "TSSetSolution"
2030 /*@
2031    TSSetSolution - Sets the initial solution vector
2032    for use by the TS routines.
2033 
2034    Logically Collective on TS and Vec
2035 
2036    Input Parameters:
2037 +  ts - the TS context obtained from TSCreate()
2038 -  u - the solution vector
2039 
2040    Level: beginner
2041 
2042 .keywords: TS, timestep, set, solution, initial conditions
2043 @*/
2044 PetscErrorCode  TSSetSolution(TS ts,Vec u)
2045 {
2046   PetscErrorCode ierr;
2047   DM             dm;
2048 
2049   PetscFunctionBegin;
2050   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2051   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
2052   ierr = PetscObjectReference((PetscObject)u);CHKERRQ(ierr);
2053   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
2054 
2055   ts->vec_sol = u;
2056 
2057   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2058   ierr = DMShellSetGlobalVector(dm,u);CHKERRQ(ierr);
2059   PetscFunctionReturn(0);
2060 }
2061 
2062 #undef __FUNCT__
2063 #define __FUNCT__ "TSSetPreStep"
2064 /*@C
2065   TSSetPreStep - Sets the general-purpose function
2066   called once at the beginning of each time step.
2067 
2068   Logically Collective on TS
2069 
2070   Input Parameters:
2071 + ts   - The TS context obtained from TSCreate()
2072 - func - The function
2073 
2074   Calling sequence of func:
2075 . func (TS ts);
2076 
2077   Level: intermediate
2078 
2079   Note:
2080   If a step is rejected, TSStep() will call this routine again before each attempt.
2081   The last completed time step number can be queried using TSGetTimeStepNumber(), the
2082   size of the step being attempted can be obtained using TSGetTimeStep().
2083 
2084 .keywords: TS, timestep
2085 .seealso: TSSetPreStage(), TSSetPostStep(), TSStep()
2086 @*/
2087 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
2088 {
2089   PetscFunctionBegin;
2090   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2091   ts->prestep = func;
2092   PetscFunctionReturn(0);
2093 }
2094 
2095 #undef __FUNCT__
2096 #define __FUNCT__ "TSPreStep"
2097 /*@
2098   TSPreStep - Runs the user-defined pre-step function.
2099 
2100   Collective on TS
2101 
2102   Input Parameters:
2103 . ts   - The TS context obtained from TSCreate()
2104 
2105   Notes:
2106   TSPreStep() is typically used within time stepping implementations,
2107   so most users would not generally call this routine themselves.
2108 
2109   Level: developer
2110 
2111 .keywords: TS, timestep
2112 .seealso: TSSetPreStep(), TSPreStage(), TSPostStep()
2113 @*/
2114 PetscErrorCode  TSPreStep(TS ts)
2115 {
2116   PetscErrorCode ierr;
2117 
2118   PetscFunctionBegin;
2119   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2120   if (ts->prestep) {
2121     PetscStackCallStandard((*ts->prestep),(ts));
2122   }
2123   PetscFunctionReturn(0);
2124 }
2125 
2126 #undef __FUNCT__
2127 #define __FUNCT__ "TSSetPreStage"
2128 /*@C
2129   TSSetPreStage - Sets the general-purpose function
2130   called once at the beginning of each stage.
2131 
2132   Logically Collective on TS
2133 
2134   Input Parameters:
2135 + ts   - The TS context obtained from TSCreate()
2136 - func - The function
2137 
2138   Calling sequence of func:
2139 . PetscErrorCode func(TS ts, PetscReal stagetime);
2140 
2141   Level: intermediate
2142 
2143   Note:
2144   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
2145   The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
2146   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
2147 
2148 .keywords: TS, timestep
2149 .seealso: TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
2150 @*/
2151 PetscErrorCode  TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
2152 {
2153   PetscFunctionBegin;
2154   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2155   ts->prestage = func;
2156   PetscFunctionReturn(0);
2157 }
2158 
2159 #undef __FUNCT__
2160 #define __FUNCT__ "TSPreStage"
2161 /*@
2162   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
2163 
2164   Collective on TS
2165 
2166   Input Parameters:
2167 . ts   - The TS context obtained from TSCreate()
2168 
2169   Notes:
2170   TSPreStage() is typically used within time stepping implementations,
2171   most users would not generally call this routine themselves.
2172 
2173   Level: developer
2174 
2175 .keywords: TS, timestep
2176 .seealso: TSSetPreStep(), TSPreStep(), TSPostStep()
2177 @*/
2178 PetscErrorCode  TSPreStage(TS ts, PetscReal stagetime)
2179 {
2180   PetscErrorCode ierr;
2181 
2182   PetscFunctionBegin;
2183   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2184   if (ts->prestage) {
2185     PetscStackCallStandard((*ts->prestage),(ts,stagetime));
2186   }
2187   PetscFunctionReturn(0);
2188 }
2189 
2190 #undef __FUNCT__
2191 #define __FUNCT__ "TSSetPostStep"
2192 /*@C
2193   TSSetPostStep - Sets the general-purpose function
2194   called once at the end of each time step.
2195 
2196   Logically Collective on TS
2197 
2198   Input Parameters:
2199 + ts   - The TS context obtained from TSCreate()
2200 - func - The function
2201 
2202   Calling sequence of func:
2203 $ func (TS ts);
2204 
2205   Level: intermediate
2206 
2207 .keywords: TS, timestep
2208 .seealso: TSSetPreStep(), TSSetPreStage(), TSGetTimeStep(), TSGetTimeStepNumber(), TSGetTime()
2209 @*/
2210 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
2211 {
2212   PetscFunctionBegin;
2213   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2214   ts->poststep = func;
2215   PetscFunctionReturn(0);
2216 }
2217 
2218 #undef __FUNCT__
2219 #define __FUNCT__ "TSPostStep"
2220 /*@
2221   TSPostStep - Runs the user-defined post-step function.
2222 
2223   Collective on TS
2224 
2225   Input Parameters:
2226 . ts   - The TS context obtained from TSCreate()
2227 
2228   Notes:
2229   TSPostStep() is typically used within time stepping implementations,
2230   so most users would not generally call this routine themselves.
2231 
2232   Level: developer
2233 
2234 .keywords: TS, timestep
2235 @*/
2236 PetscErrorCode  TSPostStep(TS ts)
2237 {
2238   PetscErrorCode ierr;
2239 
2240   PetscFunctionBegin;
2241   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2242   if (ts->poststep) {
2243     PetscStackCallStandard((*ts->poststep),(ts));
2244   }
2245   PetscFunctionReturn(0);
2246 }
2247 
2248 /* ------------ Routines to set performance monitoring options ----------- */
2249 
2250 #undef __FUNCT__
2251 #define __FUNCT__ "TSMonitorSet"
2252 /*@C
2253    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
2254    timestep to display the iteration's  progress.
2255 
2256    Logically Collective on TS
2257 
2258    Input Parameters:
2259 +  ts - the TS context obtained from TSCreate()
2260 .  monitor - monitoring routine
2261 .  mctx - [optional] user-defined context for private data for the
2262              monitor routine (use NULL if no context is desired)
2263 -  monitordestroy - [optional] routine that frees monitor context
2264           (may be NULL)
2265 
2266    Calling sequence of monitor:
2267 $    int monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
2268 
2269 +    ts - the TS context
2270 .    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
2271                                been interpolated to)
2272 .    time - current time
2273 .    u - current iterate
2274 -    mctx - [optional] monitoring context
2275 
2276    Notes:
2277    This routine adds an additional monitor to the list of monitors that
2278    already has been loaded.
2279 
2280    Fortran notes: Only a single monitor function can be set for each TS object
2281 
2282    Level: intermediate
2283 
2284 .keywords: TS, timestep, set, monitor
2285 
2286 .seealso: TSMonitorDefault(), TSMonitorCancel()
2287 @*/
2288 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
2289 {
2290   PetscFunctionBegin;
2291   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2292   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
2293   ts->monitor[ts->numbermonitors]          = monitor;
2294   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
2295   ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
2296   PetscFunctionReturn(0);
2297 }
2298 
2299 #undef __FUNCT__
2300 #define __FUNCT__ "TSMonitorCancel"
2301 /*@C
2302    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
2303 
2304    Logically Collective on TS
2305 
2306    Input Parameters:
2307 .  ts - the TS context obtained from TSCreate()
2308 
2309    Notes:
2310    There is no way to remove a single, specific monitor.
2311 
2312    Level: intermediate
2313 
2314 .keywords: TS, timestep, set, monitor
2315 
2316 .seealso: TSMonitorDefault(), TSMonitorSet()
2317 @*/
2318 PetscErrorCode  TSMonitorCancel(TS ts)
2319 {
2320   PetscErrorCode ierr;
2321   PetscInt       i;
2322 
2323   PetscFunctionBegin;
2324   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2325   for (i=0; i<ts->numbermonitors; i++) {
2326     if (ts->monitordestroy[i]) {
2327       ierr = (*ts->monitordestroy[i])(&ts->monitorcontext[i]);CHKERRQ(ierr);
2328     }
2329   }
2330   ts->numbermonitors = 0;
2331   PetscFunctionReturn(0);
2332 }
2333 
2334 #undef __FUNCT__
2335 #define __FUNCT__ "TSMonitorDefault"
2336 /*@
2337    TSMonitorDefault - Sets the Default monitor
2338 
2339    Level: intermediate
2340 
2341 .keywords: TS, set, monitor
2342 
2343 .seealso: TSMonitorDefault(), TSMonitorSet()
2344 @*/
2345 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *dummy)
2346 {
2347   PetscErrorCode ierr;
2348   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)ts));
2349 
2350   PetscFunctionBegin;
2351   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2352   ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g\n",step,(double)ts->time_step,(double)ptime);CHKERRQ(ierr);
2353   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2354   PetscFunctionReturn(0);
2355 }
2356 
2357 #undef __FUNCT__
2358 #define __FUNCT__ "TSSetRetainStages"
2359 /*@
2360    TSSetRetainStages - Request that all stages in the upcoming step be stored so that interpolation will be available.
2361 
2362    Logically Collective on TS
2363 
2364    Input Argument:
2365 .  ts - time stepping context
2366 
2367    Output Argument:
2368 .  flg - PETSC_TRUE or PETSC_FALSE
2369 
2370    Level: intermediate
2371 
2372 .keywords: TS, set
2373 
2374 .seealso: TSInterpolate(), TSSetPostStep()
2375 @*/
2376 PetscErrorCode TSSetRetainStages(TS ts,PetscBool flg)
2377 {
2378   PetscFunctionBegin;
2379   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2380   ts->retain_stages = flg;
2381   PetscFunctionReturn(0);
2382 }
2383 
2384 #undef __FUNCT__
2385 #define __FUNCT__ "TSInterpolate"
2386 /*@
2387    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
2388 
2389    Collective on TS
2390 
2391    Input Argument:
2392 +  ts - time stepping context
2393 -  t - time to interpolate to
2394 
2395    Output Argument:
2396 .  U - state at given time
2397 
2398    Notes:
2399    The user should call TSSetRetainStages() before taking a step in which interpolation will be requested.
2400 
2401    Level: intermediate
2402 
2403    Developer Notes:
2404    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
2405 
2406 .keywords: TS, set
2407 
2408 .seealso: TSSetRetainStages(), TSSetPostStep()
2409 @*/
2410 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
2411 {
2412   PetscErrorCode ierr;
2413 
2414   PetscFunctionBegin;
2415   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2416   if (t < ts->ptime - ts->time_step_prev || t > ts->ptime) SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Requested time %G not in last time steps [%G,%G]",t,ts->ptime-ts->time_step_prev,ts->ptime);
2417   if (!ts->ops->interpolate) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
2418   ierr = (*ts->ops->interpolate)(ts,t,U);CHKERRQ(ierr);
2419   PetscFunctionReturn(0);
2420 }
2421 
2422 #undef __FUNCT__
2423 #define __FUNCT__ "TSStep"
2424 /*@
2425    TSStep - Steps one time step
2426 
2427    Collective on TS
2428 
2429    Input Parameter:
2430 .  ts - the TS context obtained from TSCreate()
2431 
2432    Level: intermediate
2433 
2434    Notes:
2435    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
2436    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
2437 
2438    This may over-step the final time provided in TSSetDuration() depending on the time-step used. TSSolve() interpolates to exactly the
2439    time provided in TSSetDuration(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
2440 
2441 .keywords: TS, timestep, solve
2442 
2443 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
2444 @*/
2445 PetscErrorCode  TSStep(TS ts)
2446 {
2447   PetscReal      ptime_prev;
2448   PetscErrorCode ierr;
2449 
2450   PetscFunctionBegin;
2451   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2452   ierr = TSSetUp(ts);CHKERRQ(ierr);
2453 
2454   ts->reason = TS_CONVERGED_ITERATING;
2455   ptime_prev = ts->ptime;
2456 
2457   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
2458   ierr = (*ts->ops->step)(ts);CHKERRQ(ierr);
2459   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
2460 
2461   ts->time_step_prev = ts->ptime - ptime_prev;
2462 
2463   if (ts->reason < 0) {
2464     if (ts->errorifstepfailed) {
2465       if (ts->reason == TS_DIVERGED_NONLINEAR_SOLVE) {
2466         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]);
2467       } else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
2468     }
2469   } else if (!ts->reason) {
2470     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
2471     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
2472   }
2473   PetscFunctionReturn(0);
2474 }
2475 
2476 #undef __FUNCT__
2477 #define __FUNCT__ "TSEvaluateStep"
2478 /*@
2479    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
2480 
2481    Collective on TS
2482 
2483    Input Arguments:
2484 +  ts - time stepping context
2485 .  order - desired order of accuracy
2486 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
2487 
2488    Output Arguments:
2489 .  U - state at the end of the current step
2490 
2491    Level: advanced
2492 
2493    Notes:
2494    This function cannot be called until all stages have been evaluated.
2495    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.
2496 
2497 .seealso: TSStep(), TSAdapt
2498 @*/
2499 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
2500 {
2501   PetscErrorCode ierr;
2502 
2503   PetscFunctionBegin;
2504   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2505   PetscValidType(ts,1);
2506   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
2507   if (!ts->ops->evaluatestep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
2508   ierr = (*ts->ops->evaluatestep)(ts,order,U,done);CHKERRQ(ierr);
2509   PetscFunctionReturn(0);
2510 }
2511 
2512 #undef __FUNCT__
2513 #define __FUNCT__ "TSSolve"
2514 /*@
2515    TSSolve - Steps the requested number of timesteps.
2516 
2517    Collective on TS
2518 
2519    Input Parameter:
2520 +  ts - the TS context obtained from TSCreate()
2521 -  u - the solution vector  (can be null if TSSetSolution() was used, otherwise must contain the initial conditions)
2522 
2523    Level: beginner
2524 
2525    Notes:
2526    The final time returned by this function may be different from the time of the internally
2527    held state accessible by TSGetSolution() and TSGetTime() because the method may have
2528    stepped over the final time.
2529 
2530 .keywords: TS, timestep, solve
2531 
2532 .seealso: TSCreate(), TSSetSolution(), TSStep()
2533 @*/
2534 PetscErrorCode TSSolve(TS ts,Vec u)
2535 {
2536   PetscBool         flg;
2537   PetscViewer       viewer;
2538   PetscErrorCode    ierr;
2539   PetscViewerFormat format;
2540 
2541   PetscFunctionBegin;
2542   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2543   if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2);
2544   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 */
2545     if (!ts->vec_sol || u == ts->vec_sol) {
2546       Vec y;
2547       ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
2548       ierr = TSSetSolution(ts,y);CHKERRQ(ierr);
2549       ierr = VecDestroy(&y);CHKERRQ(ierr); /* grant ownership */
2550     }
2551     if (u) {
2552       ierr = VecCopy(u,ts->vec_sol);CHKERRQ(ierr);
2553     }
2554   } else if (u) {
2555     ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
2556   }
2557   ierr = TSSetUp(ts);CHKERRQ(ierr);
2558   /* reset time step and iteration counters */
2559   ts->steps             = 0;
2560   ts->ksp_its           = 0;
2561   ts->snes_its          = 0;
2562   ts->num_snes_failures = 0;
2563   ts->reject            = 0;
2564   ts->reason            = TS_CONVERGED_ITERATING;
2565 
2566   ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject)ts)->prefix,"-ts_view_pre",&viewer,&format,&flg);CHKERRQ(ierr);
2567   if (flg && !PetscPreLoadingOn) {
2568     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
2569     ierr = TSView(ts,viewer);CHKERRQ(ierr);
2570     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
2571     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2572   }
2573 
2574   if (ts->ops->solve) {         /* This private interface is transitional and should be removed when all implementations are updated. */
2575     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
2576     ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);
2577 
2578     ts->solvetime = ts->ptime;
2579   } else {
2580     /* steps the requested number of timesteps. */
2581     ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
2582     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
2583     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
2584     while (!ts->reason) {
2585       ierr = TSStep(ts);CHKERRQ(ierr);
2586       ierr = TSPostStep(ts);CHKERRQ(ierr);
2587       ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
2588     }
2589     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
2590       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
2591 
2592       ts->solvetime = ts->max_time;
2593     } else {
2594       if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
2595       ts->solvetime = ts->ptime;
2596     }
2597   }
2598   ierr = TSMonitor(ts,-1,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
2599   ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject)ts)->prefix,"-ts_view",&viewer,&format,&flg);CHKERRQ(ierr);
2600   if (flg && !PetscPreLoadingOn) {
2601     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
2602     ierr = TSView(ts,viewer);CHKERRQ(ierr);
2603     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
2604     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2605   }
2606   PetscFunctionReturn(0);
2607 }
2608 
2609 #undef __FUNCT__
2610 #define __FUNCT__ "TSMonitor"
2611 /*@
2612    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
2613 
2614    Collective on TS
2615 
2616    Input Parameters:
2617 +  ts - time stepping context obtained from TSCreate()
2618 .  step - step number that has just completed
2619 .  ptime - model time of the state
2620 -  u - state at the current model time
2621 
2622    Notes:
2623    TSMonitor() is typically used within the time stepping implementations.
2624    Users might call this function when using the TSStep() interface instead of TSSolve().
2625 
2626    Level: advanced
2627 
2628 .keywords: TS, timestep
2629 @*/
2630 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
2631 {
2632   PetscErrorCode ierr;
2633   PetscInt       i,n = ts->numbermonitors;
2634 
2635   PetscFunctionBegin;
2636   for (i=0; i<n; i++) {
2637     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
2638   }
2639   PetscFunctionReturn(0);
2640 }
2641 
2642 /* ------------------------------------------------------------------------*/
2643 struct _n_TSMonitorLGCtx {
2644   PetscDrawLG lg;
2645   PetscInt    howoften;  /* when > 0 uses step % howoften, when negative only final solution plotted */
2646   PetscInt    ksp_its,snes_its;
2647 };
2648 
2649 
2650 #undef __FUNCT__
2651 #define __FUNCT__ "TSMonitorLGCtxCreate"
2652 /*@C
2653    TSMonitorLGCtxCreate - Creates a line graph context for use with
2654    TS to monitor the solution process graphically in various ways
2655 
2656    Collective on TS
2657 
2658    Input Parameters:
2659 +  host - the X display to open, or null for the local machine
2660 .  label - the title to put in the title bar
2661 .  x, y - the screen coordinates of the upper left coordinate of the window
2662 .  m, n - the screen width and height in pixels
2663 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
2664 
2665    Output Parameter:
2666 .  ctx - the context
2667 
2668    Options Database Key:
2669 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
2670 .  -ts_monitor_lg_solution -
2671 .  -ts_monitor_lg_error -
2672 .  -ts_monitor_lg_ksp_iterations -
2673 .  -ts_monitor_lg_snes_iterations -
2674 -  -lg_indicate_data_points <true,false> - indicate the data points (at each time step) on the plot; default is true
2675 
2676    Notes:
2677    Use TSMonitorLGCtxDestroy() to destroy.
2678 
2679    Level: intermediate
2680 
2681 .keywords: TS, monitor, line graph, residual, seealso
2682 
2683 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
2684 
2685 @*/
2686 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
2687 {
2688   PetscDraw      win;
2689   PetscErrorCode ierr;
2690   PetscBool      flg = PETSC_TRUE;
2691 
2692   PetscFunctionBegin;
2693   ierr = PetscNew(struct _n_TSMonitorLGCtx,ctx);CHKERRQ(ierr);
2694   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&win);CHKERRQ(ierr);
2695   ierr = PetscDrawSetFromOptions(win);CHKERRQ(ierr);
2696   ierr = PetscDrawLGCreate(win,1,&(*ctx)->lg);CHKERRQ(ierr);
2697   ierr = PetscOptionsGetBool(NULL,"-lg_indicate_data_points",&flg,NULL);CHKERRQ(ierr);
2698   if (flg) {
2699     ierr = PetscDrawLGIndicateDataPoints((*ctx)->lg);CHKERRQ(ierr);
2700   }
2701   ierr = PetscLogObjectParent((*ctx)->lg,win);CHKERRQ(ierr);
2702   (*ctx)->howoften = howoften;
2703   PetscFunctionReturn(0);
2704 }
2705 
2706 #undef __FUNCT__
2707 #define __FUNCT__ "TSMonitorLGTimeStep"
2708 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
2709 {
2710   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
2711   PetscReal      x   = ptime,y;
2712   PetscErrorCode ierr;
2713 
2714   PetscFunctionBegin;
2715   if (!n) {
2716     PetscDrawAxis axis;
2717     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
2718     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time","Time step");CHKERRQ(ierr);
2719     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
2720   }
2721   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
2722   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
2723   if (((ctx->howoften > 0) && (!(n % ctx->howoften))) || ((ctx->howoften == -1) && (n == -1))) {
2724     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
2725   }
2726   PetscFunctionReturn(0);
2727 }
2728 
2729 #undef __FUNCT__
2730 #define __FUNCT__ "TSMonitorLGCtxDestroy"
2731 /*@C
2732    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
2733    with TSMonitorLGCtxCreate().
2734 
2735    Collective on TSMonitorLGCtx
2736 
2737    Input Parameter:
2738 .  ctx - the monitor context
2739 
2740    Level: intermediate
2741 
2742 .keywords: TS, monitor, line graph, destroy
2743 
2744 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
2745 @*/
2746 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
2747 {
2748   PetscDraw      draw;
2749   PetscErrorCode ierr;
2750 
2751   PetscFunctionBegin;
2752   ierr = PetscDrawLGGetDraw((*ctx)->lg,&draw);CHKERRQ(ierr);
2753   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
2754   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
2755   ierr = PetscFree(*ctx);CHKERRQ(ierr);
2756   PetscFunctionReturn(0);
2757 }
2758 
2759 #undef __FUNCT__
2760 #define __FUNCT__ "TSGetTime"
2761 /*@
2762    TSGetTime - Gets the time of the most recently completed step.
2763 
2764    Not Collective
2765 
2766    Input Parameter:
2767 .  ts - the TS context obtained from TSCreate()
2768 
2769    Output Parameter:
2770 .  t  - the current time
2771 
2772    Level: beginner
2773 
2774    Note:
2775    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
2776    TSSetPreStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
2777 
2778 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
2779 
2780 .keywords: TS, get, time
2781 @*/
2782 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
2783 {
2784   PetscFunctionBegin;
2785   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2786   PetscValidRealPointer(t,2);
2787   *t = ts->ptime;
2788   PetscFunctionReturn(0);
2789 }
2790 
2791 #undef __FUNCT__
2792 #define __FUNCT__ "TSSetTime"
2793 /*@
2794    TSSetTime - Allows one to reset the time.
2795 
2796    Logically Collective on TS
2797 
2798    Input Parameters:
2799 +  ts - the TS context obtained from TSCreate()
2800 -  time - the time
2801 
2802    Level: intermediate
2803 
2804 .seealso: TSGetTime(), TSSetDuration()
2805 
2806 .keywords: TS, set, time
2807 @*/
2808 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
2809 {
2810   PetscFunctionBegin;
2811   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2812   PetscValidLogicalCollectiveReal(ts,t,2);
2813   ts->ptime = t;
2814   PetscFunctionReturn(0);
2815 }
2816 
2817 #undef __FUNCT__
2818 #define __FUNCT__ "TSSetOptionsPrefix"
2819 /*@C
2820    TSSetOptionsPrefix - Sets the prefix used for searching for all
2821    TS options in the database.
2822 
2823    Logically Collective on TS
2824 
2825    Input Parameter:
2826 +  ts     - The TS context
2827 -  prefix - The prefix to prepend to all option names
2828 
2829    Notes:
2830    A hyphen (-) must NOT be given at the beginning of the prefix name.
2831    The first character of all runtime options is AUTOMATICALLY the
2832    hyphen.
2833 
2834    Level: advanced
2835 
2836 .keywords: TS, set, options, prefix, database
2837 
2838 .seealso: TSSetFromOptions()
2839 
2840 @*/
2841 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
2842 {
2843   PetscErrorCode ierr;
2844   SNES           snes;
2845 
2846   PetscFunctionBegin;
2847   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2848   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2849   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2850   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
2851   PetscFunctionReturn(0);
2852 }
2853 
2854 
2855 #undef __FUNCT__
2856 #define __FUNCT__ "TSAppendOptionsPrefix"
2857 /*@C
2858    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
2859    TS options in the database.
2860 
2861    Logically Collective on TS
2862 
2863    Input Parameter:
2864 +  ts     - The TS context
2865 -  prefix - The prefix to prepend to all option names
2866 
2867    Notes:
2868    A hyphen (-) must NOT be given at the beginning of the prefix name.
2869    The first character of all runtime options is AUTOMATICALLY the
2870    hyphen.
2871 
2872    Level: advanced
2873 
2874 .keywords: TS, append, options, prefix, database
2875 
2876 .seealso: TSGetOptionsPrefix()
2877 
2878 @*/
2879 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
2880 {
2881   PetscErrorCode ierr;
2882   SNES           snes;
2883 
2884   PetscFunctionBegin;
2885   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2886   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2887   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2888   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
2889   PetscFunctionReturn(0);
2890 }
2891 
2892 #undef __FUNCT__
2893 #define __FUNCT__ "TSGetOptionsPrefix"
2894 /*@C
2895    TSGetOptionsPrefix - Sets the prefix used for searching for all
2896    TS options in the database.
2897 
2898    Not Collective
2899 
2900    Input Parameter:
2901 .  ts - The TS context
2902 
2903    Output Parameter:
2904 .  prefix - A pointer to the prefix string used
2905 
2906    Notes: On the fortran side, the user should pass in a string 'prifix' of
2907    sufficient length to hold the prefix.
2908 
2909    Level: intermediate
2910 
2911 .keywords: TS, get, options, prefix, database
2912 
2913 .seealso: TSAppendOptionsPrefix()
2914 @*/
2915 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
2916 {
2917   PetscErrorCode ierr;
2918 
2919   PetscFunctionBegin;
2920   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2921   PetscValidPointer(prefix,2);
2922   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2923   PetscFunctionReturn(0);
2924 }
2925 
2926 #undef __FUNCT__
2927 #define __FUNCT__ "TSGetRHSJacobian"
2928 /*@C
2929    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
2930 
2931    Not Collective, but parallel objects are returned if TS is parallel
2932 
2933    Input Parameter:
2934 .  ts  - The TS context obtained from TSCreate()
2935 
2936    Output Parameters:
2937 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
2938 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
2939 .  func - Function to compute the Jacobian of the RHS  (or NULL)
2940 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
2941 
2942    Notes: You can pass in NULL for any return argument you do not need.
2943 
2944    Level: intermediate
2945 
2946 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
2947 
2948 .keywords: TS, timestep, get, matrix, Jacobian
2949 @*/
2950 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
2951 {
2952   PetscErrorCode ierr;
2953   SNES           snes;
2954   DM             dm;
2955 
2956   PetscFunctionBegin;
2957   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2958   ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
2959   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2960   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
2961   PetscFunctionReturn(0);
2962 }
2963 
2964 #undef __FUNCT__
2965 #define __FUNCT__ "TSGetIJacobian"
2966 /*@C
2967    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
2968 
2969    Not Collective, but parallel objects are returned if TS is parallel
2970 
2971    Input Parameter:
2972 .  ts  - The TS context obtained from TSCreate()
2973 
2974    Output Parameters:
2975 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
2976 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
2977 .  f   - The function to compute the matrices
2978 - ctx - User-defined context for Jacobian evaluation routine
2979 
2980    Notes: You can pass in NULL for any return argument you do not need.
2981 
2982    Level: advanced
2983 
2984 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
2985 
2986 .keywords: TS, timestep, get, matrix, Jacobian
2987 @*/
2988 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
2989 {
2990   PetscErrorCode ierr;
2991   SNES           snes;
2992   DM             dm;
2993 
2994   PetscFunctionBegin;
2995   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2996   ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
2997   ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
2998   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2999   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
3000   PetscFunctionReturn(0);
3001 }
3002 
3003 
3004 #undef __FUNCT__
3005 #define __FUNCT__ "TSMonitorDrawSolution"
3006 /*@C
3007    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
3008    VecView() for the solution at each timestep
3009 
3010    Collective on TS
3011 
3012    Input Parameters:
3013 +  ts - the TS context
3014 .  step - current time-step
3015 .  ptime - current time
3016 -  dummy - either a viewer or NULL
3017 
3018    Options Database:
3019 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3020 
3021    Notes: the initial solution and current solution are not displayed with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
3022        will look bad
3023 
3024    Level: intermediate
3025 
3026 .keywords: TS,  vector, monitor, view
3027 
3028 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3029 @*/
3030 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3031 {
3032   PetscErrorCode   ierr;
3033   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
3034   PetscDraw        draw;
3035 
3036   PetscFunctionBegin;
3037   if (!step && ictx->showinitial) {
3038     if (!ictx->initialsolution) {
3039       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
3040     }
3041     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
3042   }
3043   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften)) && (step > -1)) || ((ictx->howoften == -1) && (step == -1)))) PetscFunctionReturn(0);
3044 
3045   if (ictx->showinitial) {
3046     PetscReal pause;
3047     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
3048     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
3049     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
3050     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
3051     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
3052   }
3053   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
3054   if (ictx->showtimestepandtime) {
3055     PetscReal xl,yl,xr,yr,tw,w,h;
3056     char      time[32];
3057     size_t    len;
3058 
3059     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
3060     ierr = PetscSNPrintf(time,32,"Timestep %d Time %f",(int)step,(double)ptime);CHKERRQ(ierr);
3061     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
3062     ierr =  PetscStrlen(time,&len);CHKERRQ(ierr);
3063     ierr = PetscDrawStringGetSize(draw,&tw,NULL);CHKERRQ(ierr);
3064     w    = xl + .5*(xr - xl) - .5*len*tw;
3065     h    = yl + .95*(yr - yl);
3066     ierr = PetscDrawString(draw,w,h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
3067     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
3068   }
3069 
3070   if (ictx->showinitial) {
3071     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
3072   }
3073   PetscFunctionReturn(0);
3074 }
3075 
3076 #undef __FUNCT__
3077 #define __FUNCT__ "TSMonitorDrawSolutionPhase"
3078 /*@C
3079    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
3080 
3081    Collective on TS
3082 
3083    Input Parameters:
3084 +  ts - the TS context
3085 .  step - current time-step
3086 .  ptime - current time
3087 -  dummy - either a viewer or NULL
3088 
3089    Level: intermediate
3090 
3091 .keywords: TS,  vector, monitor, view
3092 
3093 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3094 @*/
3095 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3096 {
3097   PetscErrorCode    ierr;
3098   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
3099   PetscDraw         draw;
3100   MPI_Comm          comm;
3101   PetscInt          n;
3102   PetscMPIInt       size;
3103   PetscReal         xl,yl,xr,yr,tw,w,h;
3104   char              time[32];
3105   size_t            len;
3106   const PetscScalar *U;
3107 
3108   PetscFunctionBegin;
3109   ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
3110   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
3111   if (size != 1) SETERRQ(comm,PETSC_ERR_SUP,"Only allowed for sequential runs");
3112   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
3113   if (n != 2) SETERRQ(comm,PETSC_ERR_SUP,"Only for ODEs with two unknowns");
3114 
3115   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
3116 
3117   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
3118   ierr = PetscDrawAxisGetLimits(ictx->axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
3119   if ((PetscRealPart(U[0]) < xl) || (PetscRealPart(U[1]) < yl) || (PetscRealPart(U[0]) > xr) || (PetscRealPart(U[1]) > yr)) {
3120       ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
3121       PetscFunctionReturn(0);
3122   }
3123   if (!step) ictx->color++;
3124   ierr = PetscDrawPoint(draw,PetscRealPart(U[0]),PetscRealPart(U[1]),ictx->color);CHKERRQ(ierr);
3125   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
3126 
3127   if (ictx->showtimestepandtime) {
3128     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
3129     ierr = PetscSNPrintf(time,32,"Timestep %d Time %f",(int)step,(double)ptime);CHKERRQ(ierr);
3130     ierr = PetscStrlen(time,&len);CHKERRQ(ierr);
3131     ierr = PetscDrawStringGetSize(draw,&tw,NULL);CHKERRQ(ierr);
3132     w    = xl + .5*(xr - xl) - .5*len*tw;
3133     h    = yl + .95*(yr - yl);
3134     ierr = PetscDrawString(draw,w,h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
3135   }
3136   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
3137   PetscFunctionReturn(0);
3138 }
3139 
3140 
3141 #undef __FUNCT__
3142 #define __FUNCT__ "TSMonitorDrawCtxDestroy"
3143 /*@C
3144    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
3145 
3146    Collective on TS
3147 
3148    Input Parameters:
3149 .    ctx - the monitor context
3150 
3151    Level: intermediate
3152 
3153 .keywords: TS,  vector, monitor, view
3154 
3155 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
3156 @*/
3157 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
3158 {
3159   PetscErrorCode ierr;
3160 
3161   PetscFunctionBegin;
3162   ierr = PetscDrawAxisDestroy(&(*ictx)->axis);CHKERRQ(ierr);
3163   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
3164   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
3165   ierr = PetscFree(*ictx);CHKERRQ(ierr);
3166   PetscFunctionReturn(0);
3167 }
3168 
3169 #undef __FUNCT__
3170 #define __FUNCT__ "TSMonitorDrawCtxCreate"
3171 /*@C
3172    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
3173 
3174    Collective on TS
3175 
3176    Input Parameter:
3177 .    ts - time-step context
3178 
3179    Output Patameter:
3180 .    ctx - the monitor context
3181 
3182    Options Database:
3183 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3184 
3185    Level: intermediate
3186 
3187 .keywords: TS,  vector, monitor, view
3188 
3189 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
3190 @*/
3191 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
3192 {
3193   PetscErrorCode   ierr;
3194 
3195   PetscFunctionBegin;
3196   ierr = PetscNew(struct _n_TSMonitorDrawCtx,ctx);CHKERRQ(ierr);
3197   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
3198   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
3199 
3200   (*ctx)->howoften    = howoften;
3201   (*ctx)->showinitial = PETSC_FALSE;
3202   ierr = PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
3203 
3204   (*ctx)->showtimestepandtime = PETSC_FALSE;
3205   ierr = PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
3206   (*ctx)->color = PETSC_DRAW_WHITE;
3207   PetscFunctionReturn(0);
3208 }
3209 
3210 #undef __FUNCT__
3211 #define __FUNCT__ "TSMonitorDrawError"
3212 /*@C
3213    TSMonitorDrawError - Monitors progress of the TS solvers by calling
3214    VecView() for the error at each timestep
3215 
3216    Collective on TS
3217 
3218    Input Parameters:
3219 +  ts - the TS context
3220 .  step - current time-step
3221 .  ptime - current time
3222 -  dummy - either a viewer or NULL
3223 
3224    Level: intermediate
3225 
3226 .keywords: TS,  vector, monitor, view
3227 
3228 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3229 @*/
3230 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3231 {
3232   PetscErrorCode   ierr;
3233   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
3234   PetscViewer      viewer = ctx->viewer;
3235   Vec              work;
3236 
3237   PetscFunctionBegin;
3238   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften)) && (step > -1)) || ((ctx->howoften == -1) && (step == -1)))) PetscFunctionReturn(0);
3239   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
3240   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
3241   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
3242   ierr = VecView(work,viewer);CHKERRQ(ierr);
3243   ierr = VecDestroy(&work);CHKERRQ(ierr);
3244   PetscFunctionReturn(0);
3245 }
3246 
3247 #include <petsc-private/dmimpl.h>
3248 #undef __FUNCT__
3249 #define __FUNCT__ "TSSetDM"
3250 /*@
3251    TSSetDM - Sets the DM that may be used by some preconditioners
3252 
3253    Logically Collective on TS and DM
3254 
3255    Input Parameters:
3256 +  ts - the preconditioner context
3257 -  dm - the dm
3258 
3259    Level: intermediate
3260 
3261 
3262 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
3263 @*/
3264 PetscErrorCode  TSSetDM(TS ts,DM dm)
3265 {
3266   PetscErrorCode ierr;
3267   SNES           snes;
3268   DMTS           tsdm;
3269 
3270   PetscFunctionBegin;
3271   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3272   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
3273   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
3274     if (ts->dm->dmts && !dm->dmts) {
3275       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
3276       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
3277       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
3278         tsdm->originaldm = dm;
3279       }
3280     }
3281     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
3282   }
3283   ts->dm = dm;
3284 
3285   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3286   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
3287   PetscFunctionReturn(0);
3288 }
3289 
3290 #undef __FUNCT__
3291 #define __FUNCT__ "TSGetDM"
3292 /*@
3293    TSGetDM - Gets the DM that may be used by some preconditioners
3294 
3295    Not Collective
3296 
3297    Input Parameter:
3298 . ts - the preconditioner context
3299 
3300    Output Parameter:
3301 .  dm - the dm
3302 
3303    Level: intermediate
3304 
3305 
3306 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
3307 @*/
3308 PetscErrorCode  TSGetDM(TS ts,DM *dm)
3309 {
3310   PetscErrorCode ierr;
3311 
3312   PetscFunctionBegin;
3313   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3314   if (!ts->dm) {
3315     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
3316     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
3317   }
3318   *dm = ts->dm;
3319   PetscFunctionReturn(0);
3320 }
3321 
3322 #undef __FUNCT__
3323 #define __FUNCT__ "SNESTSFormFunction"
3324 /*@
3325    SNESTSFormFunction - Function to evaluate nonlinear residual
3326 
3327    Logically Collective on SNES
3328 
3329    Input Parameter:
3330 + snes - nonlinear solver
3331 . U - the current state at which to evaluate the residual
3332 - ctx - user context, must be a TS
3333 
3334    Output Parameter:
3335 . F - the nonlinear residual
3336 
3337    Notes:
3338    This function is not normally called by users and is automatically registered with the SNES used by TS.
3339    It is most frequently passed to MatFDColoringSetFunction().
3340 
3341    Level: advanced
3342 
3343 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
3344 @*/
3345 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
3346 {
3347   TS             ts = (TS)ctx;
3348   PetscErrorCode ierr;
3349 
3350   PetscFunctionBegin;
3351   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3352   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
3353   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
3354   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
3355   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
3356   PetscFunctionReturn(0);
3357 }
3358 
3359 #undef __FUNCT__
3360 #define __FUNCT__ "SNESTSFormJacobian"
3361 /*@
3362    SNESTSFormJacobian - Function to evaluate the Jacobian
3363 
3364    Collective on SNES
3365 
3366    Input Parameter:
3367 + snes - nonlinear solver
3368 . U - the current state at which to evaluate the residual
3369 - ctx - user context, must be a TS
3370 
3371    Output Parameter:
3372 + A - the Jacobian
3373 . B - the preconditioning matrix (may be the same as A)
3374 - flag - indicates any structure change in the matrix
3375 
3376    Notes:
3377    This function is not normally called by users and is automatically registered with the SNES used by TS.
3378 
3379    Level: developer
3380 
3381 .seealso: SNESSetJacobian()
3382 @*/
3383 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat *A,Mat *B,MatStructure *flag,void *ctx)
3384 {
3385   TS             ts = (TS)ctx;
3386   PetscErrorCode ierr;
3387 
3388   PetscFunctionBegin;
3389   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3390   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
3391   PetscValidPointer(A,3);
3392   PetscValidHeaderSpecific(*A,MAT_CLASSID,3);
3393   PetscValidPointer(B,4);
3394   PetscValidHeaderSpecific(*B,MAT_CLASSID,4);
3395   PetscValidPointer(flag,5);
3396   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
3397   ierr = (ts->ops->snesjacobian)(snes,U,A,B,flag,ts);CHKERRQ(ierr);
3398   PetscFunctionReturn(0);
3399 }
3400 
3401 #undef __FUNCT__
3402 #define __FUNCT__ "TSComputeRHSFunctionLinear"
3403 /*@C
3404    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems only
3405 
3406    Collective on TS
3407 
3408    Input Arguments:
3409 +  ts - time stepping context
3410 .  t - time at which to evaluate
3411 .  U - state at which to evaluate
3412 -  ctx - context
3413 
3414    Output Arguments:
3415 .  F - right hand side
3416 
3417    Level: intermediate
3418 
3419    Notes:
3420    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
3421    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
3422 
3423 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
3424 @*/
3425 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
3426 {
3427   PetscErrorCode ierr;
3428   Mat            Arhs,Brhs;
3429   MatStructure   flg2;
3430 
3431   PetscFunctionBegin;
3432   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
3433   ierr = TSComputeRHSJacobian(ts,t,U,&Arhs,&Brhs,&flg2);CHKERRQ(ierr);
3434   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
3435   PetscFunctionReturn(0);
3436 }
3437 
3438 #undef __FUNCT__
3439 #define __FUNCT__ "TSComputeRHSJacobianConstant"
3440 /*@C
3441    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
3442 
3443    Collective on TS
3444 
3445    Input Arguments:
3446 +  ts - time stepping context
3447 .  t - time at which to evaluate
3448 .  U - state at which to evaluate
3449 -  ctx - context
3450 
3451    Output Arguments:
3452 +  A - pointer to operator
3453 .  B - pointer to preconditioning matrix
3454 -  flg - matrix structure flag
3455 
3456    Level: intermediate
3457 
3458    Notes:
3459    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
3460 
3461 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
3462 @*/
3463 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat *A,Mat *B,MatStructure *flg,void *ctx)
3464 {
3465   PetscFunctionBegin;
3466   *flg = SAME_PRECONDITIONER;
3467   PetscFunctionReturn(0);
3468 }
3469 
3470 #undef __FUNCT__
3471 #define __FUNCT__ "TSComputeIFunctionLinear"
3472 /*@C
3473    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
3474 
3475    Collective on TS
3476 
3477    Input Arguments:
3478 +  ts - time stepping context
3479 .  t - time at which to evaluate
3480 .  U - state at which to evaluate
3481 .  Udot - time derivative of state vector
3482 -  ctx - context
3483 
3484    Output Arguments:
3485 .  F - left hand side
3486 
3487    Level: intermediate
3488 
3489    Notes:
3490    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
3491    user is required to write their own TSComputeIFunction.
3492    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
3493    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
3494 
3495 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant()
3496 @*/
3497 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
3498 {
3499   PetscErrorCode ierr;
3500   Mat            A,B;
3501   MatStructure   flg2;
3502 
3503   PetscFunctionBegin;
3504   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
3505   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,&A,&B,&flg2,PETSC_TRUE);CHKERRQ(ierr);
3506   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
3507   PetscFunctionReturn(0);
3508 }
3509 
3510 #undef __FUNCT__
3511 #define __FUNCT__ "TSComputeIJacobianConstant"
3512 /*@C
3513    TSComputeIJacobianConstant - Reuses a Jacobian that is time-independent.
3514 
3515    Collective on TS
3516 
3517    Input Arguments:
3518 +  ts - time stepping context
3519 .  t - time at which to evaluate
3520 .  U - state at which to evaluate
3521 .  Udot - time derivative of state vector
3522 .  shift - shift to apply
3523 -  ctx - context
3524 
3525    Output Arguments:
3526 +  A - pointer to operator
3527 .  B - pointer to preconditioning matrix
3528 -  flg - matrix structure flag
3529 
3530    Level: intermediate
3531 
3532    Notes:
3533    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
3534 
3535 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
3536 @*/
3537 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat *A,Mat *B,MatStructure *flg,void *ctx)
3538 {
3539   PetscFunctionBegin;
3540   *flg = SAME_PRECONDITIONER;
3541   PetscFunctionReturn(0);
3542 }
3543 #undef __FUNCT__
3544 #define __FUNCT__ "TSGetEquationType"
3545 /*@
3546    TSGetEquationType - Gets the type of the equation that TS is solving.
3547 
3548    Not Collective
3549 
3550    Input Parameter:
3551 .  ts - the TS context
3552 
3553    Output Parameter:
3554 .  equation_type - see TSEquationType
3555 
3556    Level: beginner
3557 
3558 .keywords: TS, equation type
3559 
3560 .seealso: TSSetEquationType(), TSEquationType
3561 @*/
3562 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
3563 {
3564   PetscFunctionBegin;
3565   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3566   PetscValidPointer(equation_type,2);
3567   *equation_type = ts->equation_type;
3568   PetscFunctionReturn(0);
3569 }
3570 
3571 #undef __FUNCT__
3572 #define __FUNCT__ "TSSetEquationType"
3573 /*@
3574    TSSetEquationType - Sets the type of the equation that TS is solving.
3575 
3576    Not Collective
3577 
3578    Input Parameter:
3579 +  ts - the TS context
3580 .  equation_type - see TSEquationType
3581 
3582    Level: advanced
3583 
3584 .keywords: TS, equation type
3585 
3586 .seealso: TSGetEquationType(), TSEquationType
3587 @*/
3588 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
3589 {
3590   PetscFunctionBegin;
3591   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3592   ts->equation_type = equation_type;
3593   PetscFunctionReturn(0);
3594 }
3595 
3596 #undef __FUNCT__
3597 #define __FUNCT__ "TSGetConvergedReason"
3598 /*@
3599    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
3600 
3601    Not Collective
3602 
3603    Input Parameter:
3604 .  ts - the TS context
3605 
3606    Output Parameter:
3607 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
3608             manual pages for the individual convergence tests for complete lists
3609 
3610    Level: beginner
3611 
3612    Notes:
3613    Can only be called after the call to TSSolve() is complete.
3614 
3615 .keywords: TS, nonlinear, set, convergence, test
3616 
3617 .seealso: TSSetConvergenceTest(), TSConvergedReason
3618 @*/
3619 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
3620 {
3621   PetscFunctionBegin;
3622   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3623   PetscValidPointer(reason,2);
3624   *reason = ts->reason;
3625   PetscFunctionReturn(0);
3626 }
3627 
3628 #undef __FUNCT__
3629 #define __FUNCT__ "TSSetConvergedReason"
3630 /*@
3631    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
3632 
3633    Not Collective
3634 
3635    Input Parameter:
3636 +  ts - the TS context
3637 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
3638             manual pages for the individual convergence tests for complete lists
3639 
3640    Level: advanced
3641 
3642    Notes:
3643    Can only be called during TSSolve() is active.
3644 
3645 .keywords: TS, nonlinear, set, convergence, test
3646 
3647 .seealso: TSConvergedReason
3648 @*/
3649 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
3650 {
3651   PetscFunctionBegin;
3652   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3653   ts->reason = reason;
3654   PetscFunctionReturn(0);
3655 }
3656 
3657 #undef __FUNCT__
3658 #define __FUNCT__ "TSGetSolveTime"
3659 /*@
3660    TSGetSolveTime - Gets the time after a call to TSSolve()
3661 
3662    Not Collective
3663 
3664    Input Parameter:
3665 .  ts - the TS context
3666 
3667    Output Parameter:
3668 .  ftime - the final time. This time should correspond to the final time set with TSSetDuration()
3669 
3670    Level: beginner
3671 
3672    Notes:
3673    Can only be called after the call to TSSolve() is complete.
3674 
3675 .keywords: TS, nonlinear, set, convergence, test
3676 
3677 .seealso: TSSetConvergenceTest(), TSConvergedReason
3678 @*/
3679 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
3680 {
3681   PetscFunctionBegin;
3682   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3683   PetscValidPointer(ftime,2);
3684   *ftime = ts->solvetime;
3685   PetscFunctionReturn(0);
3686 }
3687 
3688 #undef __FUNCT__
3689 #define __FUNCT__ "TSGetSNESIterations"
3690 /*@
3691    TSGetSNESIterations - Gets the total number of nonlinear iterations
3692    used by the time integrator.
3693 
3694    Not Collective
3695 
3696    Input Parameter:
3697 .  ts - TS context
3698 
3699    Output Parameter:
3700 .  nits - number of nonlinear iterations
3701 
3702    Notes:
3703    This counter is reset to zero for each successive call to TSSolve().
3704 
3705    Level: intermediate
3706 
3707 .keywords: TS, get, number, nonlinear, iterations
3708 
3709 .seealso:  TSGetKSPIterations()
3710 @*/
3711 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
3712 {
3713   PetscFunctionBegin;
3714   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3715   PetscValidIntPointer(nits,2);
3716   *nits = ts->snes_its;
3717   PetscFunctionReturn(0);
3718 }
3719 
3720 #undef __FUNCT__
3721 #define __FUNCT__ "TSGetKSPIterations"
3722 /*@
3723    TSGetKSPIterations - Gets the total number of linear iterations
3724    used by the time integrator.
3725 
3726    Not Collective
3727 
3728    Input Parameter:
3729 .  ts - TS context
3730 
3731    Output Parameter:
3732 .  lits - number of linear iterations
3733 
3734    Notes:
3735    This counter is reset to zero for each successive call to TSSolve().
3736 
3737    Level: intermediate
3738 
3739 .keywords: TS, get, number, linear, iterations
3740 
3741 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
3742 @*/
3743 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
3744 {
3745   PetscFunctionBegin;
3746   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3747   PetscValidIntPointer(lits,2);
3748   *lits = ts->ksp_its;
3749   PetscFunctionReturn(0);
3750 }
3751 
3752 #undef __FUNCT__
3753 #define __FUNCT__ "TSGetStepRejections"
3754 /*@
3755    TSGetStepRejections - Gets the total number of rejected steps.
3756 
3757    Not Collective
3758 
3759    Input Parameter:
3760 .  ts - TS context
3761 
3762    Output Parameter:
3763 .  rejects - number of steps rejected
3764 
3765    Notes:
3766    This counter is reset to zero for each successive call to TSSolve().
3767 
3768    Level: intermediate
3769 
3770 .keywords: TS, get, number
3771 
3772 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
3773 @*/
3774 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
3775 {
3776   PetscFunctionBegin;
3777   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3778   PetscValidIntPointer(rejects,2);
3779   *rejects = ts->reject;
3780   PetscFunctionReturn(0);
3781 }
3782 
3783 #undef __FUNCT__
3784 #define __FUNCT__ "TSGetSNESFailures"
3785 /*@
3786    TSGetSNESFailures - Gets the total number of failed SNES solves
3787 
3788    Not Collective
3789 
3790    Input Parameter:
3791 .  ts - TS context
3792 
3793    Output Parameter:
3794 .  fails - number of failed nonlinear solves
3795 
3796    Notes:
3797    This counter is reset to zero for each successive call to TSSolve().
3798 
3799    Level: intermediate
3800 
3801 .keywords: TS, get, number
3802 
3803 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
3804 @*/
3805 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
3806 {
3807   PetscFunctionBegin;
3808   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3809   PetscValidIntPointer(fails,2);
3810   *fails = ts->num_snes_failures;
3811   PetscFunctionReturn(0);
3812 }
3813 
3814 #undef __FUNCT__
3815 #define __FUNCT__ "TSSetMaxStepRejections"
3816 /*@
3817    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
3818 
3819    Not Collective
3820 
3821    Input Parameter:
3822 +  ts - TS context
3823 -  rejects - maximum number of rejected steps, pass -1 for unlimited
3824 
3825    Notes:
3826    The counter is reset to zero for each step
3827 
3828    Options Database Key:
3829  .  -ts_max_reject - Maximum number of step rejections before a step fails
3830 
3831    Level: intermediate
3832 
3833 .keywords: TS, set, maximum, number
3834 
3835 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
3836 @*/
3837 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
3838 {
3839   PetscFunctionBegin;
3840   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3841   ts->max_reject = rejects;
3842   PetscFunctionReturn(0);
3843 }
3844 
3845 #undef __FUNCT__
3846 #define __FUNCT__ "TSSetMaxSNESFailures"
3847 /*@
3848    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
3849 
3850    Not Collective
3851 
3852    Input Parameter:
3853 +  ts - TS context
3854 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
3855 
3856    Notes:
3857    The counter is reset to zero for each successive call to TSSolve().
3858 
3859    Options Database Key:
3860  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
3861 
3862    Level: intermediate
3863 
3864 .keywords: TS, set, maximum, number
3865 
3866 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
3867 @*/
3868 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
3869 {
3870   PetscFunctionBegin;
3871   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3872   ts->max_snes_failures = fails;
3873   PetscFunctionReturn(0);
3874 }
3875 
3876 #undef __FUNCT__
3877 #define __FUNCT__ "TSSetErrorIfStepFails()"
3878 /*@
3879    TSSetErrorIfStepFails - Error if no step succeeds
3880 
3881    Not Collective
3882 
3883    Input Parameter:
3884 +  ts - TS context
3885 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
3886 
3887    Options Database Key:
3888  .  -ts_error_if_step_fails - Error if no step succeeds
3889 
3890    Level: intermediate
3891 
3892 .keywords: TS, set, error
3893 
3894 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
3895 @*/
3896 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
3897 {
3898   PetscFunctionBegin;
3899   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3900   ts->errorifstepfailed = err;
3901   PetscFunctionReturn(0);
3902 }
3903 
3904 #undef __FUNCT__
3905 #define __FUNCT__ "TSMonitorSolutionBinary"
3906 /*@C
3907    TSMonitorSolutionBinary - Monitors progress of the TS solvers by VecView() for the solution at each timestep. Normally the viewer is a binary file
3908 
3909    Collective on TS
3910 
3911    Input Parameters:
3912 +  ts - the TS context
3913 .  step - current time-step
3914 .  ptime - current time
3915 .  u - current state
3916 -  viewer - binary viewer
3917 
3918    Level: intermediate
3919 
3920 .keywords: TS,  vector, monitor, view
3921 
3922 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3923 @*/
3924 PetscErrorCode  TSMonitorSolutionBinary(TS ts,PetscInt step,PetscReal ptime,Vec u,void *viewer)
3925 {
3926   PetscErrorCode ierr;
3927   PetscViewer    v = (PetscViewer)viewer;
3928 
3929   PetscFunctionBegin;
3930   ierr = VecView(u,v);CHKERRQ(ierr);
3931   PetscFunctionReturn(0);
3932 }
3933 
3934 #undef __FUNCT__
3935 #define __FUNCT__ "TSMonitorSolutionVTK"
3936 /*@C
3937    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
3938 
3939    Collective on TS
3940 
3941    Input Parameters:
3942 +  ts - the TS context
3943 .  step - current time-step
3944 .  ptime - current time
3945 .  u - current state
3946 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
3947 
3948    Level: intermediate
3949 
3950    Notes:
3951    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.
3952    These are named according to the file name template.
3953 
3954    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
3955 
3956 .keywords: TS,  vector, monitor, view
3957 
3958 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3959 @*/
3960 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
3961 {
3962   PetscErrorCode ierr;
3963   char           filename[PETSC_MAX_PATH_LEN];
3964   PetscViewer    viewer;
3965 
3966   PetscFunctionBegin;
3967   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
3968   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
3969   ierr = VecView(u,viewer);CHKERRQ(ierr);
3970   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3971   PetscFunctionReturn(0);
3972 }
3973 
3974 #undef __FUNCT__
3975 #define __FUNCT__ "TSMonitorSolutionVTKDestroy"
3976 /*@C
3977    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
3978 
3979    Collective on TS
3980 
3981    Input Parameters:
3982 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
3983 
3984    Level: intermediate
3985 
3986    Note:
3987    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
3988 
3989 .keywords: TS,  vector, monitor, view
3990 
3991 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
3992 @*/
3993 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
3994 {
3995   PetscErrorCode ierr;
3996 
3997   PetscFunctionBegin;
3998   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
3999   PetscFunctionReturn(0);
4000 }
4001 
4002 #undef __FUNCT__
4003 #define __FUNCT__ "TSGetTSAdapt"
4004 /*@
4005    TSGetTSAdapt - Get the adaptive controller context for the current method
4006 
4007    Collective on TS if controller has not been created yet
4008 
4009    Input Arguments:
4010 .  ts - time stepping context
4011 
4012    Output Arguments:
4013 .  adapt - adaptive controller
4014 
4015    Level: intermediate
4016 
4017 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
4018 @*/
4019 PetscErrorCode TSGetTSAdapt(TS ts,TSAdapt *adapt)
4020 {
4021   PetscErrorCode ierr;
4022 
4023   PetscFunctionBegin;
4024   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4025   PetscValidPointer(adapt,2);
4026   if (!ts->adapt) {
4027     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
4028     ierr = PetscLogObjectParent(ts,ts->adapt);CHKERRQ(ierr);
4029     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
4030   }
4031   *adapt = ts->adapt;
4032   PetscFunctionReturn(0);
4033 }
4034 
4035 #undef __FUNCT__
4036 #define __FUNCT__ "TSSetTolerances"
4037 /*@
4038    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
4039 
4040    Logically Collective
4041 
4042    Input Arguments:
4043 +  ts - time integration context
4044 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
4045 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
4046 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
4047 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
4048 
4049    Level: beginner
4050 
4051 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
4052 @*/
4053 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
4054 {
4055   PetscErrorCode ierr;
4056 
4057   PetscFunctionBegin;
4058   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
4059   if (vatol) {
4060     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
4061     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
4062 
4063     ts->vatol = vatol;
4064   }
4065   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
4066   if (vrtol) {
4067     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
4068     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
4069 
4070     ts->vrtol = vrtol;
4071   }
4072   PetscFunctionReturn(0);
4073 }
4074 
4075 #undef __FUNCT__
4076 #define __FUNCT__ "TSGetTolerances"
4077 /*@
4078    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
4079 
4080    Logically Collective
4081 
4082    Input Arguments:
4083 .  ts - time integration context
4084 
4085    Output Arguments:
4086 +  atol - scalar absolute tolerances, NULL to ignore
4087 .  vatol - vector of absolute tolerances, NULL to ignore
4088 .  rtol - scalar relative tolerances, NULL to ignore
4089 -  vrtol - vector of relative tolerances, NULL to ignore
4090 
4091    Level: beginner
4092 
4093 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
4094 @*/
4095 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
4096 {
4097   PetscFunctionBegin;
4098   if (atol)  *atol  = ts->atol;
4099   if (vatol) *vatol = ts->vatol;
4100   if (rtol)  *rtol  = ts->rtol;
4101   if (vrtol) *vrtol = ts->vrtol;
4102   PetscFunctionReturn(0);
4103 }
4104 
4105 #undef __FUNCT__
4106 #define __FUNCT__ "TSSetDifferentialEquationsIS"
4107 /*@
4108    TSSetDifferentialEquationsIS - Sets an IS containing locations of differential equations in a DAE
4109 
4110    Not Collective
4111 
4112    Input Arguments:
4113 +  ts - time stepping context
4114 -  is_diff - Index set for differential equations
4115 
4116    Level: advanced
4117 
4118 @*/
4119 PetscErrorCode TSSetDifferentialEquationsIS(TS ts, IS is_diff)
4120 {
4121   PetscErrorCode ierr;
4122 
4123   PetscFunctionBegin;
4124   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4125   PetscValidHeaderSpecific(is_diff,IS_CLASSID,2);
4126   PetscCheckSameComm(ts,1,is_diff,2);
4127   ierr = PetscObjectReference((PetscObject)is_diff);CHKERRQ(ierr);
4128   ierr = ISDestroy(&ts->is_diff);CHKERRQ(ierr);
4129   ts->is_diff = is_diff;
4130   PetscFunctionReturn(0);
4131 }
4132 
4133 #undef __FUNCT__
4134 #define __FUNCT__ "TSErrorWeightedNorm"
4135 /*@
4136    TSErrorWeightedNorm - compute a weighted norm of the difference between a vector and the current state
4137 
4138    Collective on TS
4139 
4140    Input Arguments:
4141 +  ts - time stepping context
4142 -  Y - state vector to be compared to ts->vec_sol
4143 
4144    Options Database Keys:
4145 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
4146 
4147    Output Arguments:
4148 .  norm - weighted norm, a value of 1.0 is considered small
4149 
4150    Level: developer
4151 
4152 .seealso: TSSetTolerances()
4153 @*/
4154 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec Y,PetscReal *norm)
4155 {
4156   PetscErrorCode    ierr;
4157   PetscInt          i,n,N,rstart;
4158   const PetscScalar *u,*y;
4159   Vec               U;
4160   PetscReal         sum,gsum;
4161   PetscReal         max,gmax;
4162 
4163   PetscFunctionBegin;
4164   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4165   PetscValidHeaderSpecific(Y,VEC_CLASSID,2);
4166   PetscValidPointer(norm,3);
4167   U = ts->vec_sol;
4168   PetscCheckSameTypeAndComm(U,1,Y,2);
4169   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"Y cannot be the TS solution vector");
4170 
4171   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
4172   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
4173   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
4174   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
4175   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
4176   sum  = 0.;
4177   max  = 0.;
4178   if (ts->vatol && ts->vrtol) {
4179     const PetscScalar *atol,*rtol;
4180     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4181     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4182     for (i=0; i<n; i++) {
4183       PetscReal tol = PetscRealPart(atol[i]) + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4184       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4185     }
4186     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4187     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4188   } else if (ts->vatol) {       /* vector atol, scalar rtol */
4189     const PetscScalar *atol;
4190     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4191     for (i=0; i<n; i++) {
4192       PetscReal tol = PetscRealPart(atol[i]) + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4193       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4194     }
4195     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4196   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
4197     const PetscScalar *rtol;
4198     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4199     for (i=0; i<n; i++) {
4200       PetscReal tol = ts->atol + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4201       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4202     }
4203     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4204   } else {                      /* scalar atol, scalar rtol */
4205     if (ts->is_diff) {
4206       const PetscInt *idx;
4207       PetscInt k;
4208       ierr = ISGetIndices(ts->is_diff,&idx);CHKERRQ(ierr);
4209       ierr = ISGetLocalSize(ts->is_diff,&n);CHKERRQ(ierr);
4210       if (ts->adapt->wnormtype == NORM_2) {
4211 	for (i=0; i<n; i++) {
4212 	  k = idx[i] - rstart;
4213 	  PetscReal tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[k]),PetscAbsScalar(y[k]));
4214 	  sum += PetscSqr(PetscAbsScalar(y[k] - u[k]) / tol);
4215 	}
4216       } else {
4217 	for (i=0; i<n; i++) {
4218 	  k = idx[i] - rstart;
4219 	  PetscReal tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[k]),PetscAbsScalar(y[k]));
4220 	  max = PetscMax(max,PetscAbsScalar(y[k] - u[k]) / tol);
4221 	}
4222       }
4223     } else {
4224       if (ts->adapt->wnormtype == NORM_2) {
4225 	for (i=0; i<n; i++) {
4226 	  PetscReal tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4227 	  sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4228 	}
4229       } else {
4230 	for (i=0; i<n; i++) {
4231 	  PetscReal tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4232 	  max = PetscMax(max,PetscAbsScalar(y[i] - u[i]) / tol);
4233 	}
4234       }
4235     }
4236   }
4237   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
4238   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
4239 
4240   if (ts->adapt->wnormtype == NORM_2) {
4241     ierr  = MPI_Allreduce(&sum,&gsum,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
4242     *norm = PetscSqrtReal(gsum / N);
4243   } else {
4244     ierr = MPI_Allreduce(&max,&gmax,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
4245     *norm = gmax;
4246   }
4247 
4248   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
4249   PetscFunctionReturn(0);
4250 }
4251 
4252 #undef __FUNCT__
4253 #define __FUNCT__ "TSSetCFLTimeLocal"
4254 /*@
4255    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
4256 
4257    Logically Collective on TS
4258 
4259    Input Arguments:
4260 +  ts - time stepping context
4261 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
4262 
4263    Note:
4264    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
4265 
4266    Level: intermediate
4267 
4268 .seealso: TSGetCFLTime(), TSADAPTCFL
4269 @*/
4270 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
4271 {
4272   PetscFunctionBegin;
4273   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4274   ts->cfltime_local = cfltime;
4275   ts->cfltime       = -1.;
4276   PetscFunctionReturn(0);
4277 }
4278 
4279 #undef __FUNCT__
4280 #define __FUNCT__ "TSGetCFLTime"
4281 /*@
4282    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
4283 
4284    Collective on TS
4285 
4286    Input Arguments:
4287 .  ts - time stepping context
4288 
4289    Output Arguments:
4290 .  cfltime - maximum stable time step for forward Euler
4291 
4292    Level: advanced
4293 
4294 .seealso: TSSetCFLTimeLocal()
4295 @*/
4296 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
4297 {
4298   PetscErrorCode ierr;
4299 
4300   PetscFunctionBegin;
4301   if (ts->cfltime < 0) {
4302     ierr = MPI_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
4303   }
4304   *cfltime = ts->cfltime;
4305   PetscFunctionReturn(0);
4306 }
4307 
4308 #undef __FUNCT__
4309 #define __FUNCT__ "TSVISetVariableBounds"
4310 /*@
4311    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
4312 
4313    Input Parameters:
4314 .  ts   - the TS context.
4315 .  xl   - lower bound.
4316 .  xu   - upper bound.
4317 
4318    Notes:
4319    If this routine is not called then the lower and upper bounds are set to
4320    SNES_VI_NINF and SNES_VI_INF respectively during SNESSetUp().
4321 
4322    Level: advanced
4323 
4324 @*/
4325 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
4326 {
4327   PetscErrorCode ierr;
4328   SNES           snes;
4329 
4330   PetscFunctionBegin;
4331   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4332   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
4333   PetscFunctionReturn(0);
4334 }
4335 
4336 #if defined(PETSC_HAVE_MATLAB_ENGINE)
4337 #include <mex.h>
4338 
4339 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
4340 
4341 #undef __FUNCT__
4342 #define __FUNCT__ "TSComputeFunction_Matlab"
4343 /*
4344    TSComputeFunction_Matlab - Calls the function that has been set with
4345                          TSSetFunctionMatlab().
4346 
4347    Collective on TS
4348 
4349    Input Parameters:
4350 +  snes - the TS context
4351 -  u - input vector
4352 
4353    Output Parameter:
4354 .  y - function vector, as set by TSSetFunction()
4355 
4356    Notes:
4357    TSComputeFunction() is typically used within nonlinear solvers
4358    implementations, so most users would not generally call this routine
4359    themselves.
4360 
4361    Level: developer
4362 
4363 .keywords: TS, nonlinear, compute, function
4364 
4365 .seealso: TSSetFunction(), TSGetFunction()
4366 */
4367 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
4368 {
4369   PetscErrorCode  ierr;
4370   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4371   int             nlhs  = 1,nrhs = 7;
4372   mxArray         *plhs[1],*prhs[7];
4373   long long int   lx = 0,lxdot = 0,ly = 0,ls = 0;
4374 
4375   PetscFunctionBegin;
4376   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
4377   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
4378   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
4379   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
4380   PetscCheckSameComm(snes,1,u,3);
4381   PetscCheckSameComm(snes,1,y,5);
4382 
4383   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
4384   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4385   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
4386   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
4387 
4388   prhs[0] =  mxCreateDoubleScalar((double)ls);
4389   prhs[1] =  mxCreateDoubleScalar(time);
4390   prhs[2] =  mxCreateDoubleScalar((double)lx);
4391   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
4392   prhs[4] =  mxCreateDoubleScalar((double)ly);
4393   prhs[5] =  mxCreateString(sctx->funcname);
4394   prhs[6] =  sctx->ctx;
4395   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
4396   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4397   mxDestroyArray(prhs[0]);
4398   mxDestroyArray(prhs[1]);
4399   mxDestroyArray(prhs[2]);
4400   mxDestroyArray(prhs[3]);
4401   mxDestroyArray(prhs[4]);
4402   mxDestroyArray(prhs[5]);
4403   mxDestroyArray(plhs[0]);
4404   PetscFunctionReturn(0);
4405 }
4406 
4407 
4408 #undef __FUNCT__
4409 #define __FUNCT__ "TSSetFunctionMatlab"
4410 /*
4411    TSSetFunctionMatlab - Sets the function evaluation routine and function
4412    vector for use by the TS routines in solving ODEs
4413    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
4414 
4415    Logically Collective on TS
4416 
4417    Input Parameters:
4418 +  ts - the TS context
4419 -  func - function evaluation routine
4420 
4421    Calling sequence of func:
4422 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
4423 
4424    Level: beginner
4425 
4426 .keywords: TS, nonlinear, set, function
4427 
4428 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4429 */
4430 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
4431 {
4432   PetscErrorCode  ierr;
4433   TSMatlabContext *sctx;
4434 
4435   PetscFunctionBegin;
4436   /* currently sctx is memory bleed */
4437   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
4438   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
4439   /*
4440      This should work, but it doesn't
4441   sctx->ctx = ctx;
4442   mexMakeArrayPersistent(sctx->ctx);
4443   */
4444   sctx->ctx = mxDuplicateArray(ctx);
4445 
4446   ierr = TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
4447   PetscFunctionReturn(0);
4448 }
4449 
4450 #undef __FUNCT__
4451 #define __FUNCT__ "TSComputeJacobian_Matlab"
4452 /*
4453    TSComputeJacobian_Matlab - Calls the function that has been set with
4454                          TSSetJacobianMatlab().
4455 
4456    Collective on TS
4457 
4458    Input Parameters:
4459 +  ts - the TS context
4460 .  u - input vector
4461 .  A, B - the matrices
4462 -  ctx - user context
4463 
4464    Output Parameter:
4465 .  flag - structure of the matrix
4466 
4467    Level: developer
4468 
4469 .keywords: TS, nonlinear, compute, function
4470 
4471 .seealso: TSSetFunction(), TSGetFunction()
4472 @*/
4473 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat *A,Mat *B,MatStructure *flag, void *ctx)
4474 {
4475   PetscErrorCode  ierr;
4476   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4477   int             nlhs  = 2,nrhs = 9;
4478   mxArray         *plhs[2],*prhs[9];
4479   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
4480 
4481   PetscFunctionBegin;
4482   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4483   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
4484 
4485   /* call Matlab function in ctx with arguments u and y */
4486 
4487   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
4488   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4489   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
4490   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
4491   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
4492 
4493   prhs[0] =  mxCreateDoubleScalar((double)ls);
4494   prhs[1] =  mxCreateDoubleScalar((double)time);
4495   prhs[2] =  mxCreateDoubleScalar((double)lx);
4496   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
4497   prhs[4] =  mxCreateDoubleScalar((double)shift);
4498   prhs[5] =  mxCreateDoubleScalar((double)lA);
4499   prhs[6] =  mxCreateDoubleScalar((double)lB);
4500   prhs[7] =  mxCreateString(sctx->funcname);
4501   prhs[8] =  sctx->ctx;
4502   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
4503   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4504   *flag   =  (MatStructure) mxGetScalar(plhs[1]);CHKERRQ(ierr);
4505   mxDestroyArray(prhs[0]);
4506   mxDestroyArray(prhs[1]);
4507   mxDestroyArray(prhs[2]);
4508   mxDestroyArray(prhs[3]);
4509   mxDestroyArray(prhs[4]);
4510   mxDestroyArray(prhs[5]);
4511   mxDestroyArray(prhs[6]);
4512   mxDestroyArray(prhs[7]);
4513   mxDestroyArray(plhs[0]);
4514   mxDestroyArray(plhs[1]);
4515   PetscFunctionReturn(0);
4516 }
4517 
4518 
4519 #undef __FUNCT__
4520 #define __FUNCT__ "TSSetJacobianMatlab"
4521 /*
4522    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
4523    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
4524 
4525    Logically Collective on TS
4526 
4527    Input Parameters:
4528 +  ts - the TS context
4529 .  A,B - Jacobian matrices
4530 .  func - function evaluation routine
4531 -  ctx - user context
4532 
4533    Calling sequence of func:
4534 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
4535 
4536 
4537    Level: developer
4538 
4539 .keywords: TS, nonlinear, set, function
4540 
4541 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4542 */
4543 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
4544 {
4545   PetscErrorCode  ierr;
4546   TSMatlabContext *sctx;
4547 
4548   PetscFunctionBegin;
4549   /* currently sctx is memory bleed */
4550   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
4551   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
4552   /*
4553      This should work, but it doesn't
4554   sctx->ctx = ctx;
4555   mexMakeArrayPersistent(sctx->ctx);
4556   */
4557   sctx->ctx = mxDuplicateArray(ctx);
4558 
4559   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
4560   PetscFunctionReturn(0);
4561 }
4562 
4563 #undef __FUNCT__
4564 #define __FUNCT__ "TSMonitor_Matlab"
4565 /*
4566    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
4567 
4568    Collective on TS
4569 
4570 .seealso: TSSetFunction(), TSGetFunction()
4571 @*/
4572 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
4573 {
4574   PetscErrorCode  ierr;
4575   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4576   int             nlhs  = 1,nrhs = 6;
4577   mxArray         *plhs[1],*prhs[6];
4578   long long int   lx = 0,ls = 0;
4579 
4580   PetscFunctionBegin;
4581   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4582   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4583 
4584   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
4585   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4586 
4587   prhs[0] =  mxCreateDoubleScalar((double)ls);
4588   prhs[1] =  mxCreateDoubleScalar((double)it);
4589   prhs[2] =  mxCreateDoubleScalar((double)time);
4590   prhs[3] =  mxCreateDoubleScalar((double)lx);
4591   prhs[4] =  mxCreateString(sctx->funcname);
4592   prhs[5] =  sctx->ctx;
4593   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
4594   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4595   mxDestroyArray(prhs[0]);
4596   mxDestroyArray(prhs[1]);
4597   mxDestroyArray(prhs[2]);
4598   mxDestroyArray(prhs[3]);
4599   mxDestroyArray(prhs[4]);
4600   mxDestroyArray(plhs[0]);
4601   PetscFunctionReturn(0);
4602 }
4603 
4604 
4605 #undef __FUNCT__
4606 #define __FUNCT__ "TSMonitorSetMatlab"
4607 /*
4608    TSMonitorSetMatlab - Sets the monitor function from Matlab
4609 
4610    Level: developer
4611 
4612 .keywords: TS, nonlinear, set, function
4613 
4614 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4615 */
4616 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
4617 {
4618   PetscErrorCode  ierr;
4619   TSMatlabContext *sctx;
4620 
4621   PetscFunctionBegin;
4622   /* currently sctx is memory bleed */
4623   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
4624   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
4625   /*
4626      This should work, but it doesn't
4627   sctx->ctx = ctx;
4628   mexMakeArrayPersistent(sctx->ctx);
4629   */
4630   sctx->ctx = mxDuplicateArray(ctx);
4631 
4632   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);CHKERRQ(ierr);
4633   PetscFunctionReturn(0);
4634 }
4635 #endif
4636 
4637 
4638 
4639 #undef __FUNCT__
4640 #define __FUNCT__ "TSMonitorLGSolution"
4641 /*@C
4642    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
4643        in a time based line graph
4644 
4645    Collective on TS
4646 
4647    Input Parameters:
4648 +  ts - the TS context
4649 .  step - current time-step
4650 .  ptime - current time
4651 -  lg - a line graph object
4652 
4653    Level: intermediate
4654 
4655     Notes: each process in a parallel run displays its component solutions in a separate window
4656 
4657 .keywords: TS,  vector, monitor, view
4658 
4659 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4660 @*/
4661 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4662 {
4663   PetscErrorCode    ierr;
4664   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
4665   const PetscScalar *yy;
4666   PetscInt          dim;
4667 
4668   PetscFunctionBegin;
4669   if (!step) {
4670     PetscDrawAxis axis;
4671     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4672     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
4673     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
4674     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
4675     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4676   }
4677   ierr = VecGetArrayRead(u,&yy);CHKERRQ(ierr);
4678 #if defined(PETSC_USE_COMPLEX)
4679   {
4680     PetscReal *yreal;
4681     PetscInt  i,n;
4682     ierr = VecGetLocalSize(u,&n);CHKERRQ(ierr);
4683     ierr = PetscMalloc(n*sizeof(PetscReal),&yreal);CHKERRQ(ierr);
4684     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
4685     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
4686     ierr = PetscFree(yreal);CHKERRQ(ierr);
4687   }
4688 #else
4689   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
4690 #endif
4691   ierr = VecRestoreArrayRead(u,&yy);CHKERRQ(ierr);
4692   if (((ctx->howoften > 0) && (!(step % ctx->howoften)) && (step > -1)) || ((ctx->howoften == -1) && (step == -1))) {
4693     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4694   }
4695   PetscFunctionReturn(0);
4696 }
4697 
4698 #undef __FUNCT__
4699 #define __FUNCT__ "TSMonitorLGError"
4700 /*@C
4701    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the solution vector
4702        in a time based line graph
4703 
4704    Collective on TS
4705 
4706    Input Parameters:
4707 +  ts - the TS context
4708 .  step - current time-step
4709 .  ptime - current time
4710 -  lg - a line graph object
4711 
4712    Level: intermediate
4713 
4714    Notes:
4715    Only for sequential solves.
4716 
4717    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
4718 
4719    Options Database Keys:
4720 .  -ts_monitor_lg_error - create a graphical monitor of error history
4721 
4722 .keywords: TS,  vector, monitor, view
4723 
4724 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4725 @*/
4726 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4727 {
4728   PetscErrorCode    ierr;
4729   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
4730   const PetscScalar *yy;
4731   Vec               y;
4732   PetscInt          dim;
4733 
4734   PetscFunctionBegin;
4735   if (!step) {
4736     PetscDrawAxis axis;
4737     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4738     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Solution");CHKERRQ(ierr);
4739     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
4740     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
4741     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4742   }
4743   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
4744   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
4745   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
4746   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
4747 #if defined(PETSC_USE_COMPLEX)
4748   {
4749     PetscReal *yreal;
4750     PetscInt  i,n;
4751     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
4752     ierr = PetscMalloc(n*sizeof(PetscReal),&yreal);CHKERRQ(ierr);
4753     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
4754     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
4755     ierr = PetscFree(yreal);CHKERRQ(ierr);
4756   }
4757 #else
4758   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
4759 #endif
4760   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
4761   ierr = VecDestroy(&y);CHKERRQ(ierr);
4762   if (((ctx->howoften > 0) && (!(step % ctx->howoften)) && (step > -1)) || ((ctx->howoften == -1) && (step == -1))) {
4763     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4764   }
4765   PetscFunctionReturn(0);
4766 }
4767 
4768 #undef __FUNCT__
4769 #define __FUNCT__ "TSMonitorLGSNESIterations"
4770 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
4771 {
4772   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4773   PetscReal      x   = ptime,y;
4774   PetscErrorCode ierr;
4775   PetscInt       its;
4776 
4777   PetscFunctionBegin;
4778   if (!n) {
4779     PetscDrawAxis axis;
4780 
4781     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4782     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
4783     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4784 
4785     ctx->snes_its = 0;
4786   }
4787   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
4788   y    = its - ctx->snes_its;
4789   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4790   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
4791     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4792   }
4793   ctx->snes_its = its;
4794   PetscFunctionReturn(0);
4795 }
4796 
4797 #undef __FUNCT__
4798 #define __FUNCT__ "TSMonitorLGKSPIterations"
4799 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
4800 {
4801   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4802   PetscReal      x   = ptime,y;
4803   PetscErrorCode ierr;
4804   PetscInt       its;
4805 
4806   PetscFunctionBegin;
4807   if (!n) {
4808     PetscDrawAxis axis;
4809 
4810     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4811     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
4812     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4813 
4814     ctx->ksp_its = 0;
4815   }
4816   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
4817   y    = its - ctx->ksp_its;
4818   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4819   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
4820     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4821   }
4822   ctx->ksp_its = its;
4823   PetscFunctionReturn(0);
4824 }
4825 
4826 #undef __FUNCT__
4827 #define __FUNCT__ "TSComputeLinearStability"
4828 /*@
4829    TSComputeLinearStability - computes the linear stability function at a point
4830 
4831    Collective on TS and Vec
4832 
4833    Input Parameters:
4834 +  ts - the TS context
4835 -  xr,xi - real and imaginary part of input arguments
4836 
4837    Output Parameters:
4838 .  yr,yi - real and imaginary part of function value
4839 
4840    Level: developer
4841 
4842 .keywords: TS, compute
4843 
4844 .seealso: TSSetRHSFunction(), TSComputeIFunction()
4845 @*/
4846 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
4847 {
4848   PetscErrorCode ierr;
4849 
4850   PetscFunctionBegin;
4851   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4852   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
4853   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
4854   PetscFunctionReturn(0);
4855 }
4856