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