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