xref: /petsc/src/ts/interface/ts.c (revision d45a07a79bb1e93ae6fa85d4a4175cd20a6ac3a0)
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     PetscMPIInt rank;
1397     const char  *name;
1398 
1399     ierr = PetscObjectGetName((PetscObject)ts,&name);CHKERRQ(ierr);
1400     ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
1401     if (!((PetscObject)ts)->amsmem && !rank) {
1402       char       dir[1024];
1403 
1404       ierr = PetscObjectViewSAWs((PetscObject)ts,viewer);CHKERRQ(ierr);
1405       ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time_step",name);CHKERRQ(ierr);
1406       PetscStackCallSAWs(SAWs_Register,(dir,&ts->steps,1,SAWs_READ,SAWs_INT));
1407       ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time",name);CHKERRQ(ierr);
1408       PetscStackCallSAWs(SAWs_Register,(dir,&ts->ptime,1,SAWs_READ,SAWs_DOUBLE));
1409     }
1410     if (ts->ops->view) {
1411       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
1412     }
1413 #endif
1414   }
1415 
1416   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1417   ierr = PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials);CHKERRQ(ierr);
1418   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1419   PetscFunctionReturn(0);
1420 }
1421 
1422 
1423 #undef __FUNCT__
1424 #define __FUNCT__ "TSSetApplicationContext"
1425 /*@
1426    TSSetApplicationContext - Sets an optional user-defined context for
1427    the timesteppers.
1428 
1429    Logically Collective on TS
1430 
1431    Input Parameters:
1432 +  ts - the TS context obtained from TSCreate()
1433 -  usrP - optional user context
1434 
1435    Level: intermediate
1436 
1437 .keywords: TS, timestep, set, application, context
1438 
1439 .seealso: TSGetApplicationContext()
1440 @*/
1441 PetscErrorCode  TSSetApplicationContext(TS ts,void *usrP)
1442 {
1443   PetscFunctionBegin;
1444   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1445   ts->user = usrP;
1446   PetscFunctionReturn(0);
1447 }
1448 
1449 #undef __FUNCT__
1450 #define __FUNCT__ "TSGetApplicationContext"
1451 /*@
1452     TSGetApplicationContext - Gets the user-defined context for the
1453     timestepper.
1454 
1455     Not Collective
1456 
1457     Input Parameter:
1458 .   ts - the TS context obtained from TSCreate()
1459 
1460     Output Parameter:
1461 .   usrP - user context
1462 
1463     Level: intermediate
1464 
1465 .keywords: TS, timestep, get, application, context
1466 
1467 .seealso: TSSetApplicationContext()
1468 @*/
1469 PetscErrorCode  TSGetApplicationContext(TS ts,void *usrP)
1470 {
1471   PetscFunctionBegin;
1472   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1473   *(void**)usrP = ts->user;
1474   PetscFunctionReturn(0);
1475 }
1476 
1477 #undef __FUNCT__
1478 #define __FUNCT__ "TSGetTimeStepNumber"
1479 /*@
1480    TSGetTimeStepNumber - Gets the number of time steps completed.
1481 
1482    Not Collective
1483 
1484    Input Parameter:
1485 .  ts - the TS context obtained from TSCreate()
1486 
1487    Output Parameter:
1488 .  iter - number of steps completed so far
1489 
1490    Level: intermediate
1491 
1492 .keywords: TS, timestep, get, iteration, number
1493 .seealso: TSGetTime(), TSGetTimeStep(), TSSetPreStep(), TSSetPreStage(), TSSetPostStep()
1494 @*/
1495 PetscErrorCode  TSGetTimeStepNumber(TS ts,PetscInt *iter)
1496 {
1497   PetscFunctionBegin;
1498   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1499   PetscValidIntPointer(iter,2);
1500   *iter = ts->steps;
1501   PetscFunctionReturn(0);
1502 }
1503 
1504 #undef __FUNCT__
1505 #define __FUNCT__ "TSSetInitialTimeStep"
1506 /*@
1507    TSSetInitialTimeStep - Sets the initial timestep to be used,
1508    as well as the initial time.
1509 
1510    Logically Collective on TS
1511 
1512    Input Parameters:
1513 +  ts - the TS context obtained from TSCreate()
1514 .  initial_time - the initial time
1515 -  time_step - the size of the timestep
1516 
1517    Level: intermediate
1518 
1519 .seealso: TSSetTimeStep(), TSGetTimeStep()
1520 
1521 .keywords: TS, set, initial, timestep
1522 @*/
1523 PetscErrorCode  TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step)
1524 {
1525   PetscErrorCode ierr;
1526 
1527   PetscFunctionBegin;
1528   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1529   ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr);
1530   ierr = TSSetTime(ts,initial_time);CHKERRQ(ierr);
1531   PetscFunctionReturn(0);
1532 }
1533 
1534 #undef __FUNCT__
1535 #define __FUNCT__ "TSSetTimeStep"
1536 /*@
1537    TSSetTimeStep - Allows one to reset the timestep at any time,
1538    useful for simple pseudo-timestepping codes.
1539 
1540    Logically Collective on TS
1541 
1542    Input Parameters:
1543 +  ts - the TS context obtained from TSCreate()
1544 -  time_step - the size of the timestep
1545 
1546    Level: intermediate
1547 
1548 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1549 
1550 .keywords: TS, set, timestep
1551 @*/
1552 PetscErrorCode  TSSetTimeStep(TS ts,PetscReal time_step)
1553 {
1554   PetscFunctionBegin;
1555   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1556   PetscValidLogicalCollectiveReal(ts,time_step,2);
1557   ts->time_step      = time_step;
1558   ts->time_step_orig = time_step;
1559   PetscFunctionReturn(0);
1560 }
1561 
1562 #undef __FUNCT__
1563 #define __FUNCT__ "TSSetExactFinalTime"
1564 /*@
1565    TSSetExactFinalTime - Determines whether to adapt the final time step to
1566      match the exact final time, interpolate solution to the exact final time,
1567      or just return at the final time TS computed.
1568 
1569   Logically Collective on TS
1570 
1571    Input Parameter:
1572 +   ts - the time-step context
1573 -   eftopt - exact final time option
1574 
1575    Level: beginner
1576 
1577 .seealso: TSExactFinalTimeOption
1578 @*/
1579 PetscErrorCode  TSSetExactFinalTime(TS ts,TSExactFinalTimeOption eftopt)
1580 {
1581   PetscFunctionBegin;
1582   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1583   PetscValidLogicalCollectiveEnum(ts,eftopt,2);
1584   ts->exact_final_time = eftopt;
1585   PetscFunctionReturn(0);
1586 }
1587 
1588 #undef __FUNCT__
1589 #define __FUNCT__ "TSGetTimeStep"
1590 /*@
1591    TSGetTimeStep - Gets the current timestep size.
1592 
1593    Not Collective
1594 
1595    Input Parameter:
1596 .  ts - the TS context obtained from TSCreate()
1597 
1598    Output Parameter:
1599 .  dt - the current timestep size
1600 
1601    Level: intermediate
1602 
1603 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1604 
1605 .keywords: TS, get, timestep
1606 @*/
1607 PetscErrorCode  TSGetTimeStep(TS ts,PetscReal *dt)
1608 {
1609   PetscFunctionBegin;
1610   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1611   PetscValidRealPointer(dt,2);
1612   *dt = ts->time_step;
1613   PetscFunctionReturn(0);
1614 }
1615 
1616 #undef __FUNCT__
1617 #define __FUNCT__ "TSGetSolution"
1618 /*@
1619    TSGetSolution - Returns the solution at the present timestep. It
1620    is valid to call this routine inside the function that you are evaluating
1621    in order to move to the new timestep. This vector not changed until
1622    the solution at the next timestep has been calculated.
1623 
1624    Not Collective, but Vec returned is parallel if TS is parallel
1625 
1626    Input Parameter:
1627 .  ts - the TS context obtained from TSCreate()
1628 
1629    Output Parameter:
1630 .  v - the vector containing the solution
1631 
1632    Level: intermediate
1633 
1634 .seealso: TSGetTimeStep()
1635 
1636 .keywords: TS, timestep, get, solution
1637 @*/
1638 PetscErrorCode  TSGetSolution(TS ts,Vec *v)
1639 {
1640   PetscFunctionBegin;
1641   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1642   PetscValidPointer(v,2);
1643   *v = ts->vec_sol;
1644   PetscFunctionReturn(0);
1645 }
1646 
1647 /* ----- Routines to initialize and destroy a timestepper ---- */
1648 #undef __FUNCT__
1649 #define __FUNCT__ "TSSetProblemType"
1650 /*@
1651   TSSetProblemType - Sets the type of problem to be solved.
1652 
1653   Not collective
1654 
1655   Input Parameters:
1656 + ts   - The TS
1657 - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1658 .vb
1659          U_t - A U = 0      (linear)
1660          U_t - A(t) U = 0   (linear)
1661          F(t,U,U_t) = 0     (nonlinear)
1662 .ve
1663 
1664    Level: beginner
1665 
1666 .keywords: TS, problem type
1667 .seealso: TSSetUp(), TSProblemType, TS
1668 @*/
1669 PetscErrorCode  TSSetProblemType(TS ts, TSProblemType type)
1670 {
1671   PetscErrorCode ierr;
1672 
1673   PetscFunctionBegin;
1674   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1675   ts->problem_type = type;
1676   if (type == TS_LINEAR) {
1677     SNES snes;
1678     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1679     ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);
1680   }
1681   PetscFunctionReturn(0);
1682 }
1683 
1684 #undef __FUNCT__
1685 #define __FUNCT__ "TSGetProblemType"
1686 /*@C
1687   TSGetProblemType - Gets the type of problem to be solved.
1688 
1689   Not collective
1690 
1691   Input Parameter:
1692 . ts   - The TS
1693 
1694   Output Parameter:
1695 . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1696 .vb
1697          M U_t = A U
1698          M(t) U_t = A(t) U
1699          F(t,U,U_t)
1700 .ve
1701 
1702    Level: beginner
1703 
1704 .keywords: TS, problem type
1705 .seealso: TSSetUp(), TSProblemType, TS
1706 @*/
1707 PetscErrorCode  TSGetProblemType(TS ts, TSProblemType *type)
1708 {
1709   PetscFunctionBegin;
1710   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1711   PetscValidIntPointer(type,2);
1712   *type = ts->problem_type;
1713   PetscFunctionReturn(0);
1714 }
1715 
1716 #undef __FUNCT__
1717 #define __FUNCT__ "TSSetUp"
1718 /*@
1719    TSSetUp - Sets up the internal data structures for the later use
1720    of a timestepper.
1721 
1722    Collective on TS
1723 
1724    Input Parameter:
1725 .  ts - the TS context obtained from TSCreate()
1726 
1727    Notes:
1728    For basic use of the TS solvers the user need not explicitly call
1729    TSSetUp(), since these actions will automatically occur during
1730    the call to TSStep().  However, if one wishes to control this
1731    phase separately, TSSetUp() should be called after TSCreate()
1732    and optional routines of the form TSSetXXX(), but before TSStep().
1733 
1734    Level: advanced
1735 
1736 .keywords: TS, timestep, setup
1737 
1738 .seealso: TSCreate(), TSStep(), TSDestroy()
1739 @*/
1740 PetscErrorCode  TSSetUp(TS ts)
1741 {
1742   PetscErrorCode ierr;
1743   DM             dm;
1744   PetscErrorCode (*func)(SNES,Vec,Vec,void*);
1745   PetscErrorCode (*jac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
1746   TSIJacobian    ijac;
1747   TSRHSJacobian  rhsjac;
1748 
1749   PetscFunctionBegin;
1750   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1751   if (ts->setupcalled) PetscFunctionReturn(0);
1752 
1753   if (!((PetscObject)ts)->type_name) {
1754     ierr = TSSetType(ts,TSEULER);CHKERRQ(ierr);
1755   }
1756 
1757   if (!ts->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first");
1758 
1759   ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr);
1760 
1761   if (ts->rhsjacobian.reuse) {
1762     Mat Amat,Pmat;
1763     SNES snes;
1764     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1765     ierr = SNESGetJacobian(snes,&Amat,&Pmat,NULL,NULL);CHKERRQ(ierr);
1766     /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
1767      * have displaced the RHS matrix */
1768     if (Amat == ts->Arhs) {
1769       ierr = MatDuplicate(ts->Arhs,MAT_DO_NOT_COPY_VALUES,&Amat);CHKERRQ(ierr);
1770       ierr = SNESSetJacobian(snes,Amat,NULL,NULL,NULL);CHKERRQ(ierr);
1771       ierr = MatDestroy(&Amat);CHKERRQ(ierr);
1772     }
1773     if (Pmat == ts->Brhs) {
1774       ierr = MatDuplicate(ts->Brhs,MAT_DO_NOT_COPY_VALUES,&Pmat);CHKERRQ(ierr);
1775       ierr = SNESSetJacobian(snes,NULL,Pmat,NULL,NULL);CHKERRQ(ierr);
1776       ierr = MatDestroy(&Pmat);CHKERRQ(ierr);
1777     }
1778   }
1779 
1780   if (ts->ops->setup) {
1781     ierr = (*ts->ops->setup)(ts);CHKERRQ(ierr);
1782   }
1783 
1784   /* in the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
1785    to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
1786    */
1787   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1788   ierr = DMSNESGetFunction(dm,&func,NULL);CHKERRQ(ierr);
1789   if (!func) {
1790     ierr =DMSNESSetFunction(dm,SNESTSFormFunction,ts);CHKERRQ(ierr);
1791   }
1792   /* if the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
1793      Otherwise, the SNES will use coloring internally to form the Jacobian.
1794    */
1795   ierr = DMSNESGetJacobian(dm,&jac,NULL);CHKERRQ(ierr);
1796   ierr = DMTSGetIJacobian(dm,&ijac,NULL);CHKERRQ(ierr);
1797   ierr = DMTSGetRHSJacobian(dm,&rhsjac,NULL);CHKERRQ(ierr);
1798   if (!jac && (ijac || rhsjac)) {
1799     ierr = DMSNESSetJacobian(dm,SNESTSFormJacobian,ts);CHKERRQ(ierr);
1800   }
1801   ts->setupcalled = PETSC_TRUE;
1802   PetscFunctionReturn(0);
1803 }
1804 
1805 #undef __FUNCT__
1806 #define __FUNCT__ "TSReset"
1807 /*@
1808    TSReset - Resets a TS context and removes any allocated Vecs and Mats.
1809 
1810    Collective on TS
1811 
1812    Input Parameter:
1813 .  ts - the TS context obtained from TSCreate()
1814 
1815    Level: beginner
1816 
1817 .keywords: TS, timestep, reset
1818 
1819 .seealso: TSCreate(), TSSetup(), TSDestroy()
1820 @*/
1821 PetscErrorCode  TSReset(TS ts)
1822 {
1823   PetscErrorCode ierr;
1824 
1825   PetscFunctionBegin;
1826   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1827   if (ts->ops->reset) {
1828     ierr = (*ts->ops->reset)(ts);CHKERRQ(ierr);
1829   }
1830   if (ts->snes) {ierr = SNESReset(ts->snes);CHKERRQ(ierr);}
1831 
1832   ierr = MatDestroy(&ts->Arhs);CHKERRQ(ierr);
1833   ierr = MatDestroy(&ts->Brhs);CHKERRQ(ierr);
1834   ierr = VecDestroy(&ts->Frhs);CHKERRQ(ierr);
1835   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
1836   ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
1837   ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
1838   ierr = VecDestroyVecs(ts->nwork,&ts->work);CHKERRQ(ierr);
1839 
1840   ts->setupcalled = PETSC_FALSE;
1841   PetscFunctionReturn(0);
1842 }
1843 
1844 #undef __FUNCT__
1845 #define __FUNCT__ "TSDestroy"
1846 /*@
1847    TSDestroy - Destroys the timestepper context that was created
1848    with TSCreate().
1849 
1850    Collective on TS
1851 
1852    Input Parameter:
1853 .  ts - the TS context obtained from TSCreate()
1854 
1855    Level: beginner
1856 
1857 .keywords: TS, timestepper, destroy
1858 
1859 .seealso: TSCreate(), TSSetUp(), TSSolve()
1860 @*/
1861 PetscErrorCode  TSDestroy(TS *ts)
1862 {
1863   PetscErrorCode ierr;
1864 
1865   PetscFunctionBegin;
1866   if (!*ts) PetscFunctionReturn(0);
1867   PetscValidHeaderSpecific((*ts),TS_CLASSID,1);
1868   if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; PetscFunctionReturn(0);}
1869 
1870   ierr = TSReset((*ts));CHKERRQ(ierr);
1871 
1872   /* if memory was published with SAWs then destroy it */
1873   ierr = PetscObjectSAWsViewOff((PetscObject)*ts);CHKERRQ(ierr);
1874   if ((*ts)->ops->destroy) {ierr = (*(*ts)->ops->destroy)((*ts));CHKERRQ(ierr);}
1875 
1876   ierr = TSAdaptDestroy(&(*ts)->adapt);CHKERRQ(ierr);
1877   ierr = SNESDestroy(&(*ts)->snes);CHKERRQ(ierr);
1878   ierr = DMDestroy(&(*ts)->dm);CHKERRQ(ierr);
1879   ierr = TSMonitorCancel((*ts));CHKERRQ(ierr);
1880 
1881   ierr = PetscHeaderDestroy(ts);CHKERRQ(ierr);
1882   PetscFunctionReturn(0);
1883 }
1884 
1885 #undef __FUNCT__
1886 #define __FUNCT__ "TSGetSNES"
1887 /*@
1888    TSGetSNES - Returns the SNES (nonlinear solver) associated with
1889    a TS (timestepper) context. Valid only for nonlinear problems.
1890 
1891    Not Collective, but SNES is parallel if TS is parallel
1892 
1893    Input Parameter:
1894 .  ts - the TS context obtained from TSCreate()
1895 
1896    Output Parameter:
1897 .  snes - the nonlinear solver context
1898 
1899    Notes:
1900    The user can then directly manipulate the SNES context to set various
1901    options, etc.  Likewise, the user can then extract and manipulate the
1902    KSP, KSP, and PC contexts as well.
1903 
1904    TSGetSNES() does not work for integrators that do not use SNES; in
1905    this case TSGetSNES() returns NULL in snes.
1906 
1907    Level: beginner
1908 
1909 .keywords: timestep, get, SNES
1910 @*/
1911 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
1912 {
1913   PetscErrorCode ierr;
1914 
1915   PetscFunctionBegin;
1916   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1917   PetscValidPointer(snes,2);
1918   if (!ts->snes) {
1919     ierr = SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes);CHKERRQ(ierr);
1920     ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
1921     ierr = PetscLogObjectParent(ts,ts->snes);CHKERRQ(ierr);
1922     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);CHKERRQ(ierr);
1923     if (ts->dm) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
1924     if (ts->problem_type == TS_LINEAR) {
1925       ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr);
1926     }
1927   }
1928   *snes = ts->snes;
1929   PetscFunctionReturn(0);
1930 }
1931 
1932 #undef __FUNCT__
1933 #define __FUNCT__ "TSSetSNES"
1934 /*@
1935    TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
1936 
1937    Collective
1938 
1939    Input Parameter:
1940 +  ts - the TS context obtained from TSCreate()
1941 -  snes - the nonlinear solver context
1942 
1943    Notes:
1944    Most users should have the TS created by calling TSGetSNES()
1945 
1946    Level: developer
1947 
1948 .keywords: timestep, set, SNES
1949 @*/
1950 PetscErrorCode TSSetSNES(TS ts,SNES snes)
1951 {
1952   PetscErrorCode ierr;
1953   PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
1954 
1955   PetscFunctionBegin;
1956   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1957   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
1958   ierr = PetscObjectReference((PetscObject)snes);CHKERRQ(ierr);
1959   ierr = SNESDestroy(&ts->snes);CHKERRQ(ierr);
1960 
1961   ts->snes = snes;
1962 
1963   ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
1964   ierr = SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL);CHKERRQ(ierr);
1965   if (func == SNESTSFormJacobian) {
1966     ierr = SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts);CHKERRQ(ierr);
1967   }
1968   PetscFunctionReturn(0);
1969 }
1970 
1971 #undef __FUNCT__
1972 #define __FUNCT__ "TSGetKSP"
1973 /*@
1974    TSGetKSP - Returns the KSP (linear solver) associated with
1975    a TS (timestepper) context.
1976 
1977    Not Collective, but KSP is parallel if TS is parallel
1978 
1979    Input Parameter:
1980 .  ts - the TS context obtained from TSCreate()
1981 
1982    Output Parameter:
1983 .  ksp - the nonlinear solver context
1984 
1985    Notes:
1986    The user can then directly manipulate the KSP context to set various
1987    options, etc.  Likewise, the user can then extract and manipulate the
1988    KSP and PC contexts as well.
1989 
1990    TSGetKSP() does not work for integrators that do not use KSP;
1991    in this case TSGetKSP() returns NULL in ksp.
1992 
1993    Level: beginner
1994 
1995 .keywords: timestep, get, KSP
1996 @*/
1997 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
1998 {
1999   PetscErrorCode ierr;
2000   SNES           snes;
2001 
2002   PetscFunctionBegin;
2003   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2004   PetscValidPointer(ksp,2);
2005   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
2006   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
2007   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2008   ierr = SNESGetKSP(snes,ksp);CHKERRQ(ierr);
2009   PetscFunctionReturn(0);
2010 }
2011 
2012 /* ----------- Routines to set solver parameters ---------- */
2013 
2014 #undef __FUNCT__
2015 #define __FUNCT__ "TSGetDuration"
2016 /*@
2017    TSGetDuration - Gets the maximum number of timesteps to use and
2018    maximum time for iteration.
2019 
2020    Not Collective
2021 
2022    Input Parameters:
2023 +  ts       - the TS context obtained from TSCreate()
2024 .  maxsteps - maximum number of iterations to use, or NULL
2025 -  maxtime  - final time to iterate to, or NULL
2026 
2027    Level: intermediate
2028 
2029 .keywords: TS, timestep, get, maximum, iterations, time
2030 @*/
2031 PetscErrorCode  TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
2032 {
2033   PetscFunctionBegin;
2034   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2035   if (maxsteps) {
2036     PetscValidIntPointer(maxsteps,2);
2037     *maxsteps = ts->max_steps;
2038   }
2039   if (maxtime) {
2040     PetscValidScalarPointer(maxtime,3);
2041     *maxtime = ts->max_time;
2042   }
2043   PetscFunctionReturn(0);
2044 }
2045 
2046 #undef __FUNCT__
2047 #define __FUNCT__ "TSSetDuration"
2048 /*@
2049    TSSetDuration - Sets the maximum number of timesteps to use and
2050    maximum time for iteration.
2051 
2052    Logically Collective on TS
2053 
2054    Input Parameters:
2055 +  ts - the TS context obtained from TSCreate()
2056 .  maxsteps - maximum number of iterations to use
2057 -  maxtime - final time to iterate to
2058 
2059    Options Database Keys:
2060 .  -ts_max_steps <maxsteps> - Sets maxsteps
2061 .  -ts_final_time <maxtime> - Sets maxtime
2062 
2063    Notes:
2064    The default maximum number of iterations is 5000. Default time is 5.0
2065 
2066    Level: intermediate
2067 
2068 .keywords: TS, timestep, set, maximum, iterations
2069 
2070 .seealso: TSSetExactFinalTime()
2071 @*/
2072 PetscErrorCode  TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
2073 {
2074   PetscFunctionBegin;
2075   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2076   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
2077   PetscValidLogicalCollectiveReal(ts,maxtime,2);
2078   if (maxsteps >= 0) ts->max_steps = maxsteps;
2079   if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
2080   PetscFunctionReturn(0);
2081 }
2082 
2083 #undef __FUNCT__
2084 #define __FUNCT__ "TSSetSolution"
2085 /*@
2086    TSSetSolution - Sets the initial solution vector
2087    for use by the TS routines.
2088 
2089    Logically Collective on TS and Vec
2090 
2091    Input Parameters:
2092 +  ts - the TS context obtained from TSCreate()
2093 -  u - the solution vector
2094 
2095    Level: beginner
2096 
2097 .keywords: TS, timestep, set, solution, initial conditions
2098 @*/
2099 PetscErrorCode  TSSetSolution(TS ts,Vec u)
2100 {
2101   PetscErrorCode ierr;
2102   DM             dm;
2103 
2104   PetscFunctionBegin;
2105   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2106   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
2107   ierr = PetscObjectReference((PetscObject)u);CHKERRQ(ierr);
2108   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
2109 
2110   ts->vec_sol = u;
2111 
2112   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2113   ierr = DMShellSetGlobalVector(dm,u);CHKERRQ(ierr);
2114   PetscFunctionReturn(0);
2115 }
2116 
2117 #undef __FUNCT__
2118 #define __FUNCT__ "TSSetPreStep"
2119 /*@C
2120   TSSetPreStep - Sets the general-purpose function
2121   called once at the beginning of each time step.
2122 
2123   Logically Collective on TS
2124 
2125   Input Parameters:
2126 + ts   - The TS context obtained from TSCreate()
2127 - func - The function
2128 
2129   Calling sequence of func:
2130 . func (TS ts);
2131 
2132   Level: intermediate
2133 
2134   Note:
2135   If a step is rejected, TSStep() will call this routine again before each attempt.
2136   The last completed time step number can be queried using TSGetTimeStepNumber(), the
2137   size of the step being attempted can be obtained using TSGetTimeStep().
2138 
2139 .keywords: TS, timestep
2140 .seealso: TSSetPreStage(), TSSetPostStep(), TSStep()
2141 @*/
2142 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
2143 {
2144   PetscFunctionBegin;
2145   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2146   ts->prestep = func;
2147   PetscFunctionReturn(0);
2148 }
2149 
2150 #undef __FUNCT__
2151 #define __FUNCT__ "TSPreStep"
2152 /*@
2153   TSPreStep - Runs the user-defined pre-step function.
2154 
2155   Collective on TS
2156 
2157   Input Parameters:
2158 . ts   - The TS context obtained from TSCreate()
2159 
2160   Notes:
2161   TSPreStep() is typically used within time stepping implementations,
2162   so most users would not generally call this routine themselves.
2163 
2164   Level: developer
2165 
2166 .keywords: TS, timestep
2167 .seealso: TSSetPreStep(), TSPreStage(), TSPostStep()
2168 @*/
2169 PetscErrorCode  TSPreStep(TS ts)
2170 {
2171   PetscErrorCode ierr;
2172 
2173   PetscFunctionBegin;
2174   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2175   if (ts->prestep) {
2176     PetscStackCallStandard((*ts->prestep),(ts));
2177   }
2178   PetscFunctionReturn(0);
2179 }
2180 
2181 #undef __FUNCT__
2182 #define __FUNCT__ "TSSetPreStage"
2183 /*@C
2184   TSSetPreStage - Sets the general-purpose function
2185   called once at the beginning of each stage.
2186 
2187   Logically Collective on TS
2188 
2189   Input Parameters:
2190 + ts   - The TS context obtained from TSCreate()
2191 - func - The function
2192 
2193   Calling sequence of func:
2194 . PetscErrorCode func(TS ts, PetscReal stagetime);
2195 
2196   Level: intermediate
2197 
2198   Note:
2199   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
2200   The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
2201   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
2202 
2203 .keywords: TS, timestep
2204 .seealso: TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
2205 @*/
2206 PetscErrorCode  TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
2207 {
2208   PetscFunctionBegin;
2209   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2210   ts->prestage = func;
2211   PetscFunctionReturn(0);
2212 }
2213 
2214 #undef __FUNCT__
2215 #define __FUNCT__ "TSPreStage"
2216 /*@
2217   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
2218 
2219   Collective on TS
2220 
2221   Input Parameters:
2222 . ts   - The TS context obtained from TSCreate()
2223 
2224   Notes:
2225   TSPreStage() is typically used within time stepping implementations,
2226   most users would not generally call this routine themselves.
2227 
2228   Level: developer
2229 
2230 .keywords: TS, timestep
2231 .seealso: TSSetPreStep(), TSPreStep(), TSPostStep()
2232 @*/
2233 PetscErrorCode  TSPreStage(TS ts, PetscReal stagetime)
2234 {
2235   PetscErrorCode ierr;
2236 
2237   PetscFunctionBegin;
2238   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2239   if (ts->prestage) {
2240     PetscStackCallStandard((*ts->prestage),(ts,stagetime));
2241   }
2242   PetscFunctionReturn(0);
2243 }
2244 
2245 #undef __FUNCT__
2246 #define __FUNCT__ "TSSetPostStep"
2247 /*@C
2248   TSSetPostStep - Sets the general-purpose function
2249   called once at the end of each time step.
2250 
2251   Logically Collective on TS
2252 
2253   Input Parameters:
2254 + ts   - The TS context obtained from TSCreate()
2255 - func - The function
2256 
2257   Calling sequence of func:
2258 $ func (TS ts);
2259 
2260   Level: intermediate
2261 
2262 .keywords: TS, timestep
2263 .seealso: TSSetPreStep(), TSSetPreStage(), TSGetTimeStep(), TSGetTimeStepNumber(), TSGetTime()
2264 @*/
2265 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
2266 {
2267   PetscFunctionBegin;
2268   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2269   ts->poststep = func;
2270   PetscFunctionReturn(0);
2271 }
2272 
2273 #undef __FUNCT__
2274 #define __FUNCT__ "TSPostStep"
2275 /*@
2276   TSPostStep - Runs the user-defined post-step function.
2277 
2278   Collective on TS
2279 
2280   Input Parameters:
2281 . ts   - The TS context obtained from TSCreate()
2282 
2283   Notes:
2284   TSPostStep() is typically used within time stepping implementations,
2285   so most users would not generally call this routine themselves.
2286 
2287   Level: developer
2288 
2289 .keywords: TS, timestep
2290 @*/
2291 PetscErrorCode  TSPostStep(TS ts)
2292 {
2293   PetscErrorCode ierr;
2294 
2295   PetscFunctionBegin;
2296   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2297   if (ts->poststep) {
2298     PetscStackCallStandard((*ts->poststep),(ts));
2299   }
2300   PetscFunctionReturn(0);
2301 }
2302 
2303 /* ------------ Routines to set performance monitoring options ----------- */
2304 
2305 #undef __FUNCT__
2306 #define __FUNCT__ "TSMonitorSet"
2307 /*@C
2308    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
2309    timestep to display the iteration's  progress.
2310 
2311    Logically Collective on TS
2312 
2313    Input Parameters:
2314 +  ts - the TS context obtained from TSCreate()
2315 .  monitor - monitoring routine
2316 .  mctx - [optional] user-defined context for private data for the
2317              monitor routine (use NULL if no context is desired)
2318 -  monitordestroy - [optional] routine that frees monitor context
2319           (may be NULL)
2320 
2321    Calling sequence of monitor:
2322 $    int monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
2323 
2324 +    ts - the TS context
2325 .    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
2326                                been interpolated to)
2327 .    time - current time
2328 .    u - current iterate
2329 -    mctx - [optional] monitoring context
2330 
2331    Notes:
2332    This routine adds an additional monitor to the list of monitors that
2333    already has been loaded.
2334 
2335    Fortran notes: Only a single monitor function can be set for each TS object
2336 
2337    Level: intermediate
2338 
2339 .keywords: TS, timestep, set, monitor
2340 
2341 .seealso: TSMonitorDefault(), TSMonitorCancel()
2342 @*/
2343 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
2344 {
2345   PetscFunctionBegin;
2346   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2347   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
2348   ts->monitor[ts->numbermonitors]          = monitor;
2349   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
2350   ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
2351   PetscFunctionReturn(0);
2352 }
2353 
2354 #undef __FUNCT__
2355 #define __FUNCT__ "TSMonitorCancel"
2356 /*@C
2357    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
2358 
2359    Logically Collective on TS
2360 
2361    Input Parameters:
2362 .  ts - the TS context obtained from TSCreate()
2363 
2364    Notes:
2365    There is no way to remove a single, specific monitor.
2366 
2367    Level: intermediate
2368 
2369 .keywords: TS, timestep, set, monitor
2370 
2371 .seealso: TSMonitorDefault(), TSMonitorSet()
2372 @*/
2373 PetscErrorCode  TSMonitorCancel(TS ts)
2374 {
2375   PetscErrorCode ierr;
2376   PetscInt       i;
2377 
2378   PetscFunctionBegin;
2379   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2380   for (i=0; i<ts->numbermonitors; i++) {
2381     if (ts->monitordestroy[i]) {
2382       ierr = (*ts->monitordestroy[i])(&ts->monitorcontext[i]);CHKERRQ(ierr);
2383     }
2384   }
2385   ts->numbermonitors = 0;
2386   PetscFunctionReturn(0);
2387 }
2388 
2389 #undef __FUNCT__
2390 #define __FUNCT__ "TSMonitorDefault"
2391 /*@
2392    TSMonitorDefault - Sets the Default monitor
2393 
2394    Level: intermediate
2395 
2396 .keywords: TS, set, monitor
2397 
2398 .seealso: TSMonitorDefault(), TSMonitorSet()
2399 @*/
2400 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *dummy)
2401 {
2402   PetscErrorCode ierr;
2403   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)ts));
2404 
2405   PetscFunctionBegin;
2406   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2407   ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g\n",step,(double)ts->time_step,(double)ptime);CHKERRQ(ierr);
2408   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2409   PetscFunctionReturn(0);
2410 }
2411 
2412 #undef __FUNCT__
2413 #define __FUNCT__ "TSSetRetainStages"
2414 /*@
2415    TSSetRetainStages - Request that all stages in the upcoming step be stored so that interpolation will be available.
2416 
2417    Logically Collective on TS
2418 
2419    Input Argument:
2420 .  ts - time stepping context
2421 
2422    Output Argument:
2423 .  flg - PETSC_TRUE or PETSC_FALSE
2424 
2425    Level: intermediate
2426 
2427 .keywords: TS, set
2428 
2429 .seealso: TSInterpolate(), TSSetPostStep()
2430 @*/
2431 PetscErrorCode TSSetRetainStages(TS ts,PetscBool flg)
2432 {
2433   PetscFunctionBegin;
2434   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2435   ts->retain_stages = flg;
2436   PetscFunctionReturn(0);
2437 }
2438 
2439 #undef __FUNCT__
2440 #define __FUNCT__ "TSInterpolate"
2441 /*@
2442    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
2443 
2444    Collective on TS
2445 
2446    Input Argument:
2447 +  ts - time stepping context
2448 -  t - time to interpolate to
2449 
2450    Output Argument:
2451 .  U - state at given time
2452 
2453    Notes:
2454    The user should call TSSetRetainStages() before taking a step in which interpolation will be requested.
2455 
2456    Level: intermediate
2457 
2458    Developer Notes:
2459    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
2460 
2461 .keywords: TS, set
2462 
2463 .seealso: TSSetRetainStages(), TSSetPostStep()
2464 @*/
2465 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
2466 {
2467   PetscErrorCode ierr;
2468 
2469   PetscFunctionBegin;
2470   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2471   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
2472   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);
2473   if (!ts->ops->interpolate) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
2474   ierr = (*ts->ops->interpolate)(ts,t,U);CHKERRQ(ierr);
2475   PetscFunctionReturn(0);
2476 }
2477 
2478 #undef __FUNCT__
2479 #define __FUNCT__ "TSStep"
2480 /*@
2481    TSStep - Steps one time step
2482 
2483    Collective on TS
2484 
2485    Input Parameter:
2486 .  ts - the TS context obtained from TSCreate()
2487 
2488    Level: intermediate
2489 
2490    Notes:
2491    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
2492    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
2493 
2494    This may over-step the final time provided in TSSetDuration() depending on the time-step used. TSSolve() interpolates to exactly the
2495    time provided in TSSetDuration(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
2496 
2497 .keywords: TS, timestep, solve
2498 
2499 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
2500 @*/
2501 PetscErrorCode  TSStep(TS ts)
2502 {
2503   PetscReal      ptime_prev;
2504   PetscErrorCode ierr;
2505 
2506   PetscFunctionBegin;
2507   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2508   ierr = TSSetUp(ts);CHKERRQ(ierr);
2509 
2510   ts->reason = TS_CONVERGED_ITERATING;
2511   ptime_prev = ts->ptime;
2512 
2513   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
2514   ierr = (*ts->ops->step)(ts);CHKERRQ(ierr);
2515   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
2516 
2517   ts->time_step_prev = ts->ptime - ptime_prev;
2518 
2519   if (ts->reason < 0) {
2520     if (ts->errorifstepfailed) {
2521       if (ts->reason == TS_DIVERGED_NONLINEAR_SOLVE) {
2522         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]);
2523       } else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
2524     }
2525   } else if (!ts->reason) {
2526     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
2527     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
2528   }
2529   PetscFunctionReturn(0);
2530 }
2531 
2532 #undef __FUNCT__
2533 #define __FUNCT__ "TSEvaluateStep"
2534 /*@
2535    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
2536 
2537    Collective on TS
2538 
2539    Input Arguments:
2540 +  ts - time stepping context
2541 .  order - desired order of accuracy
2542 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
2543 
2544    Output Arguments:
2545 .  U - state at the end of the current step
2546 
2547    Level: advanced
2548 
2549    Notes:
2550    This function cannot be called until all stages have been evaluated.
2551    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.
2552 
2553 .seealso: TSStep(), TSAdapt
2554 @*/
2555 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
2556 {
2557   PetscErrorCode ierr;
2558 
2559   PetscFunctionBegin;
2560   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2561   PetscValidType(ts,1);
2562   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
2563   if (!ts->ops->evaluatestep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
2564   ierr = (*ts->ops->evaluatestep)(ts,order,U,done);CHKERRQ(ierr);
2565   PetscFunctionReturn(0);
2566 }
2567 
2568 #undef __FUNCT__
2569 #define __FUNCT__ "TSSolve"
2570 /*@
2571    TSSolve - Steps the requested number of timesteps.
2572 
2573    Collective on TS
2574 
2575    Input Parameter:
2576 +  ts - the TS context obtained from TSCreate()
2577 -  u - the solution vector  (can be null if TSSetSolution() was used, otherwise must contain the initial conditions)
2578 
2579    Level: beginner
2580 
2581    Notes:
2582    The final time returned by this function may be different from the time of the internally
2583    held state accessible by TSGetSolution() and TSGetTime() because the method may have
2584    stepped over the final time.
2585 
2586 .keywords: TS, timestep, solve
2587 
2588 .seealso: TSCreate(), TSSetSolution(), TSStep()
2589 @*/
2590 PetscErrorCode TSSolve(TS ts,Vec u)
2591 {
2592   PetscBool         flg;
2593   PetscViewer       viewer;
2594   Vec               solution;
2595   PetscErrorCode    ierr;
2596   PetscViewerFormat format;
2597 
2598   PetscFunctionBegin;
2599   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2600   if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2);
2601   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 */
2602     PetscValidHeaderSpecific(u,VEC_CLASSID,2);
2603     if (!ts->vec_sol || u == ts->vec_sol) {
2604       ierr = VecDuplicate(u,&solution);CHKERRQ(ierr);
2605       ierr = TSSetSolution(ts,solution);CHKERRQ(ierr);
2606       ierr = VecDestroy(&solution);CHKERRQ(ierr); /* grant ownership */
2607     }
2608     ierr = VecCopy(u,ts->vec_sol);CHKERRQ(ierr);
2609   } else if (u) {
2610     ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
2611   }
2612   ierr = TSSetUp(ts);CHKERRQ(ierr);
2613   /* reset time step and iteration counters */
2614   ts->steps             = 0;
2615   ts->ksp_its           = 0;
2616   ts->snes_its          = 0;
2617   ts->num_snes_failures = 0;
2618   ts->reject            = 0;
2619   ts->reason            = TS_CONVERGED_ITERATING;
2620 
2621   ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject)ts)->prefix,"-ts_view_pre",&viewer,&format,&flg);CHKERRQ(ierr);
2622   if (flg && !PetscPreLoadingOn) {
2623     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
2624     ierr = TSView(ts,viewer);CHKERRQ(ierr);
2625     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
2626     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2627   }
2628 
2629   if (ts->ops->solve) {         /* This private interface is transitional and should be removed when all implementations are updated. */
2630     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
2631     ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);
2632     ts->solvetime = ts->ptime;
2633   } else {
2634     /* steps the requested number of timesteps. */
2635     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
2636     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
2637     while (!ts->reason) {
2638       ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
2639       ierr = TSStep(ts);CHKERRQ(ierr);
2640       ierr = TSPostStep(ts);CHKERRQ(ierr);
2641     }
2642     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
2643       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
2644       ts->solvetime = ts->max_time;
2645       solution = u;
2646     } else {
2647       if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
2648       ts->solvetime = ts->ptime;
2649       solution = ts->vec_sol;
2650     }
2651     ierr = TSMonitor(ts,ts->steps,ts->solvetime,solution);CHKERRQ(ierr);
2652   }
2653   ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject)ts)->prefix,"-ts_view",&viewer,&format,&flg);CHKERRQ(ierr);
2654   if (flg && !PetscPreLoadingOn) {
2655     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
2656     ierr = TSView(ts,viewer);CHKERRQ(ierr);
2657     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
2658     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2659   }
2660   PetscFunctionReturn(0);
2661 }
2662 
2663 #undef __FUNCT__
2664 #define __FUNCT__ "TSMonitor"
2665 /*@
2666    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
2667 
2668    Collective on TS
2669 
2670    Input Parameters:
2671 +  ts - time stepping context obtained from TSCreate()
2672 .  step - step number that has just completed
2673 .  ptime - model time of the state
2674 -  u - state at the current model time
2675 
2676    Notes:
2677    TSMonitor() is typically used within the time stepping implementations.
2678    Users might call this function when using the TSStep() interface instead of TSSolve().
2679 
2680    Level: advanced
2681 
2682 .keywords: TS, timestep
2683 @*/
2684 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
2685 {
2686   PetscErrorCode ierr;
2687   PetscInt       i,n = ts->numbermonitors;
2688 
2689   PetscFunctionBegin;
2690   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2691   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
2692   for (i=0; i<n; i++) {
2693     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
2694   }
2695   PetscFunctionReturn(0);
2696 }
2697 
2698 /* ------------------------------------------------------------------------*/
2699 struct _n_TSMonitorLGCtx {
2700   PetscDrawLG lg;
2701   PetscInt    howoften;  /* when > 0 uses step % howoften, when negative only final solution plotted */
2702   PetscInt    ksp_its,snes_its;
2703 };
2704 
2705 
2706 #undef __FUNCT__
2707 #define __FUNCT__ "TSMonitorLGCtxCreate"
2708 /*@C
2709    TSMonitorLGCtxCreate - Creates a line graph context for use with
2710    TS to monitor the solution process graphically in various ways
2711 
2712    Collective on TS
2713 
2714    Input Parameters:
2715 +  host - the X display to open, or null for the local machine
2716 .  label - the title to put in the title bar
2717 .  x, y - the screen coordinates of the upper left coordinate of the window
2718 .  m, n - the screen width and height in pixels
2719 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
2720 
2721    Output Parameter:
2722 .  ctx - the context
2723 
2724    Options Database Key:
2725 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
2726 .  -ts_monitor_lg_solution -
2727 .  -ts_monitor_lg_error -
2728 .  -ts_monitor_lg_ksp_iterations -
2729 .  -ts_monitor_lg_snes_iterations -
2730 -  -lg_indicate_data_points <true,false> - indicate the data points (at each time step) on the plot; default is true
2731 
2732    Notes:
2733    Use TSMonitorLGCtxDestroy() to destroy.
2734 
2735    Level: intermediate
2736 
2737 .keywords: TS, monitor, line graph, residual, seealso
2738 
2739 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
2740 
2741 @*/
2742 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
2743 {
2744   PetscDraw      win;
2745   PetscErrorCode ierr;
2746   PetscBool      flg = PETSC_TRUE;
2747 
2748   PetscFunctionBegin;
2749   ierr = PetscNew(struct _n_TSMonitorLGCtx,ctx);CHKERRQ(ierr);
2750   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&win);CHKERRQ(ierr);
2751   ierr = PetscDrawSetFromOptions(win);CHKERRQ(ierr);
2752   ierr = PetscDrawLGCreate(win,1,&(*ctx)->lg);CHKERRQ(ierr);
2753   ierr = PetscOptionsGetBool(NULL,"-lg_indicate_data_points",&flg,NULL);CHKERRQ(ierr);
2754   if (flg) {
2755     ierr = PetscDrawLGIndicateDataPoints((*ctx)->lg);CHKERRQ(ierr);
2756   }
2757   ierr = PetscLogObjectParent((*ctx)->lg,win);CHKERRQ(ierr);
2758   (*ctx)->howoften = howoften;
2759   PetscFunctionReturn(0);
2760 }
2761 
2762 #undef __FUNCT__
2763 #define __FUNCT__ "TSMonitorLGTimeStep"
2764 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
2765 {
2766   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
2767   PetscReal      x   = ptime,y;
2768   PetscErrorCode ierr;
2769 
2770   PetscFunctionBegin;
2771   if (!step) {
2772     PetscDrawAxis axis;
2773     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
2774     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time","Time step");CHKERRQ(ierr);
2775     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
2776   }
2777   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
2778   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
2779   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
2780     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
2781   }
2782   PetscFunctionReturn(0);
2783 }
2784 
2785 #undef __FUNCT__
2786 #define __FUNCT__ "TSMonitorLGCtxDestroy"
2787 /*@C
2788    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
2789    with TSMonitorLGCtxCreate().
2790 
2791    Collective on TSMonitorLGCtx
2792 
2793    Input Parameter:
2794 .  ctx - the monitor context
2795 
2796    Level: intermediate
2797 
2798 .keywords: TS, monitor, line graph, destroy
2799 
2800 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
2801 @*/
2802 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
2803 {
2804   PetscDraw      draw;
2805   PetscErrorCode ierr;
2806 
2807   PetscFunctionBegin;
2808   ierr = PetscDrawLGGetDraw((*ctx)->lg,&draw);CHKERRQ(ierr);
2809   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
2810   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
2811   ierr = PetscFree(*ctx);CHKERRQ(ierr);
2812   PetscFunctionReturn(0);
2813 }
2814 
2815 #undef __FUNCT__
2816 #define __FUNCT__ "TSGetTime"
2817 /*@
2818    TSGetTime - Gets the time of the most recently completed step.
2819 
2820    Not Collective
2821 
2822    Input Parameter:
2823 .  ts - the TS context obtained from TSCreate()
2824 
2825    Output Parameter:
2826 .  t  - the current time
2827 
2828    Level: beginner
2829 
2830    Note:
2831    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
2832    TSSetPreStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
2833 
2834 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
2835 
2836 .keywords: TS, get, time
2837 @*/
2838 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
2839 {
2840   PetscFunctionBegin;
2841   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2842   PetscValidRealPointer(t,2);
2843   *t = ts->ptime;
2844   PetscFunctionReturn(0);
2845 }
2846 
2847 #undef __FUNCT__
2848 #define __FUNCT__ "TSSetTime"
2849 /*@
2850    TSSetTime - Allows one to reset the time.
2851 
2852    Logically Collective on TS
2853 
2854    Input Parameters:
2855 +  ts - the TS context obtained from TSCreate()
2856 -  time - the time
2857 
2858    Level: intermediate
2859 
2860 .seealso: TSGetTime(), TSSetDuration()
2861 
2862 .keywords: TS, set, time
2863 @*/
2864 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
2865 {
2866   PetscFunctionBegin;
2867   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2868   PetscValidLogicalCollectiveReal(ts,t,2);
2869   ts->ptime = t;
2870   PetscFunctionReturn(0);
2871 }
2872 
2873 #undef __FUNCT__
2874 #define __FUNCT__ "TSSetOptionsPrefix"
2875 /*@C
2876    TSSetOptionsPrefix - Sets the prefix used for searching for all
2877    TS options in the database.
2878 
2879    Logically Collective on TS
2880 
2881    Input Parameter:
2882 +  ts     - The TS context
2883 -  prefix - The prefix to prepend to all option names
2884 
2885    Notes:
2886    A hyphen (-) must NOT be given at the beginning of the prefix name.
2887    The first character of all runtime options is AUTOMATICALLY the
2888    hyphen.
2889 
2890    Level: advanced
2891 
2892 .keywords: TS, set, options, prefix, database
2893 
2894 .seealso: TSSetFromOptions()
2895 
2896 @*/
2897 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
2898 {
2899   PetscErrorCode ierr;
2900   SNES           snes;
2901 
2902   PetscFunctionBegin;
2903   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2904   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2905   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2906   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
2907   PetscFunctionReturn(0);
2908 }
2909 
2910 
2911 #undef __FUNCT__
2912 #define __FUNCT__ "TSAppendOptionsPrefix"
2913 /*@C
2914    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
2915    TS options in the database.
2916 
2917    Logically Collective on TS
2918 
2919    Input Parameter:
2920 +  ts     - The TS context
2921 -  prefix - The prefix to prepend to all option names
2922 
2923    Notes:
2924    A hyphen (-) must NOT be given at the beginning of the prefix name.
2925    The first character of all runtime options is AUTOMATICALLY the
2926    hyphen.
2927 
2928    Level: advanced
2929 
2930 .keywords: TS, append, options, prefix, database
2931 
2932 .seealso: TSGetOptionsPrefix()
2933 
2934 @*/
2935 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
2936 {
2937   PetscErrorCode ierr;
2938   SNES           snes;
2939 
2940   PetscFunctionBegin;
2941   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2942   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2943   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2944   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
2945   PetscFunctionReturn(0);
2946 }
2947 
2948 #undef __FUNCT__
2949 #define __FUNCT__ "TSGetOptionsPrefix"
2950 /*@C
2951    TSGetOptionsPrefix - Sets the prefix used for searching for all
2952    TS options in the database.
2953 
2954    Not Collective
2955 
2956    Input Parameter:
2957 .  ts - The TS context
2958 
2959    Output Parameter:
2960 .  prefix - A pointer to the prefix string used
2961 
2962    Notes: On the fortran side, the user should pass in a string 'prifix' of
2963    sufficient length to hold the prefix.
2964 
2965    Level: intermediate
2966 
2967 .keywords: TS, get, options, prefix, database
2968 
2969 .seealso: TSAppendOptionsPrefix()
2970 @*/
2971 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
2972 {
2973   PetscErrorCode ierr;
2974 
2975   PetscFunctionBegin;
2976   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2977   PetscValidPointer(prefix,2);
2978   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2979   PetscFunctionReturn(0);
2980 }
2981 
2982 #undef __FUNCT__
2983 #define __FUNCT__ "TSGetRHSJacobian"
2984 /*@C
2985    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
2986 
2987    Not Collective, but parallel objects are returned if TS is parallel
2988 
2989    Input Parameter:
2990 .  ts  - The TS context obtained from TSCreate()
2991 
2992    Output Parameters:
2993 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
2994 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
2995 .  func - Function to compute the Jacobian of the RHS  (or NULL)
2996 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
2997 
2998    Notes: You can pass in NULL for any return argument you do not need.
2999 
3000    Level: intermediate
3001 
3002 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
3003 
3004 .keywords: TS, timestep, get, matrix, Jacobian
3005 @*/
3006 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
3007 {
3008   PetscErrorCode ierr;
3009   SNES           snes;
3010   DM             dm;
3011 
3012   PetscFunctionBegin;
3013   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3014   ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
3015   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3016   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
3017   PetscFunctionReturn(0);
3018 }
3019 
3020 #undef __FUNCT__
3021 #define __FUNCT__ "TSGetIJacobian"
3022 /*@C
3023    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
3024 
3025    Not Collective, but parallel objects are returned if TS is parallel
3026 
3027    Input Parameter:
3028 .  ts  - The TS context obtained from TSCreate()
3029 
3030    Output Parameters:
3031 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
3032 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
3033 .  f   - The function to compute the matrices
3034 - ctx - User-defined context for Jacobian evaluation routine
3035 
3036    Notes: You can pass in NULL for any return argument you do not need.
3037 
3038    Level: advanced
3039 
3040 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
3041 
3042 .keywords: TS, timestep, get, matrix, Jacobian
3043 @*/
3044 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
3045 {
3046   PetscErrorCode ierr;
3047   SNES           snes;
3048   DM             dm;
3049 
3050   PetscFunctionBegin;
3051   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3052   ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
3053   ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
3054   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3055   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
3056   PetscFunctionReturn(0);
3057 }
3058 
3059 
3060 #undef __FUNCT__
3061 #define __FUNCT__ "TSMonitorDrawSolution"
3062 /*@C
3063    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
3064    VecView() for the solution at each timestep
3065 
3066    Collective on TS
3067 
3068    Input Parameters:
3069 +  ts - the TS context
3070 .  step - current time-step
3071 .  ptime - current time
3072 -  dummy - either a viewer or NULL
3073 
3074    Options Database:
3075 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3076 
3077    Notes: the initial solution and current solution are not displayed with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
3078        will look bad
3079 
3080    Level: intermediate
3081 
3082 .keywords: TS,  vector, monitor, view
3083 
3084 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3085 @*/
3086 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3087 {
3088   PetscErrorCode   ierr;
3089   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
3090   PetscDraw        draw;
3091 
3092   PetscFunctionBegin;
3093   if (!step && ictx->showinitial) {
3094     if (!ictx->initialsolution) {
3095       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
3096     }
3097     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
3098   }
3099   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
3100 
3101   if (ictx->showinitial) {
3102     PetscReal pause;
3103     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
3104     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
3105     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
3106     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
3107     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
3108   }
3109   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
3110   if (ictx->showtimestepandtime) {
3111     PetscReal xl,yl,xr,yr,tw,w,h;
3112     char      time[32];
3113     size_t    len;
3114 
3115     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
3116     ierr = PetscSNPrintf(time,32,"Timestep %d Time %f",(int)step,(double)ptime);CHKERRQ(ierr);
3117     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
3118     ierr =  PetscStrlen(time,&len);CHKERRQ(ierr);
3119     ierr = PetscDrawStringGetSize(draw,&tw,NULL);CHKERRQ(ierr);
3120     w    = xl + .5*(xr - xl) - .5*len*tw;
3121     h    = yl + .95*(yr - yl);
3122     ierr = PetscDrawString(draw,w,h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
3123     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
3124   }
3125 
3126   if (ictx->showinitial) {
3127     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
3128   }
3129   PetscFunctionReturn(0);
3130 }
3131 
3132 #undef __FUNCT__
3133 #define __FUNCT__ "TSMonitorDrawSolutionPhase"
3134 /*@C
3135    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
3136 
3137    Collective on TS
3138 
3139    Input Parameters:
3140 +  ts - the TS context
3141 .  step - current time-step
3142 .  ptime - current time
3143 -  dummy - either a viewer or NULL
3144 
3145    Level: intermediate
3146 
3147 .keywords: TS,  vector, monitor, view
3148 
3149 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3150 @*/
3151 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3152 {
3153   PetscErrorCode    ierr;
3154   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
3155   PetscDraw         draw;
3156   MPI_Comm          comm;
3157   PetscInt          n;
3158   PetscMPIInt       size;
3159   PetscReal         xl,yl,xr,yr,tw,w,h;
3160   char              time[32];
3161   size_t            len;
3162   const PetscScalar *U;
3163 
3164   PetscFunctionBegin;
3165   ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
3166   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
3167   if (size != 1) SETERRQ(comm,PETSC_ERR_SUP,"Only allowed for sequential runs");
3168   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
3169   if (n != 2) SETERRQ(comm,PETSC_ERR_SUP,"Only for ODEs with two unknowns");
3170 
3171   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
3172 
3173   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
3174   ierr = PetscDrawAxisGetLimits(ictx->axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
3175   if ((PetscRealPart(U[0]) < xl) || (PetscRealPart(U[1]) < yl) || (PetscRealPart(U[0]) > xr) || (PetscRealPart(U[1]) > yr)) {
3176       ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
3177       PetscFunctionReturn(0);
3178   }
3179   if (!step) ictx->color++;
3180   ierr = PetscDrawPoint(draw,PetscRealPart(U[0]),PetscRealPart(U[1]),ictx->color);CHKERRQ(ierr);
3181   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
3182 
3183   if (ictx->showtimestepandtime) {
3184     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
3185     ierr = PetscSNPrintf(time,32,"Timestep %d Time %f",(int)step,(double)ptime);CHKERRQ(ierr);
3186     ierr = PetscStrlen(time,&len);CHKERRQ(ierr);
3187     ierr = PetscDrawStringGetSize(draw,&tw,NULL);CHKERRQ(ierr);
3188     w    = xl + .5*(xr - xl) - .5*len*tw;
3189     h    = yl + .95*(yr - yl);
3190     ierr = PetscDrawString(draw,w,h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
3191   }
3192   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
3193   PetscFunctionReturn(0);
3194 }
3195 
3196 
3197 #undef __FUNCT__
3198 #define __FUNCT__ "TSMonitorDrawCtxDestroy"
3199 /*@C
3200    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
3201 
3202    Collective on TS
3203 
3204    Input Parameters:
3205 .    ctx - the monitor context
3206 
3207    Level: intermediate
3208 
3209 .keywords: TS,  vector, monitor, view
3210 
3211 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
3212 @*/
3213 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
3214 {
3215   PetscErrorCode ierr;
3216 
3217   PetscFunctionBegin;
3218   ierr = PetscDrawAxisDestroy(&(*ictx)->axis);CHKERRQ(ierr);
3219   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
3220   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
3221   ierr = PetscFree(*ictx);CHKERRQ(ierr);
3222   PetscFunctionReturn(0);
3223 }
3224 
3225 #undef __FUNCT__
3226 #define __FUNCT__ "TSMonitorDrawCtxCreate"
3227 /*@C
3228    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
3229 
3230    Collective on TS
3231 
3232    Input Parameter:
3233 .    ts - time-step context
3234 
3235    Output Patameter:
3236 .    ctx - the monitor context
3237 
3238    Options Database:
3239 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3240 
3241    Level: intermediate
3242 
3243 .keywords: TS,  vector, monitor, view
3244 
3245 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
3246 @*/
3247 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
3248 {
3249   PetscErrorCode   ierr;
3250 
3251   PetscFunctionBegin;
3252   ierr = PetscNew(struct _n_TSMonitorDrawCtx,ctx);CHKERRQ(ierr);
3253   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
3254   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
3255 
3256   (*ctx)->howoften    = howoften;
3257   (*ctx)->showinitial = PETSC_FALSE;
3258   ierr = PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
3259 
3260   (*ctx)->showtimestepandtime = PETSC_FALSE;
3261   ierr = PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
3262   (*ctx)->color = PETSC_DRAW_WHITE;
3263   PetscFunctionReturn(0);
3264 }
3265 
3266 #undef __FUNCT__
3267 #define __FUNCT__ "TSMonitorDrawError"
3268 /*@C
3269    TSMonitorDrawError - Monitors progress of the TS solvers by calling
3270    VecView() for the error at each timestep
3271 
3272    Collective on TS
3273 
3274    Input Parameters:
3275 +  ts - the TS context
3276 .  step - current time-step
3277 .  ptime - current time
3278 -  dummy - either a viewer or NULL
3279 
3280    Level: intermediate
3281 
3282 .keywords: TS,  vector, monitor, view
3283 
3284 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3285 @*/
3286 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3287 {
3288   PetscErrorCode   ierr;
3289   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
3290   PetscViewer      viewer = ctx->viewer;
3291   Vec              work;
3292 
3293   PetscFunctionBegin;
3294   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
3295   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
3296   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
3297   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
3298   ierr = VecView(work,viewer);CHKERRQ(ierr);
3299   ierr = VecDestroy(&work);CHKERRQ(ierr);
3300   PetscFunctionReturn(0);
3301 }
3302 
3303 #include <petsc-private/dmimpl.h>
3304 #undef __FUNCT__
3305 #define __FUNCT__ "TSSetDM"
3306 /*@
3307    TSSetDM - Sets the DM that may be used by some preconditioners
3308 
3309    Logically Collective on TS and DM
3310 
3311    Input Parameters:
3312 +  ts - the preconditioner context
3313 -  dm - the dm
3314 
3315    Level: intermediate
3316 
3317 
3318 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
3319 @*/
3320 PetscErrorCode  TSSetDM(TS ts,DM dm)
3321 {
3322   PetscErrorCode ierr;
3323   SNES           snes;
3324   DMTS           tsdm;
3325 
3326   PetscFunctionBegin;
3327   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3328   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
3329   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
3330     if (ts->dm->dmts && !dm->dmts) {
3331       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
3332       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
3333       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
3334         tsdm->originaldm = dm;
3335       }
3336     }
3337     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
3338   }
3339   ts->dm = dm;
3340 
3341   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3342   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
3343   PetscFunctionReturn(0);
3344 }
3345 
3346 #undef __FUNCT__
3347 #define __FUNCT__ "TSGetDM"
3348 /*@
3349    TSGetDM - Gets the DM that may be used by some preconditioners
3350 
3351    Not Collective
3352 
3353    Input Parameter:
3354 . ts - the preconditioner context
3355 
3356    Output Parameter:
3357 .  dm - the dm
3358 
3359    Level: intermediate
3360 
3361 
3362 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
3363 @*/
3364 PetscErrorCode  TSGetDM(TS ts,DM *dm)
3365 {
3366   PetscErrorCode ierr;
3367 
3368   PetscFunctionBegin;
3369   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3370   if (!ts->dm) {
3371     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
3372     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
3373   }
3374   *dm = ts->dm;
3375   PetscFunctionReturn(0);
3376 }
3377 
3378 #undef __FUNCT__
3379 #define __FUNCT__ "SNESTSFormFunction"
3380 /*@
3381    SNESTSFormFunction - Function to evaluate nonlinear residual
3382 
3383    Logically Collective on SNES
3384 
3385    Input Parameter:
3386 + snes - nonlinear solver
3387 . U - the current state at which to evaluate the residual
3388 - ctx - user context, must be a TS
3389 
3390    Output Parameter:
3391 . F - the nonlinear residual
3392 
3393    Notes:
3394    This function is not normally called by users and is automatically registered with the SNES used by TS.
3395    It is most frequently passed to MatFDColoringSetFunction().
3396 
3397    Level: advanced
3398 
3399 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
3400 @*/
3401 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
3402 {
3403   TS             ts = (TS)ctx;
3404   PetscErrorCode ierr;
3405 
3406   PetscFunctionBegin;
3407   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3408   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
3409   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
3410   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
3411   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
3412   PetscFunctionReturn(0);
3413 }
3414 
3415 #undef __FUNCT__
3416 #define __FUNCT__ "SNESTSFormJacobian"
3417 /*@
3418    SNESTSFormJacobian - Function to evaluate the Jacobian
3419 
3420    Collective on SNES
3421 
3422    Input Parameter:
3423 + snes - nonlinear solver
3424 . U - the current state at which to evaluate the residual
3425 - ctx - user context, must be a TS
3426 
3427    Output Parameter:
3428 + A - the Jacobian
3429 . B - the preconditioning matrix (may be the same as A)
3430 - flag - indicates any structure change in the matrix
3431 
3432    Notes:
3433    This function is not normally called by users and is automatically registered with the SNES used by TS.
3434 
3435    Level: developer
3436 
3437 .seealso: SNESSetJacobian()
3438 @*/
3439 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat *A,Mat *B,MatStructure *flag,void *ctx)
3440 {
3441   TS             ts = (TS)ctx;
3442   PetscErrorCode ierr;
3443 
3444   PetscFunctionBegin;
3445   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3446   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
3447   PetscValidPointer(A,3);
3448   PetscValidHeaderSpecific(*A,MAT_CLASSID,3);
3449   PetscValidPointer(B,4);
3450   PetscValidHeaderSpecific(*B,MAT_CLASSID,4);
3451   PetscValidPointer(flag,5);
3452   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
3453   ierr = (ts->ops->snesjacobian)(snes,U,A,B,flag,ts);CHKERRQ(ierr);
3454   PetscFunctionReturn(0);
3455 }
3456 
3457 #undef __FUNCT__
3458 #define __FUNCT__ "TSComputeRHSFunctionLinear"
3459 /*@C
3460    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems only
3461 
3462    Collective on TS
3463 
3464    Input Arguments:
3465 +  ts - time stepping context
3466 .  t - time at which to evaluate
3467 .  U - state at which to evaluate
3468 -  ctx - context
3469 
3470    Output Arguments:
3471 .  F - right hand side
3472 
3473    Level: intermediate
3474 
3475    Notes:
3476    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
3477    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
3478 
3479 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
3480 @*/
3481 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
3482 {
3483   PetscErrorCode ierr;
3484   Mat            Arhs,Brhs;
3485   MatStructure   flg2;
3486 
3487   PetscFunctionBegin;
3488   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
3489   ierr = TSComputeRHSJacobian(ts,t,U,&Arhs,&Brhs,&flg2);CHKERRQ(ierr);
3490   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
3491   PetscFunctionReturn(0);
3492 }
3493 
3494 #undef __FUNCT__
3495 #define __FUNCT__ "TSComputeRHSJacobianConstant"
3496 /*@C
3497    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
3498 
3499    Collective on TS
3500 
3501    Input Arguments:
3502 +  ts - time stepping context
3503 .  t - time at which to evaluate
3504 .  U - state at which to evaluate
3505 -  ctx - context
3506 
3507    Output Arguments:
3508 +  A - pointer to operator
3509 .  B - pointer to preconditioning matrix
3510 -  flg - matrix structure flag
3511 
3512    Level: intermediate
3513 
3514    Notes:
3515    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
3516 
3517 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
3518 @*/
3519 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat *A,Mat *B,MatStructure *flg,void *ctx)
3520 {
3521   PetscFunctionBegin;
3522   *flg = SAME_PRECONDITIONER;
3523   PetscFunctionReturn(0);
3524 }
3525 
3526 #undef __FUNCT__
3527 #define __FUNCT__ "TSComputeIFunctionLinear"
3528 /*@C
3529    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
3530 
3531    Collective on TS
3532 
3533    Input Arguments:
3534 +  ts - time stepping context
3535 .  t - time at which to evaluate
3536 .  U - state at which to evaluate
3537 .  Udot - time derivative of state vector
3538 -  ctx - context
3539 
3540    Output Arguments:
3541 .  F - left hand side
3542 
3543    Level: intermediate
3544 
3545    Notes:
3546    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
3547    user is required to write their own TSComputeIFunction.
3548    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
3549    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
3550 
3551 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant()
3552 @*/
3553 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
3554 {
3555   PetscErrorCode ierr;
3556   Mat            A,B;
3557   MatStructure   flg2;
3558 
3559   PetscFunctionBegin;
3560   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
3561   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,&A,&B,&flg2,PETSC_TRUE);CHKERRQ(ierr);
3562   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
3563   PetscFunctionReturn(0);
3564 }
3565 
3566 #undef __FUNCT__
3567 #define __FUNCT__ "TSComputeIJacobianConstant"
3568 /*@C
3569    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
3570 
3571    Collective on TS
3572 
3573    Input Arguments:
3574 +  ts - time stepping context
3575 .  t - time at which to evaluate
3576 .  U - state at which to evaluate
3577 .  Udot - time derivative of state vector
3578 .  shift - shift to apply
3579 -  ctx - context
3580 
3581    Output Arguments:
3582 +  A - pointer to operator
3583 .  B - pointer to preconditioning matrix
3584 -  flg - matrix structure flag
3585 
3586    Level: advanced
3587 
3588    Notes:
3589    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
3590 
3591    It is only appropriate for problems of the form
3592 
3593 $     M Udot = F(U,t)
3594 
3595   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
3596   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
3597   an implicit operator of the form
3598 
3599 $    shift*M + J
3600 
3601   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
3602   a copy of M or reassemble it when requested.
3603 
3604 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
3605 @*/
3606 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat *A,Mat *B,MatStructure *flg,void *ctx)
3607 {
3608   PetscErrorCode ierr;
3609 
3610   PetscFunctionBegin;
3611   ierr = MatScale(*A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
3612   ts->ijacobian.shift = shift;
3613   *flg = SAME_PRECONDITIONER;
3614   PetscFunctionReturn(0);
3615 }
3616 
3617 #undef __FUNCT__
3618 #define __FUNCT__ "TSGetEquationType"
3619 /*@
3620    TSGetEquationType - Gets the type of the equation that TS is solving.
3621 
3622    Not Collective
3623 
3624    Input Parameter:
3625 .  ts - the TS context
3626 
3627    Output Parameter:
3628 .  equation_type - see TSEquationType
3629 
3630    Level: beginner
3631 
3632 .keywords: TS, equation type
3633 
3634 .seealso: TSSetEquationType(), TSEquationType
3635 @*/
3636 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
3637 {
3638   PetscFunctionBegin;
3639   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3640   PetscValidPointer(equation_type,2);
3641   *equation_type = ts->equation_type;
3642   PetscFunctionReturn(0);
3643 }
3644 
3645 #undef __FUNCT__
3646 #define __FUNCT__ "TSSetEquationType"
3647 /*@
3648    TSSetEquationType - Sets the type of the equation that TS is solving.
3649 
3650    Not Collective
3651 
3652    Input Parameter:
3653 +  ts - the TS context
3654 .  equation_type - see TSEquationType
3655 
3656    Level: advanced
3657 
3658 .keywords: TS, equation type
3659 
3660 .seealso: TSGetEquationType(), TSEquationType
3661 @*/
3662 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
3663 {
3664   PetscFunctionBegin;
3665   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3666   ts->equation_type = equation_type;
3667   PetscFunctionReturn(0);
3668 }
3669 
3670 #undef __FUNCT__
3671 #define __FUNCT__ "TSGetConvergedReason"
3672 /*@
3673    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
3674 
3675    Not Collective
3676 
3677    Input Parameter:
3678 .  ts - the TS context
3679 
3680    Output Parameter:
3681 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
3682             manual pages for the individual convergence tests for complete lists
3683 
3684    Level: beginner
3685 
3686    Notes:
3687    Can only be called after the call to TSSolve() is complete.
3688 
3689 .keywords: TS, nonlinear, set, convergence, test
3690 
3691 .seealso: TSSetConvergenceTest(), TSConvergedReason
3692 @*/
3693 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
3694 {
3695   PetscFunctionBegin;
3696   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3697   PetscValidPointer(reason,2);
3698   *reason = ts->reason;
3699   PetscFunctionReturn(0);
3700 }
3701 
3702 #undef __FUNCT__
3703 #define __FUNCT__ "TSSetConvergedReason"
3704 /*@
3705    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
3706 
3707    Not Collective
3708 
3709    Input Parameter:
3710 +  ts - the TS context
3711 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
3712             manual pages for the individual convergence tests for complete lists
3713 
3714    Level: advanced
3715 
3716    Notes:
3717    Can only be called during TSSolve() is active.
3718 
3719 .keywords: TS, nonlinear, set, convergence, test
3720 
3721 .seealso: TSConvergedReason
3722 @*/
3723 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
3724 {
3725   PetscFunctionBegin;
3726   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3727   ts->reason = reason;
3728   PetscFunctionReturn(0);
3729 }
3730 
3731 #undef __FUNCT__
3732 #define __FUNCT__ "TSGetSolveTime"
3733 /*@
3734    TSGetSolveTime - Gets the time after a call to TSSolve()
3735 
3736    Not Collective
3737 
3738    Input Parameter:
3739 .  ts - the TS context
3740 
3741    Output Parameter:
3742 .  ftime - the final time. This time should correspond to the final time set with TSSetDuration()
3743 
3744    Level: beginner
3745 
3746    Notes:
3747    Can only be called after the call to TSSolve() is complete.
3748 
3749 .keywords: TS, nonlinear, set, convergence, test
3750 
3751 .seealso: TSSetConvergenceTest(), TSConvergedReason
3752 @*/
3753 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
3754 {
3755   PetscFunctionBegin;
3756   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3757   PetscValidPointer(ftime,2);
3758   *ftime = ts->solvetime;
3759   PetscFunctionReturn(0);
3760 }
3761 
3762 #undef __FUNCT__
3763 #define __FUNCT__ "TSGetSNESIterations"
3764 /*@
3765    TSGetSNESIterations - Gets the total number of nonlinear iterations
3766    used by the time integrator.
3767 
3768    Not Collective
3769 
3770    Input Parameter:
3771 .  ts - TS context
3772 
3773    Output Parameter:
3774 .  nits - number of nonlinear iterations
3775 
3776    Notes:
3777    This counter is reset to zero for each successive call to TSSolve().
3778 
3779    Level: intermediate
3780 
3781 .keywords: TS, get, number, nonlinear, iterations
3782 
3783 .seealso:  TSGetKSPIterations()
3784 @*/
3785 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
3786 {
3787   PetscFunctionBegin;
3788   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3789   PetscValidIntPointer(nits,2);
3790   *nits = ts->snes_its;
3791   PetscFunctionReturn(0);
3792 }
3793 
3794 #undef __FUNCT__
3795 #define __FUNCT__ "TSGetKSPIterations"
3796 /*@
3797    TSGetKSPIterations - Gets the total number of linear iterations
3798    used by the time integrator.
3799 
3800    Not Collective
3801 
3802    Input Parameter:
3803 .  ts - TS context
3804 
3805    Output Parameter:
3806 .  lits - number of linear iterations
3807 
3808    Notes:
3809    This counter is reset to zero for each successive call to TSSolve().
3810 
3811    Level: intermediate
3812 
3813 .keywords: TS, get, number, linear, iterations
3814 
3815 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
3816 @*/
3817 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
3818 {
3819   PetscFunctionBegin;
3820   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3821   PetscValidIntPointer(lits,2);
3822   *lits = ts->ksp_its;
3823   PetscFunctionReturn(0);
3824 }
3825 
3826 #undef __FUNCT__
3827 #define __FUNCT__ "TSGetStepRejections"
3828 /*@
3829    TSGetStepRejections - Gets the total number of rejected steps.
3830 
3831    Not Collective
3832 
3833    Input Parameter:
3834 .  ts - TS context
3835 
3836    Output Parameter:
3837 .  rejects - number of steps rejected
3838 
3839    Notes:
3840    This counter is reset to zero for each successive call to TSSolve().
3841 
3842    Level: intermediate
3843 
3844 .keywords: TS, get, number
3845 
3846 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
3847 @*/
3848 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
3849 {
3850   PetscFunctionBegin;
3851   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3852   PetscValidIntPointer(rejects,2);
3853   *rejects = ts->reject;
3854   PetscFunctionReturn(0);
3855 }
3856 
3857 #undef __FUNCT__
3858 #define __FUNCT__ "TSGetSNESFailures"
3859 /*@
3860    TSGetSNESFailures - Gets the total number of failed SNES solves
3861 
3862    Not Collective
3863 
3864    Input Parameter:
3865 .  ts - TS context
3866 
3867    Output Parameter:
3868 .  fails - number of failed nonlinear solves
3869 
3870    Notes:
3871    This counter is reset to zero for each successive call to TSSolve().
3872 
3873    Level: intermediate
3874 
3875 .keywords: TS, get, number
3876 
3877 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
3878 @*/
3879 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
3880 {
3881   PetscFunctionBegin;
3882   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3883   PetscValidIntPointer(fails,2);
3884   *fails = ts->num_snes_failures;
3885   PetscFunctionReturn(0);
3886 }
3887 
3888 #undef __FUNCT__
3889 #define __FUNCT__ "TSSetMaxStepRejections"
3890 /*@
3891    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
3892 
3893    Not Collective
3894 
3895    Input Parameter:
3896 +  ts - TS context
3897 -  rejects - maximum number of rejected steps, pass -1 for unlimited
3898 
3899    Notes:
3900    The counter is reset to zero for each step
3901 
3902    Options Database Key:
3903  .  -ts_max_reject - Maximum number of step rejections before a step fails
3904 
3905    Level: intermediate
3906 
3907 .keywords: TS, set, maximum, number
3908 
3909 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
3910 @*/
3911 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
3912 {
3913   PetscFunctionBegin;
3914   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3915   ts->max_reject = rejects;
3916   PetscFunctionReturn(0);
3917 }
3918 
3919 #undef __FUNCT__
3920 #define __FUNCT__ "TSSetMaxSNESFailures"
3921 /*@
3922    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
3923 
3924    Not Collective
3925 
3926    Input Parameter:
3927 +  ts - TS context
3928 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
3929 
3930    Notes:
3931    The counter is reset to zero for each successive call to TSSolve().
3932 
3933    Options Database Key:
3934  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
3935 
3936    Level: intermediate
3937 
3938 .keywords: TS, set, maximum, number
3939 
3940 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
3941 @*/
3942 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
3943 {
3944   PetscFunctionBegin;
3945   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3946   ts->max_snes_failures = fails;
3947   PetscFunctionReturn(0);
3948 }
3949 
3950 #undef __FUNCT__
3951 #define __FUNCT__ "TSSetErrorIfStepFails()"
3952 /*@
3953    TSSetErrorIfStepFails - Error if no step succeeds
3954 
3955    Not Collective
3956 
3957    Input Parameter:
3958 +  ts - TS context
3959 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
3960 
3961    Options Database Key:
3962  .  -ts_error_if_step_fails - Error if no step succeeds
3963 
3964    Level: intermediate
3965 
3966 .keywords: TS, set, error
3967 
3968 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
3969 @*/
3970 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
3971 {
3972   PetscFunctionBegin;
3973   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3974   ts->errorifstepfailed = err;
3975   PetscFunctionReturn(0);
3976 }
3977 
3978 #undef __FUNCT__
3979 #define __FUNCT__ "TSMonitorSolutionBinary"
3980 /*@C
3981    TSMonitorSolutionBinary - Monitors progress of the TS solvers by VecView() for the solution at each timestep. Normally the viewer is a binary file
3982 
3983    Collective on TS
3984 
3985    Input Parameters:
3986 +  ts - the TS context
3987 .  step - current time-step
3988 .  ptime - current time
3989 .  u - current state
3990 -  viewer - binary viewer
3991 
3992    Level: intermediate
3993 
3994 .keywords: TS,  vector, monitor, view
3995 
3996 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3997 @*/
3998 PetscErrorCode  TSMonitorSolutionBinary(TS ts,PetscInt step,PetscReal ptime,Vec u,void *viewer)
3999 {
4000   PetscErrorCode ierr;
4001   PetscViewer    v = (PetscViewer)viewer;
4002 
4003   PetscFunctionBegin;
4004   ierr = VecView(u,v);CHKERRQ(ierr);
4005   PetscFunctionReturn(0);
4006 }
4007 
4008 #undef __FUNCT__
4009 #define __FUNCT__ "TSMonitorSolutionVTK"
4010 /*@C
4011    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
4012 
4013    Collective on TS
4014 
4015    Input Parameters:
4016 +  ts - the TS context
4017 .  step - current time-step
4018 .  ptime - current time
4019 .  u - current state
4020 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
4021 
4022    Level: intermediate
4023 
4024    Notes:
4025    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.
4026    These are named according to the file name template.
4027 
4028    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
4029 
4030 .keywords: TS,  vector, monitor, view
4031 
4032 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4033 @*/
4034 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
4035 {
4036   PetscErrorCode ierr;
4037   char           filename[PETSC_MAX_PATH_LEN];
4038   PetscViewer    viewer;
4039 
4040   PetscFunctionBegin;
4041   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
4042   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
4043   ierr = VecView(u,viewer);CHKERRQ(ierr);
4044   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4045   PetscFunctionReturn(0);
4046 }
4047 
4048 #undef __FUNCT__
4049 #define __FUNCT__ "TSMonitorSolutionVTKDestroy"
4050 /*@C
4051    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
4052 
4053    Collective on TS
4054 
4055    Input Parameters:
4056 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
4057 
4058    Level: intermediate
4059 
4060    Note:
4061    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
4062 
4063 .keywords: TS,  vector, monitor, view
4064 
4065 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
4066 @*/
4067 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
4068 {
4069   PetscErrorCode ierr;
4070 
4071   PetscFunctionBegin;
4072   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
4073   PetscFunctionReturn(0);
4074 }
4075 
4076 #undef __FUNCT__
4077 #define __FUNCT__ "TSGetAdapt"
4078 /*@
4079    TSGetAdapt - Get the adaptive controller context for the current method
4080 
4081    Collective on TS if controller has not been created yet
4082 
4083    Input Arguments:
4084 .  ts - time stepping context
4085 
4086    Output Arguments:
4087 .  adapt - adaptive controller
4088 
4089    Level: intermediate
4090 
4091 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
4092 @*/
4093 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
4094 {
4095   PetscErrorCode ierr;
4096 
4097   PetscFunctionBegin;
4098   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4099   PetscValidPointer(adapt,2);
4100   if (!ts->adapt) {
4101     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
4102     ierr = PetscLogObjectParent(ts,ts->adapt);CHKERRQ(ierr);
4103     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
4104   }
4105   *adapt = ts->adapt;
4106   PetscFunctionReturn(0);
4107 }
4108 
4109 #undef __FUNCT__
4110 #define __FUNCT__ "TSSetTolerances"
4111 /*@
4112    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
4113 
4114    Logically Collective
4115 
4116    Input Arguments:
4117 +  ts - time integration context
4118 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
4119 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
4120 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
4121 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
4122 
4123    Level: beginner
4124 
4125 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
4126 @*/
4127 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
4128 {
4129   PetscErrorCode ierr;
4130 
4131   PetscFunctionBegin;
4132   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
4133   if (vatol) {
4134     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
4135     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
4136 
4137     ts->vatol = vatol;
4138   }
4139   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
4140   if (vrtol) {
4141     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
4142     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
4143 
4144     ts->vrtol = vrtol;
4145   }
4146   PetscFunctionReturn(0);
4147 }
4148 
4149 #undef __FUNCT__
4150 #define __FUNCT__ "TSGetTolerances"
4151 /*@
4152    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
4153 
4154    Logically Collective
4155 
4156    Input Arguments:
4157 .  ts - time integration context
4158 
4159    Output Arguments:
4160 +  atol - scalar absolute tolerances, NULL to ignore
4161 .  vatol - vector of absolute tolerances, NULL to ignore
4162 .  rtol - scalar relative tolerances, NULL to ignore
4163 -  vrtol - vector of relative tolerances, NULL to ignore
4164 
4165    Level: beginner
4166 
4167 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
4168 @*/
4169 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
4170 {
4171   PetscFunctionBegin;
4172   if (atol)  *atol  = ts->atol;
4173   if (vatol) *vatol = ts->vatol;
4174   if (rtol)  *rtol  = ts->rtol;
4175   if (vrtol) *vrtol = ts->vrtol;
4176   PetscFunctionReturn(0);
4177 }
4178 
4179 #undef __FUNCT__
4180 #define __FUNCT__ "TSErrorNormWRMS"
4181 /*@
4182    TSErrorNormWRMS - compute a weighted norm of the difference between a vector and the current state
4183 
4184    Collective on TS
4185 
4186    Input Arguments:
4187 +  ts - time stepping context
4188 -  Y - state vector to be compared to ts->vec_sol
4189 
4190    Output Arguments:
4191 .  norm - weighted norm, a value of 1.0 is considered small
4192 
4193    Level: developer
4194 
4195 .seealso: TSSetTolerances()
4196 @*/
4197 PetscErrorCode TSErrorNormWRMS(TS ts,Vec Y,PetscReal *norm)
4198 {
4199   PetscErrorCode    ierr;
4200   PetscInt          i,n,N;
4201   const PetscScalar *u,*y;
4202   Vec               U;
4203   PetscReal         sum,gsum;
4204 
4205   PetscFunctionBegin;
4206   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4207   PetscValidHeaderSpecific(Y,VEC_CLASSID,2);
4208   PetscValidPointer(norm,3);
4209   U = ts->vec_sol;
4210   PetscCheckSameTypeAndComm(U,1,Y,2);
4211   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"Y cannot be the TS solution vector");
4212 
4213   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
4214   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
4215   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
4216   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
4217   sum  = 0.;
4218   if (ts->vatol && ts->vrtol) {
4219     const PetscScalar *atol,*rtol;
4220     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4221     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4222     for (i=0; i<n; i++) {
4223       PetscReal tol = PetscRealPart(atol[i]) + PetscRealPart(rtol[i]) * 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     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4228   } else if (ts->vatol) {       /* vector atol, scalar rtol */
4229     const PetscScalar *atol;
4230     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4231     for (i=0; i<n; i++) {
4232       PetscReal tol = PetscRealPart(atol[i]) + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4233       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4234     }
4235     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4236   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
4237     const PetscScalar *rtol;
4238     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4239     for (i=0; i<n; i++) {
4240       PetscReal tol = ts->atol + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4241       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4242     }
4243     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4244   } else {                      /* scalar atol, scalar rtol */
4245     for (i=0; i<n; i++) {
4246       PetscReal tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4247       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4248     }
4249   }
4250   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
4251   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
4252 
4253   ierr  = MPI_Allreduce(&sum,&gsum,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
4254   *norm = PetscSqrtReal(gsum / N);
4255   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
4256   PetscFunctionReturn(0);
4257 }
4258 
4259 #undef __FUNCT__
4260 #define __FUNCT__ "TSSetCFLTimeLocal"
4261 /*@
4262    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
4263 
4264    Logically Collective on TS
4265 
4266    Input Arguments:
4267 +  ts - time stepping context
4268 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
4269 
4270    Note:
4271    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
4272 
4273    Level: intermediate
4274 
4275 .seealso: TSGetCFLTime(), TSADAPTCFL
4276 @*/
4277 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
4278 {
4279   PetscFunctionBegin;
4280   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4281   ts->cfltime_local = cfltime;
4282   ts->cfltime       = -1.;
4283   PetscFunctionReturn(0);
4284 }
4285 
4286 #undef __FUNCT__
4287 #define __FUNCT__ "TSGetCFLTime"
4288 /*@
4289    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
4290 
4291    Collective on TS
4292 
4293    Input Arguments:
4294 .  ts - time stepping context
4295 
4296    Output Arguments:
4297 .  cfltime - maximum stable time step for forward Euler
4298 
4299    Level: advanced
4300 
4301 .seealso: TSSetCFLTimeLocal()
4302 @*/
4303 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
4304 {
4305   PetscErrorCode ierr;
4306 
4307   PetscFunctionBegin;
4308   if (ts->cfltime < 0) {
4309     ierr = MPI_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
4310   }
4311   *cfltime = ts->cfltime;
4312   PetscFunctionReturn(0);
4313 }
4314 
4315 #undef __FUNCT__
4316 #define __FUNCT__ "TSVISetVariableBounds"
4317 /*@
4318    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
4319 
4320    Input Parameters:
4321 .  ts   - the TS context.
4322 .  xl   - lower bound.
4323 .  xu   - upper bound.
4324 
4325    Notes:
4326    If this routine is not called then the lower and upper bounds are set to
4327    SNES_VI_NINF and SNES_VI_INF respectively during SNESSetUp().
4328 
4329    Level: advanced
4330 
4331 @*/
4332 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
4333 {
4334   PetscErrorCode ierr;
4335   SNES           snes;
4336 
4337   PetscFunctionBegin;
4338   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4339   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
4340   PetscFunctionReturn(0);
4341 }
4342 
4343 #if defined(PETSC_HAVE_MATLAB_ENGINE)
4344 #include <mex.h>
4345 
4346 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
4347 
4348 #undef __FUNCT__
4349 #define __FUNCT__ "TSComputeFunction_Matlab"
4350 /*
4351    TSComputeFunction_Matlab - Calls the function that has been set with
4352                          TSSetFunctionMatlab().
4353 
4354    Collective on TS
4355 
4356    Input Parameters:
4357 +  snes - the TS context
4358 -  u - input vector
4359 
4360    Output Parameter:
4361 .  y - function vector, as set by TSSetFunction()
4362 
4363    Notes:
4364    TSComputeFunction() is typically used within nonlinear solvers
4365    implementations, so most users would not generally call this routine
4366    themselves.
4367 
4368    Level: developer
4369 
4370 .keywords: TS, nonlinear, compute, function
4371 
4372 .seealso: TSSetFunction(), TSGetFunction()
4373 */
4374 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
4375 {
4376   PetscErrorCode  ierr;
4377   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4378   int             nlhs  = 1,nrhs = 7;
4379   mxArray         *plhs[1],*prhs[7];
4380   long long int   lx = 0,lxdot = 0,ly = 0,ls = 0;
4381 
4382   PetscFunctionBegin;
4383   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
4384   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
4385   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
4386   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
4387   PetscCheckSameComm(snes,1,u,3);
4388   PetscCheckSameComm(snes,1,y,5);
4389 
4390   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
4391   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4392   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
4393   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
4394 
4395   prhs[0] =  mxCreateDoubleScalar((double)ls);
4396   prhs[1] =  mxCreateDoubleScalar(time);
4397   prhs[2] =  mxCreateDoubleScalar((double)lx);
4398   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
4399   prhs[4] =  mxCreateDoubleScalar((double)ly);
4400   prhs[5] =  mxCreateString(sctx->funcname);
4401   prhs[6] =  sctx->ctx;
4402   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
4403   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4404   mxDestroyArray(prhs[0]);
4405   mxDestroyArray(prhs[1]);
4406   mxDestroyArray(prhs[2]);
4407   mxDestroyArray(prhs[3]);
4408   mxDestroyArray(prhs[4]);
4409   mxDestroyArray(prhs[5]);
4410   mxDestroyArray(plhs[0]);
4411   PetscFunctionReturn(0);
4412 }
4413 
4414 
4415 #undef __FUNCT__
4416 #define __FUNCT__ "TSSetFunctionMatlab"
4417 /*
4418    TSSetFunctionMatlab - Sets the function evaluation routine and function
4419    vector for use by the TS routines in solving ODEs
4420    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
4421 
4422    Logically Collective on TS
4423 
4424    Input Parameters:
4425 +  ts - the TS context
4426 -  func - function evaluation routine
4427 
4428    Calling sequence of func:
4429 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
4430 
4431    Level: beginner
4432 
4433 .keywords: TS, nonlinear, set, function
4434 
4435 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4436 */
4437 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
4438 {
4439   PetscErrorCode  ierr;
4440   TSMatlabContext *sctx;
4441 
4442   PetscFunctionBegin;
4443   /* currently sctx is memory bleed */
4444   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
4445   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
4446   /*
4447      This should work, but it doesn't
4448   sctx->ctx = ctx;
4449   mexMakeArrayPersistent(sctx->ctx);
4450   */
4451   sctx->ctx = mxDuplicateArray(ctx);
4452 
4453   ierr = TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
4454   PetscFunctionReturn(0);
4455 }
4456 
4457 #undef __FUNCT__
4458 #define __FUNCT__ "TSComputeJacobian_Matlab"
4459 /*
4460    TSComputeJacobian_Matlab - Calls the function that has been set with
4461                          TSSetJacobianMatlab().
4462 
4463    Collective on TS
4464 
4465    Input Parameters:
4466 +  ts - the TS context
4467 .  u - input vector
4468 .  A, B - the matrices
4469 -  ctx - user context
4470 
4471    Output Parameter:
4472 .  flag - structure of the matrix
4473 
4474    Level: developer
4475 
4476 .keywords: TS, nonlinear, compute, function
4477 
4478 .seealso: TSSetFunction(), TSGetFunction()
4479 @*/
4480 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat *A,Mat *B,MatStructure *flag, void *ctx)
4481 {
4482   PetscErrorCode  ierr;
4483   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4484   int             nlhs  = 2,nrhs = 9;
4485   mxArray         *plhs[2],*prhs[9];
4486   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
4487 
4488   PetscFunctionBegin;
4489   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4490   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
4491 
4492   /* call Matlab function in ctx with arguments u and y */
4493 
4494   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
4495   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4496   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
4497   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
4498   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
4499 
4500   prhs[0] =  mxCreateDoubleScalar((double)ls);
4501   prhs[1] =  mxCreateDoubleScalar((double)time);
4502   prhs[2] =  mxCreateDoubleScalar((double)lx);
4503   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
4504   prhs[4] =  mxCreateDoubleScalar((double)shift);
4505   prhs[5] =  mxCreateDoubleScalar((double)lA);
4506   prhs[6] =  mxCreateDoubleScalar((double)lB);
4507   prhs[7] =  mxCreateString(sctx->funcname);
4508   prhs[8] =  sctx->ctx;
4509   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
4510   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4511   *flag   =  (MatStructure) mxGetScalar(plhs[1]);CHKERRQ(ierr);
4512   mxDestroyArray(prhs[0]);
4513   mxDestroyArray(prhs[1]);
4514   mxDestroyArray(prhs[2]);
4515   mxDestroyArray(prhs[3]);
4516   mxDestroyArray(prhs[4]);
4517   mxDestroyArray(prhs[5]);
4518   mxDestroyArray(prhs[6]);
4519   mxDestroyArray(prhs[7]);
4520   mxDestroyArray(plhs[0]);
4521   mxDestroyArray(plhs[1]);
4522   PetscFunctionReturn(0);
4523 }
4524 
4525 
4526 #undef __FUNCT__
4527 #define __FUNCT__ "TSSetJacobianMatlab"
4528 /*
4529    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
4530    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
4531 
4532    Logically Collective on TS
4533 
4534    Input Parameters:
4535 +  ts - the TS context
4536 .  A,B - Jacobian matrices
4537 .  func - function evaluation routine
4538 -  ctx - user context
4539 
4540    Calling sequence of func:
4541 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
4542 
4543 
4544    Level: developer
4545 
4546 .keywords: TS, nonlinear, set, function
4547 
4548 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4549 */
4550 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
4551 {
4552   PetscErrorCode  ierr;
4553   TSMatlabContext *sctx;
4554 
4555   PetscFunctionBegin;
4556   /* currently sctx is memory bleed */
4557   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
4558   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
4559   /*
4560      This should work, but it doesn't
4561   sctx->ctx = ctx;
4562   mexMakeArrayPersistent(sctx->ctx);
4563   */
4564   sctx->ctx = mxDuplicateArray(ctx);
4565 
4566   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
4567   PetscFunctionReturn(0);
4568 }
4569 
4570 #undef __FUNCT__
4571 #define __FUNCT__ "TSMonitor_Matlab"
4572 /*
4573    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
4574 
4575    Collective on TS
4576 
4577 .seealso: TSSetFunction(), TSGetFunction()
4578 @*/
4579 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
4580 {
4581   PetscErrorCode  ierr;
4582   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4583   int             nlhs  = 1,nrhs = 6;
4584   mxArray         *plhs[1],*prhs[6];
4585   long long int   lx = 0,ls = 0;
4586 
4587   PetscFunctionBegin;
4588   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4589   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4590 
4591   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
4592   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4593 
4594   prhs[0] =  mxCreateDoubleScalar((double)ls);
4595   prhs[1] =  mxCreateDoubleScalar((double)it);
4596   prhs[2] =  mxCreateDoubleScalar((double)time);
4597   prhs[3] =  mxCreateDoubleScalar((double)lx);
4598   prhs[4] =  mxCreateString(sctx->funcname);
4599   prhs[5] =  sctx->ctx;
4600   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
4601   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4602   mxDestroyArray(prhs[0]);
4603   mxDestroyArray(prhs[1]);
4604   mxDestroyArray(prhs[2]);
4605   mxDestroyArray(prhs[3]);
4606   mxDestroyArray(prhs[4]);
4607   mxDestroyArray(plhs[0]);
4608   PetscFunctionReturn(0);
4609 }
4610 
4611 
4612 #undef __FUNCT__
4613 #define __FUNCT__ "TSMonitorSetMatlab"
4614 /*
4615    TSMonitorSetMatlab - Sets the monitor function from Matlab
4616 
4617    Level: developer
4618 
4619 .keywords: TS, nonlinear, set, function
4620 
4621 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4622 */
4623 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
4624 {
4625   PetscErrorCode  ierr;
4626   TSMatlabContext *sctx;
4627 
4628   PetscFunctionBegin;
4629   /* currently sctx is memory bleed */
4630   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
4631   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
4632   /*
4633      This should work, but it doesn't
4634   sctx->ctx = ctx;
4635   mexMakeArrayPersistent(sctx->ctx);
4636   */
4637   sctx->ctx = mxDuplicateArray(ctx);
4638 
4639   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);CHKERRQ(ierr);
4640   PetscFunctionReturn(0);
4641 }
4642 #endif
4643 
4644 
4645 
4646 #undef __FUNCT__
4647 #define __FUNCT__ "TSMonitorLGSolution"
4648 /*@C
4649    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
4650        in a time based line graph
4651 
4652    Collective on TS
4653 
4654    Input Parameters:
4655 +  ts - the TS context
4656 .  step - current time-step
4657 .  ptime - current time
4658 -  lg - a line graph object
4659 
4660    Level: intermediate
4661 
4662     Notes: each process in a parallel run displays its component solutions in a separate window
4663 
4664 .keywords: TS,  vector, monitor, view
4665 
4666 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4667 @*/
4668 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4669 {
4670   PetscErrorCode    ierr;
4671   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
4672   const PetscScalar *yy;
4673   PetscInt          dim;
4674 
4675   PetscFunctionBegin;
4676   if (!step) {
4677     PetscDrawAxis axis;
4678     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4679     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
4680     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
4681     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
4682     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4683   }
4684   ierr = VecGetArrayRead(u,&yy);CHKERRQ(ierr);
4685 #if defined(PETSC_USE_COMPLEX)
4686   {
4687     PetscReal *yreal;
4688     PetscInt  i,n;
4689     ierr = VecGetLocalSize(u,&n);CHKERRQ(ierr);
4690     ierr = PetscMalloc(n*sizeof(PetscReal),&yreal);CHKERRQ(ierr);
4691     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
4692     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
4693     ierr = PetscFree(yreal);CHKERRQ(ierr);
4694   }
4695 #else
4696   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
4697 #endif
4698   ierr = VecRestoreArrayRead(u,&yy);CHKERRQ(ierr);
4699   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4700     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4701   }
4702   PetscFunctionReturn(0);
4703 }
4704 
4705 #undef __FUNCT__
4706 #define __FUNCT__ "TSMonitorLGError"
4707 /*@C
4708    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the solution vector
4709        in a time based line graph
4710 
4711    Collective on TS
4712 
4713    Input Parameters:
4714 +  ts - the TS context
4715 .  step - current time-step
4716 .  ptime - current time
4717 -  lg - a line graph object
4718 
4719    Level: intermediate
4720 
4721    Notes:
4722    Only for sequential solves.
4723 
4724    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
4725 
4726    Options Database Keys:
4727 .  -ts_monitor_lg_error - create a graphical monitor of error history
4728 
4729 .keywords: TS,  vector, monitor, view
4730 
4731 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4732 @*/
4733 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4734 {
4735   PetscErrorCode    ierr;
4736   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
4737   const PetscScalar *yy;
4738   Vec               y;
4739   PetscInt          dim;
4740 
4741   PetscFunctionBegin;
4742   if (!step) {
4743     PetscDrawAxis axis;
4744     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4745     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Solution");CHKERRQ(ierr);
4746     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
4747     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
4748     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4749   }
4750   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
4751   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
4752   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
4753   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
4754 #if defined(PETSC_USE_COMPLEX)
4755   {
4756     PetscReal *yreal;
4757     PetscInt  i,n;
4758     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
4759     ierr = PetscMalloc(n*sizeof(PetscReal),&yreal);CHKERRQ(ierr);
4760     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
4761     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
4762     ierr = PetscFree(yreal);CHKERRQ(ierr);
4763   }
4764 #else
4765   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
4766 #endif
4767   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
4768   ierr = VecDestroy(&y);CHKERRQ(ierr);
4769   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4770     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4771   }
4772   PetscFunctionReturn(0);
4773 }
4774 
4775 #undef __FUNCT__
4776 #define __FUNCT__ "TSMonitorLGSNESIterations"
4777 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
4778 {
4779   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4780   PetscReal      x   = ptime,y;
4781   PetscErrorCode ierr;
4782   PetscInt       its;
4783 
4784   PetscFunctionBegin;
4785   if (!n) {
4786     PetscDrawAxis axis;
4787 
4788     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4789     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
4790     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4791 
4792     ctx->snes_its = 0;
4793   }
4794   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
4795   y    = its - ctx->snes_its;
4796   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4797   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
4798     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4799   }
4800   ctx->snes_its = its;
4801   PetscFunctionReturn(0);
4802 }
4803 
4804 #undef __FUNCT__
4805 #define __FUNCT__ "TSMonitorLGKSPIterations"
4806 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
4807 {
4808   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4809   PetscReal      x   = ptime,y;
4810   PetscErrorCode ierr;
4811   PetscInt       its;
4812 
4813   PetscFunctionBegin;
4814   if (!n) {
4815     PetscDrawAxis axis;
4816 
4817     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4818     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
4819     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4820 
4821     ctx->ksp_its = 0;
4822   }
4823   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
4824   y    = its - ctx->ksp_its;
4825   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4826   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
4827     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4828   }
4829   ctx->ksp_its = its;
4830   PetscFunctionReturn(0);
4831 }
4832 
4833 #undef __FUNCT__
4834 #define __FUNCT__ "TSComputeLinearStability"
4835 /*@
4836    TSComputeLinearStability - computes the linear stability function at a point
4837 
4838    Collective on TS and Vec
4839 
4840    Input Parameters:
4841 +  ts - the TS context
4842 -  xr,xi - real and imaginary part of input arguments
4843 
4844    Output Parameters:
4845 .  yr,yi - real and imaginary part of function value
4846 
4847    Level: developer
4848 
4849 .keywords: TS, compute
4850 
4851 .seealso: TSSetRHSFunction(), TSComputeIFunction()
4852 @*/
4853 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
4854 {
4855   PetscErrorCode ierr;
4856 
4857   PetscFunctionBegin;
4858   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4859   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
4860   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
4861   PetscFunctionReturn(0);
4862 }
4863