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