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