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