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