xref: /petsc/src/ts/interface/ts.c (revision 6fd0887f21ef0698638b8674df23fd0a0afaba0b)
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   }
1963   ts->setupcalled = PETSC_FALSE;
1964   PetscFunctionReturn(0);
1965 }
1966 
1967 #undef __FUNCT__
1968 #define __FUNCT__ "TSDestroy"
1969 /*@
1970    TSDestroy - Destroys the timestepper context that was created
1971    with TSCreate().
1972 
1973    Collective on TS
1974 
1975    Input Parameter:
1976 .  ts - the TS context obtained from TSCreate()
1977 
1978    Level: beginner
1979 
1980 .keywords: TS, timestepper, destroy
1981 
1982 .seealso: TSCreate(), TSSetUp(), TSSolve()
1983 @*/
1984 PetscErrorCode  TSDestroy(TS *ts)
1985 {
1986   PetscErrorCode ierr;
1987 
1988   PetscFunctionBegin;
1989   if (!*ts) PetscFunctionReturn(0);
1990   PetscValidHeaderSpecific((*ts),TS_CLASSID,1);
1991   if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; PetscFunctionReturn(0);}
1992 
1993   ierr = TSReset((*ts));CHKERRQ(ierr);
1994 
1995   /* if memory was published with SAWs then destroy it */
1996   ierr = PetscObjectSAWsViewOff((PetscObject)*ts);CHKERRQ(ierr);
1997   if ((*ts)->ops->destroy) {ierr = (*(*ts)->ops->destroy)((*ts));CHKERRQ(ierr);}
1998 
1999   ierr = TSAdaptDestroy(&(*ts)->adapt);CHKERRQ(ierr);
2000   if ((*ts)->event) {
2001     ierr = TSEventMonitorDestroy(&(*ts)->event);CHKERRQ(ierr);
2002   }
2003   ierr = SNESDestroy(&(*ts)->snes);CHKERRQ(ierr);
2004   ierr = DMDestroy(&(*ts)->dm);CHKERRQ(ierr);
2005   ierr = TSMonitorCancel((*ts));CHKERRQ(ierr);
2006 
2007   ierr = PetscHeaderDestroy(ts);CHKERRQ(ierr);
2008   PetscFunctionReturn(0);
2009 }
2010 
2011 #undef __FUNCT__
2012 #define __FUNCT__ "TSGetSNES"
2013 /*@
2014    TSGetSNES - Returns the SNES (nonlinear solver) associated with
2015    a TS (timestepper) context. Valid only for nonlinear problems.
2016 
2017    Not Collective, but SNES is parallel if TS is parallel
2018 
2019    Input Parameter:
2020 .  ts - the TS context obtained from TSCreate()
2021 
2022    Output Parameter:
2023 .  snes - the nonlinear solver context
2024 
2025    Notes:
2026    The user can then directly manipulate the SNES context to set various
2027    options, etc.  Likewise, the user can then extract and manipulate the
2028    KSP, KSP, and PC contexts as well.
2029 
2030    TSGetSNES() does not work for integrators that do not use SNES; in
2031    this case TSGetSNES() returns NULL in snes.
2032 
2033    Level: beginner
2034 
2035 .keywords: timestep, get, SNES
2036 @*/
2037 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
2038 {
2039   PetscErrorCode ierr;
2040 
2041   PetscFunctionBegin;
2042   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2043   PetscValidPointer(snes,2);
2044   if (!ts->snes) {
2045     ierr = SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes);CHKERRQ(ierr);
2046     ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2047     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->snes);CHKERRQ(ierr);
2048     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);CHKERRQ(ierr);
2049     if (ts->dm) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
2050     if (ts->problem_type == TS_LINEAR) {
2051       ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr);
2052     }
2053   }
2054   *snes = ts->snes;
2055   PetscFunctionReturn(0);
2056 }
2057 
2058 #undef __FUNCT__
2059 #define __FUNCT__ "TSSetSNES"
2060 /*@
2061    TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
2062 
2063    Collective
2064 
2065    Input Parameter:
2066 +  ts - the TS context obtained from TSCreate()
2067 -  snes - the nonlinear solver context
2068 
2069    Notes:
2070    Most users should have the TS created by calling TSGetSNES()
2071 
2072    Level: developer
2073 
2074 .keywords: timestep, set, SNES
2075 @*/
2076 PetscErrorCode TSSetSNES(TS ts,SNES snes)
2077 {
2078   PetscErrorCode ierr;
2079   PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*);
2080 
2081   PetscFunctionBegin;
2082   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2083   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
2084   ierr = PetscObjectReference((PetscObject)snes);CHKERRQ(ierr);
2085   ierr = SNESDestroy(&ts->snes);CHKERRQ(ierr);
2086 
2087   ts->snes = snes;
2088 
2089   ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2090   ierr = SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL);CHKERRQ(ierr);
2091   if (func == SNESTSFormJacobian) {
2092     ierr = SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts);CHKERRQ(ierr);
2093   }
2094   PetscFunctionReturn(0);
2095 }
2096 
2097 #undef __FUNCT__
2098 #define __FUNCT__ "TSGetKSP"
2099 /*@
2100    TSGetKSP - Returns the KSP (linear solver) associated with
2101    a TS (timestepper) context.
2102 
2103    Not Collective, but KSP is parallel if TS is parallel
2104 
2105    Input Parameter:
2106 .  ts - the TS context obtained from TSCreate()
2107 
2108    Output Parameter:
2109 .  ksp - the nonlinear solver context
2110 
2111    Notes:
2112    The user can then directly manipulate the KSP context to set various
2113    options, etc.  Likewise, the user can then extract and manipulate the
2114    KSP and PC contexts as well.
2115 
2116    TSGetKSP() does not work for integrators that do not use KSP;
2117    in this case TSGetKSP() returns NULL in ksp.
2118 
2119    Level: beginner
2120 
2121 .keywords: timestep, get, KSP
2122 @*/
2123 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
2124 {
2125   PetscErrorCode ierr;
2126   SNES           snes;
2127 
2128   PetscFunctionBegin;
2129   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2130   PetscValidPointer(ksp,2);
2131   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
2132   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
2133   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2134   ierr = SNESGetKSP(snes,ksp);CHKERRQ(ierr);
2135   PetscFunctionReturn(0);
2136 }
2137 
2138 /* ----------- Routines to set solver parameters ---------- */
2139 
2140 #undef __FUNCT__
2141 #define __FUNCT__ "TSGetDuration"
2142 /*@
2143    TSGetDuration - Gets the maximum number of timesteps to use and
2144    maximum time for iteration.
2145 
2146    Not Collective
2147 
2148    Input Parameters:
2149 +  ts       - the TS context obtained from TSCreate()
2150 .  maxsteps - maximum number of iterations to use, or NULL
2151 -  maxtime  - final time to iterate to, or NULL
2152 
2153    Level: intermediate
2154 
2155 .keywords: TS, timestep, get, maximum, iterations, time
2156 @*/
2157 PetscErrorCode  TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
2158 {
2159   PetscFunctionBegin;
2160   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2161   if (maxsteps) {
2162     PetscValidIntPointer(maxsteps,2);
2163     *maxsteps = ts->max_steps;
2164   }
2165   if (maxtime) {
2166     PetscValidScalarPointer(maxtime,3);
2167     *maxtime = ts->max_time;
2168   }
2169   PetscFunctionReturn(0);
2170 }
2171 
2172 #undef __FUNCT__
2173 #define __FUNCT__ "TSSetDuration"
2174 /*@
2175    TSSetDuration - Sets the maximum number of timesteps to use and
2176    maximum time for iteration.
2177 
2178    Logically Collective on TS
2179 
2180    Input Parameters:
2181 +  ts - the TS context obtained from TSCreate()
2182 .  maxsteps - maximum number of iterations to use
2183 -  maxtime - final time to iterate to
2184 
2185    Options Database Keys:
2186 .  -ts_max_steps <maxsteps> - Sets maxsteps
2187 .  -ts_final_time <maxtime> - Sets maxtime
2188 
2189    Notes:
2190    The default maximum number of iterations is 5000. Default time is 5.0
2191 
2192    Level: intermediate
2193 
2194 .keywords: TS, timestep, set, maximum, iterations
2195 
2196 .seealso: TSSetExactFinalTime()
2197 @*/
2198 PetscErrorCode  TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
2199 {
2200   PetscFunctionBegin;
2201   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2202   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
2203   PetscValidLogicalCollectiveReal(ts,maxtime,2);
2204   if (maxsteps >= 0) ts->max_steps = maxsteps;
2205   if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
2206   PetscFunctionReturn(0);
2207 }
2208 
2209 #undef __FUNCT__
2210 #define __FUNCT__ "TSSetSolution"
2211 /*@
2212    TSSetSolution - Sets the initial solution vector
2213    for use by the TS routines.
2214 
2215    Logically Collective on TS and Vec
2216 
2217    Input Parameters:
2218 +  ts - the TS context obtained from TSCreate()
2219 -  u - the solution vector
2220 
2221    Level: beginner
2222 
2223 .keywords: TS, timestep, set, solution, initial conditions
2224 @*/
2225 PetscErrorCode  TSSetSolution(TS ts,Vec u)
2226 {
2227   PetscErrorCode ierr;
2228   DM             dm;
2229 
2230   PetscFunctionBegin;
2231   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2232   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
2233   ierr = PetscObjectReference((PetscObject)u);CHKERRQ(ierr);
2234   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
2235 
2236   ts->vec_sol = u;
2237 
2238   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2239   ierr = DMShellSetGlobalVector(dm,u);CHKERRQ(ierr);
2240   PetscFunctionReturn(0);
2241 }
2242 
2243 #undef __FUNCT__
2244 #define __FUNCT__ "TSSetSensitivity"
2245 /*@
2246    TSSetSensitivity - Sets the initial value of sensitivity (w.r.t. initial conditions)
2247    for use by the TS routines.
2248 
2249    Logically Collective on TS and Vec
2250 
2251    Input Parameters:
2252 +  ts - the TS context obtained from TSCreate()
2253 -  u - the solution vector
2254 
2255    Level: beginner
2256 
2257 .keywords: TS, timestep, set, sensitivity, initial conditions
2258 @*/
2259 PetscErrorCode  TSSetSensitivity(TS ts,Vec *u,PetscInt numberadjs)
2260 {
2261   PetscFunctionBegin;
2262   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2263   PetscValidPointer(u,2);
2264   ts->vecs_sensi = u;
2265   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()");
2266   ts->numberadjs = numberadjs;
2267 
2268   PetscFunctionReturn(0);
2269 }
2270 
2271 #undef __FUNCT__
2272 #define __FUNCT__ "TSSetSensitivityP"
2273 /*@
2274    TSSetSensitivityP - Sets the initial value of sensitivity (w.r.t. parameters)
2275    for use by the TS routines.
2276 
2277    Logically Collective on TS and Vec
2278 
2279    Input Parameters:
2280 +  ts - the TS context obtained from TSCreate()
2281 -  u - the solution vector
2282 
2283    Level: beginner
2284 
2285 .keywords: TS, timestep, set, sensitivity, initial conditions
2286 @*/
2287 PetscErrorCode  TSSetSensitivityP(TS ts,Vec *u,PetscInt numberadjs)
2288 {
2289   PetscFunctionBegin;
2290   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2291   PetscValidPointer(u,2);
2292   ts->vecs_sensip = u;
2293   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()");
2294   ts->numberadjs = numberadjs;
2295 
2296   PetscFunctionReturn(0);
2297 }
2298 
2299 #undef __FUNCT__
2300 #define __FUNCT__ "TSSetRHSJacobianP"
2301 /*@C
2302   TSSetRHSJacobianP - Sets the function that computes the Jacobian w.r.t. parameters.
2303 
2304   Logically Collective on TS
2305 
2306   Input Parameters:
2307 + ts   - The TS context obtained from TSCreate()
2308 - func - The function
2309 
2310   Calling sequence of func:
2311 . func (TS ts);
2312 
2313   Level: intermediate
2314 
2315 
2316 .keywords: TS, sensitivity
2317 .seealso:
2318 @*/
2319 PetscErrorCode  TSSetRHSJacobianP(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
2320 {
2321   PetscErrorCode ierr;
2322 
2323   PetscFunctionBegin;
2324   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2325   if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
2326 
2327   ts->rhsjacobianp    = func;
2328   ts->rhsjacobianpctx = ctx;
2329   if(Amat) {
2330     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
2331     ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
2332 
2333     ts->Jacp = Amat;
2334   }
2335   PetscFunctionReturn(0);
2336 }
2337 
2338 #undef __FUNCT__
2339 #define __FUNCT__ "TSRHSJacobianP"
2340 /*@
2341   TSRHSJacobianP - Runs the user-defined JacobianP function.
2342 
2343   Collective on TS
2344 
2345   Input Parameters:
2346 . ts   - The TS context obtained from TSCreate()
2347 
2348   Notes:
2349   TSJacobianP() is typically used for sensitivity implementation,
2350   so most users would not generally call this routine themselves.
2351 
2352   Level: developer
2353 
2354 .keywords: TS, sensitivity
2355 .seealso: TSSetRHSJacobianP()
2356 @*/
2357 PetscErrorCode  TSRHSJacobianP(TS ts,PetscReal t,Vec X,Mat Amat)
2358 {
2359   PetscErrorCode ierr;
2360 
2361   PetscFunctionBegin;
2362   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2363   PetscValidHeaderSpecific(X,VEC_CLASSID,3);
2364   PetscValidPointer(Amat,4);
2365 
2366   PetscStackPush("TS user JacobianP function for sensitivity analysis");
2367   ierr = (*ts->rhsjacobianp)(ts,t,X,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr);
2368   PetscStackPop;
2369 
2370   PetscFunctionReturn(0);
2371 }
2372 
2373 #undef __FUNCT__
2374 #define __FUNCT__ "TSSetQuadFunction"
2375 /*@C
2376     TSSetQuadFunction - Sets the routine for evaluating the quadrature (or integral) term in a cost function,
2377     where Q_t = r(t,u).
2378 
2379     Logically Collective on TS
2380 
2381     Input Parameters:
2382 +   ts - the TS context obtained from TSCreate()
2383 .   r -  vector to put the computed right hand side (or NULL to have it created)
2384 .   fq - routine for evaluating the right-hand-side function
2385 -   ctx - [optional] user-defined context for private data for the
2386           function evaluation routine (may be NULL)
2387 
2388     Calling sequence of func:
2389 $     func (TS ts,PetscReal t,Vec u,PetscReal *r,void *ctx);
2390 
2391 +   t - current timestep
2392 .   u - input vector
2393 .   r - function vector
2394 -   ctx - [optional] user-defined function context
2395 
2396     Level: beginner
2397 
2398 .keywords: TS, sensitivity analysis, timestep, set, quadrature, function
2399 
2400 .seealso: TSSetRHSJacobianP(),TSSetSensitivity(),TSSetSensitivityP()
2401 @*/
2402 PetscErrorCode  TSSetQuadFunction(TS ts,PetscInt numberadjs,Vec r,PetscErrorCode (*fq)(TS,PetscReal,Vec,Vec,void*),void *ctx)
2403 {
2404   PetscErrorCode ierr;
2405   PetscReal      *ralloc = NULL;
2406 
2407   PetscFunctionBegin;
2408   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2409 
2410   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.");
2411   if(ts->numberadjs && ts->numberadjs!=numberadjs) SETERRQ(PetscObjectComm((PetscObject)ts),PETS     C_ERR_USER,"The number of cost functions (2rd parameter) is inconsistent with the one set by TSSetSensitivity() or TSSetSensitivityP()");
2412 
2413   if(!r && ts->vec_quad) {
2414      ierr = VecDuplicate(ts->vec_quad,&ralloc);CHKERRQ(ierr);
2415      r    = ralloc;
2416   }
2417   ierr = VecDestroy(&ralloc);CHKERRQ(ierr);
2418 
2419   ts->qfunction = fq;
2420 
2421   PetscFunctionReturn(0);
2422 }
2423 
2424 #undef __FUNCT__
2425 #define __FUNCT__ "TSComputeQuadFunction"
2426 /*@
2427    TSComputeQuadFunction - Evaluates the quadrature function in the cost functions.
2428 
2429    Input Parameters:
2430 +  ts - the TS context
2431 .  t - current time
2432 -  U - state vector
2433 
2434    Output Parameter:
2435 .  q - vector of size numberadjs to hold the outputs
2436 
2437    Note:
2438    Most users should not need to explicitly call this routine, as it
2439    is used internally within the sensitivity analysis context.
2440 
2441    Level: developer
2442 
2443 .keywords: TS, compute
2444 
2445 .seealso: TSSetQuadFunction()
2446 @*/
2447 PetscErrorCode TSComputeQuadFunction(TS ts,PetscReal t,Vec U,Vec q)
2448 {
2449   PetscErrorCode ierr;
2450   void           *ctx;
2451   DM             dm;
2452 
2453   PetscFunctionBegin;
2454   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2455   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
2456   PetscValidHeaderSpecific(q,VEC_CLASSID,4);
2457 
2458   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,q,0);CHKERRQ(ierr);
2459   if (ts->qfunction) {
2460     PetscStackPush("TS user right-hand-side function");
2461     ierr = (*qfunction)(ts,t,U,q,ctx);CHKERRQ(ierr);
2462     PetscStackPop;
2463   } else {
2464     ierr = VecZeroEntries(q);CHKERRQ(ierr);
2465   }
2466 
2467   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,q,0);CHKERRQ(ierr);
2468   PetscFunctionReturn(0);
2469 }
2470 
2471 #undef __FUNCT__
2472 #define __FUNCT__ "TSSetPreStep"
2473 /*@C
2474   TSSetPreStep - Sets the general-purpose function
2475   called once at the beginning of each time step.
2476 
2477   Logically Collective on TS
2478 
2479   Input Parameters:
2480 + ts   - The TS context obtained from TSCreate()
2481 - func - The function
2482 
2483   Calling sequence of func:
2484 . func (TS ts);
2485 
2486   Level: intermediate
2487 
2488   Note:
2489   If a step is rejected, TSStep() will call this routine again before each attempt.
2490   The last completed time step number can be queried using TSGetTimeStepNumber(), the
2491   size of the step being attempted can be obtained using TSGetTimeStep().
2492 
2493 .keywords: TS, timestep
2494 .seealso: TSSetPreStage(), TSSetPostStage(), TSSetPostStep(), TSStep()
2495 @*/
2496 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
2497 {
2498   PetscFunctionBegin;
2499   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2500   ts->prestep = func;
2501   PetscFunctionReturn(0);
2502 }
2503 
2504 #undef __FUNCT__
2505 #define __FUNCT__ "TSPreStep"
2506 /*@
2507   TSPreStep - Runs the user-defined pre-step function.
2508 
2509   Collective on TS
2510 
2511   Input Parameters:
2512 . ts   - The TS context obtained from TSCreate()
2513 
2514   Notes:
2515   TSPreStep() is typically used within time stepping implementations,
2516   so most users would not generally call this routine themselves.
2517 
2518   Level: developer
2519 
2520 .keywords: TS, timestep
2521 .seealso: TSSetPreStep(), TSPreStage(), TSPostStage(), TSPostStep()
2522 @*/
2523 PetscErrorCode  TSPreStep(TS ts)
2524 {
2525   PetscErrorCode ierr;
2526 
2527   PetscFunctionBegin;
2528   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2529   if (ts->prestep) {
2530     PetscStackCallStandard((*ts->prestep),(ts));
2531   }
2532   PetscFunctionReturn(0);
2533 }
2534 
2535 #undef __FUNCT__
2536 #define __FUNCT__ "TSSetPreStage"
2537 /*@C
2538   TSSetPreStage - Sets the general-purpose function
2539   called once at the beginning of each stage.
2540 
2541   Logically Collective on TS
2542 
2543   Input Parameters:
2544 + ts   - The TS context obtained from TSCreate()
2545 - func - The function
2546 
2547   Calling sequence of func:
2548 . PetscErrorCode func(TS ts, PetscReal stagetime);
2549 
2550   Level: intermediate
2551 
2552   Note:
2553   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
2554   The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
2555   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
2556 
2557 .keywords: TS, timestep
2558 .seealso: TSSetPostStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
2559 @*/
2560 PetscErrorCode  TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
2561 {
2562   PetscFunctionBegin;
2563   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2564   ts->prestage = func;
2565   PetscFunctionReturn(0);
2566 }
2567 
2568 #undef __FUNCT__
2569 #define __FUNCT__ "TSSetPostStage"
2570 /*@C
2571   TSSetPostStage - Sets the general-purpose function
2572   called once at the end of each stage.
2573 
2574   Logically Collective on TS
2575 
2576   Input Parameters:
2577 + ts   - The TS context obtained from TSCreate()
2578 - func - The function
2579 
2580   Calling sequence of func:
2581 . PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y);
2582 
2583   Level: intermediate
2584 
2585   Note:
2586   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
2587   The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
2588   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
2589 
2590 .keywords: TS, timestep
2591 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
2592 @*/
2593 PetscErrorCode  TSSetPostStage(TS ts, PetscErrorCode (*func)(TS,PetscReal,PetscInt,Vec*))
2594 {
2595   PetscFunctionBegin;
2596   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2597   ts->poststage = func;
2598   PetscFunctionReturn(0);
2599 }
2600 
2601 #undef __FUNCT__
2602 #define __FUNCT__ "TSPreStage"
2603 /*@
2604   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
2605 
2606   Collective on TS
2607 
2608   Input Parameters:
2609 . ts          - The TS context obtained from TSCreate()
2610   stagetime   - The absolute time of the current stage
2611 
2612   Notes:
2613   TSPreStage() is typically used within time stepping implementations,
2614   most users would not generally call this routine themselves.
2615 
2616   Level: developer
2617 
2618 .keywords: TS, timestep
2619 .seealso: TSPostStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
2620 @*/
2621 PetscErrorCode  TSPreStage(TS ts, PetscReal stagetime)
2622 {
2623   PetscErrorCode ierr;
2624 
2625   PetscFunctionBegin;
2626   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2627   if (ts->prestage) {
2628     PetscStackCallStandard((*ts->prestage),(ts,stagetime));
2629   }
2630   PetscFunctionReturn(0);
2631 }
2632 
2633 #undef __FUNCT__
2634 #define __FUNCT__ "TSPostStage"
2635 /*@
2636   TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage()
2637 
2638   Collective on TS
2639 
2640   Input Parameters:
2641 . ts          - The TS context obtained from TSCreate()
2642   stagetime   - The absolute time of the current stage
2643   stageindex  - Stage number
2644   Y           - Array of vectors (of size = total number
2645                 of stages) with the stage solutions
2646 
2647   Notes:
2648   TSPostStage() is typically used within time stepping implementations,
2649   most users would not generally call this routine themselves.
2650 
2651   Level: developer
2652 
2653 .keywords: TS, timestep
2654 .seealso: TSPreStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
2655 @*/
2656 PetscErrorCode  TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
2657 {
2658   PetscErrorCode ierr;
2659 
2660   PetscFunctionBegin;
2661   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2662   if (ts->poststage) {
2663     PetscStackCallStandard((*ts->poststage),(ts,stagetime,stageindex,Y));
2664   }
2665   PetscFunctionReturn(0);
2666 }
2667 
2668 #undef __FUNCT__
2669 #define __FUNCT__ "TSSetPostStep"
2670 /*@C
2671   TSSetPostStep - Sets the general-purpose function
2672   called once at the end of each time step.
2673 
2674   Logically Collective on TS
2675 
2676   Input Parameters:
2677 + ts   - The TS context obtained from TSCreate()
2678 - func - The function
2679 
2680   Calling sequence of func:
2681 $ func (TS ts);
2682 
2683   Level: intermediate
2684 
2685 .keywords: TS, timestep
2686 .seealso: TSSetPreStep(), TSSetPreStage(), TSGetTimeStep(), TSGetTimeStepNumber(), TSGetTime()
2687 @*/
2688 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
2689 {
2690   PetscFunctionBegin;
2691   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2692   ts->poststep = func;
2693   PetscFunctionReturn(0);
2694 }
2695 
2696 #undef __FUNCT__
2697 #define __FUNCT__ "TSPostStep"
2698 /*@
2699   TSPostStep - Runs the user-defined post-step function.
2700 
2701   Collective on TS
2702 
2703   Input Parameters:
2704 . ts   - The TS context obtained from TSCreate()
2705 
2706   Notes:
2707   TSPostStep() is typically used within time stepping implementations,
2708   so most users would not generally call this routine themselves.
2709 
2710   Level: developer
2711 
2712 .keywords: TS, timestep
2713 @*/
2714 PetscErrorCode  TSPostStep(TS ts)
2715 {
2716   PetscErrorCode ierr;
2717 
2718   PetscFunctionBegin;
2719   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2720   if (ts->poststep) {
2721     PetscStackCallStandard((*ts->poststep),(ts));
2722   }
2723   PetscFunctionReturn(0);
2724 }
2725 
2726 /* ------------ Routines to set performance monitoring options ----------- */
2727 
2728 #undef __FUNCT__
2729 #define __FUNCT__ "TSMonitorSet"
2730 /*@C
2731    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
2732    timestep to display the iteration's  progress.
2733 
2734    Logically Collective on TS
2735 
2736    Input Parameters:
2737 +  ts - the TS context obtained from TSCreate()
2738 .  monitor - monitoring routine
2739 .  mctx - [optional] user-defined context for private data for the
2740              monitor routine (use NULL if no context is desired)
2741 -  monitordestroy - [optional] routine that frees monitor context
2742           (may be NULL)
2743 
2744    Calling sequence of monitor:
2745 $    int monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
2746 
2747 +    ts - the TS context
2748 .    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
2749                                been interpolated to)
2750 .    time - current time
2751 .    u - current iterate
2752 -    mctx - [optional] monitoring context
2753 
2754    Notes:
2755    This routine adds an additional monitor to the list of monitors that
2756    already has been loaded.
2757 
2758    Fortran notes: Only a single monitor function can be set for each TS object
2759 
2760    Level: intermediate
2761 
2762 .keywords: TS, timestep, set, monitor
2763 
2764 .seealso: TSMonitorDefault(), TSMonitorCancel()
2765 @*/
2766 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
2767 {
2768   PetscFunctionBegin;
2769   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2770   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
2771   ts->monitor[ts->numbermonitors]          = monitor;
2772   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
2773   ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
2774   PetscFunctionReturn(0);
2775 }
2776 
2777 #undef __FUNCT__
2778 #define __FUNCT__ "TSMonitorCancel"
2779 /*@C
2780    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
2781 
2782    Logically Collective on TS
2783 
2784    Input Parameters:
2785 .  ts - the TS context obtained from TSCreate()
2786 
2787    Notes:
2788    There is no way to remove a single, specific monitor.
2789 
2790    Level: intermediate
2791 
2792 .keywords: TS, timestep, set, monitor
2793 
2794 .seealso: TSMonitorDefault(), TSMonitorSet()
2795 @*/
2796 PetscErrorCode  TSMonitorCancel(TS ts)
2797 {
2798   PetscErrorCode ierr;
2799   PetscInt       i;
2800 
2801   PetscFunctionBegin;
2802   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2803   for (i=0; i<ts->numbermonitors; i++) {
2804     if (ts->monitordestroy[i]) {
2805       ierr = (*ts->monitordestroy[i])(&ts->monitorcontext[i]);CHKERRQ(ierr);
2806     }
2807   }
2808   ts->numbermonitors = 0;
2809   PetscFunctionReturn(0);
2810 }
2811 
2812 #undef __FUNCT__
2813 #define __FUNCT__ "TSMonitorDefault"
2814 /*@
2815    TSMonitorDefault - Sets the Default monitor
2816 
2817    Level: intermediate
2818 
2819 .keywords: TS, set, monitor
2820 
2821 .seealso: TSMonitorDefault(), TSMonitorSet()
2822 @*/
2823 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *dummy)
2824 {
2825   PetscErrorCode ierr;
2826   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)ts));
2827 
2828   PetscFunctionBegin;
2829   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2830   ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g\n",step,(double)ts->time_step,(double)ptime);CHKERRQ(ierr);
2831   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2832   PetscFunctionReturn(0);
2833 }
2834 
2835 #undef __FUNCT__
2836 #define __FUNCT__ "TSSetRetainStages"
2837 /*@
2838    TSSetRetainStages - Request that all stages in the upcoming step be stored so that interpolation will be available.
2839 
2840    Logically Collective on TS
2841 
2842    Input Argument:
2843 .  ts - time stepping context
2844 
2845    Output Argument:
2846 .  flg - PETSC_TRUE or PETSC_FALSE
2847 
2848    Level: intermediate
2849 
2850 .keywords: TS, set
2851 
2852 .seealso: TSInterpolate(), TSSetPostStep()
2853 @*/
2854 PetscErrorCode TSSetRetainStages(TS ts,PetscBool flg)
2855 {
2856   PetscFunctionBegin;
2857   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2858   ts->retain_stages = flg;
2859   PetscFunctionReturn(0);
2860 }
2861 
2862 #undef __FUNCT__
2863 #define __FUNCT__ "TSInterpolate"
2864 /*@
2865    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
2866 
2867    Collective on TS
2868 
2869    Input Argument:
2870 +  ts - time stepping context
2871 -  t - time to interpolate to
2872 
2873    Output Argument:
2874 .  U - state at given time
2875 
2876    Notes:
2877    The user should call TSSetRetainStages() before taking a step in which interpolation will be requested.
2878 
2879    Level: intermediate
2880 
2881    Developer Notes:
2882    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
2883 
2884 .keywords: TS, set
2885 
2886 .seealso: TSSetRetainStages(), TSSetPostStep()
2887 @*/
2888 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
2889 {
2890   PetscErrorCode ierr;
2891 
2892   PetscFunctionBegin;
2893   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2894   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
2895   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);
2896   if (!ts->ops->interpolate) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
2897   ierr = (*ts->ops->interpolate)(ts,t,U);CHKERRQ(ierr);
2898   PetscFunctionReturn(0);
2899 }
2900 
2901 #undef __FUNCT__
2902 #define __FUNCT__ "TSStep"
2903 /*@
2904    TSStep - Steps one time step
2905 
2906    Collective on TS
2907 
2908    Input Parameter:
2909 .  ts - the TS context obtained from TSCreate()
2910 
2911    Level: intermediate
2912 
2913    Notes:
2914    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
2915    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
2916 
2917    This may over-step the final time provided in TSSetDuration() depending on the time-step used. TSSolve() interpolates to exactly the
2918    time provided in TSSetDuration(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
2919 
2920 .keywords: TS, timestep, solve
2921 
2922 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate()
2923 @*/
2924 PetscErrorCode  TSStep(TS ts)
2925 {
2926   DM               dm;
2927   PetscErrorCode   ierr;
2928   static PetscBool cite = PETSC_FALSE;
2929 
2930   PetscFunctionBegin;
2931   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2932   ierr = PetscCitationsRegister("@techreport{tspaper,\n"
2933                                 "  title       = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
2934                                 "  author      = {Shrirang Abhyankar and Jed Brown and Emil Constantinescu and Debojyoti Ghosh and Barry F. Smith},\n"
2935                                 "  type        = {Preprint},\n"
2936                                 "  number      = {ANL/MCS-P5061-0114},\n"
2937                                 "  institution = {Argonne National Laboratory},\n"
2938                                 "  year        = {2014}\n}\n",&cite);
2939 
2940   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
2941   ierr = TSSetUp(ts);CHKERRQ(ierr);
2942 
2943   ts->reason = TS_CONVERGED_ITERATING;
2944   ts->ptime_prev = ts->ptime;
2945   ierr = DMSetOutputSequenceNumber(dm, ts->steps, ts->ptime);CHKERRQ(ierr);
2946   ierr = VecViewFromOptions(ts->vec_sol, ((PetscObject) ts)->prefix, "-ts_view_solution");CHKERRQ(ierr);
2947 
2948   if (!ts->ops->step) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSStep not implemented for type '%s'",((PetscObject)ts)->type_name);
2949   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
2950   if(ts->reverse_mode) {
2951     if(!ts->ops->stepadj) {
2952       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);
2953     }else {
2954       ierr = (*ts->ops->stepadj)(ts);CHKERRQ(ierr);
2955     }
2956   }else {
2957     ierr = (*ts->ops->step)(ts);CHKERRQ(ierr);
2958   }
2959   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
2960 
2961   ts->time_step_prev = ts->ptime - ts->ptime_prev;
2962   ierr = DMSetOutputSequenceNumber(dm, ts->steps, ts->ptime);CHKERRQ(ierr);
2963 
2964   if (ts->reason < 0) {
2965     if (ts->errorifstepfailed) {
2966       if (ts->reason == TS_DIVERGED_NONLINEAR_SOLVE) {
2967         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]);
2968       } else if (ts->reason == TS_DIVERGED_STEP_REJECTED) {
2969         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]);
2970       } else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
2971     }
2972   } else if (!ts->reason) {
2973     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
2974     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
2975   }
2976   PetscFunctionReturn(0);
2977 }
2978 
2979 #undef __FUNCT__
2980 #define __FUNCT__ "TSEvaluateStep"
2981 /*@
2982    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
2983 
2984    Collective on TS
2985 
2986    Input Arguments:
2987 +  ts - time stepping context
2988 .  order - desired order of accuracy
2989 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
2990 
2991    Output Arguments:
2992 .  U - state at the end of the current step
2993 
2994    Level: advanced
2995 
2996    Notes:
2997    This function cannot be called until all stages have been evaluated.
2998    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.
2999 
3000 .seealso: TSStep(), TSAdapt
3001 @*/
3002 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
3003 {
3004   PetscErrorCode ierr;
3005 
3006   PetscFunctionBegin;
3007   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3008   PetscValidType(ts,1);
3009   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3010   if (!ts->ops->evaluatestep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3011   ierr = (*ts->ops->evaluatestep)(ts,order,U,done);CHKERRQ(ierr);
3012   PetscFunctionReturn(0);
3013 }
3014 
3015 #undef __FUNCT__
3016 #define __FUNCT__ "TSSolve"
3017 /*@
3018    TSSolve - Steps the requested number of timesteps.
3019 
3020    Collective on TS
3021 
3022    Input Parameter:
3023 +  ts - the TS context obtained from TSCreate()
3024 -  u - the solution vector  (can be null if TSSetSolution() was used, otherwise must contain the initial conditions)
3025 
3026    Level: beginner
3027 
3028    Notes:
3029    The final time returned by this function may be different from the time of the internally
3030    held state accessible by TSGetSolution() and TSGetTime() because the method may have
3031    stepped over the final time.
3032 
3033 .keywords: TS, timestep, solve
3034 
3035 .seealso: TSCreate(), TSSetSolution(), TSStep()
3036 @*/
3037 PetscErrorCode TSSolve(TS ts,Vec u)
3038 {
3039   Vec               solution;
3040   PetscErrorCode    ierr;
3041 
3042   PetscFunctionBegin;
3043   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3044   if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3045   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 */
3046     PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3047     if (!ts->vec_sol || u == ts->vec_sol) {
3048       ierr = VecDuplicate(u,&solution);CHKERRQ(ierr);
3049       ierr = TSSetSolution(ts,solution);CHKERRQ(ierr);
3050       ierr = VecDestroy(&solution);CHKERRQ(ierr); /* grant ownership */
3051     }
3052     ierr = VecCopy(u,ts->vec_sol);CHKERRQ(ierr);
3053   } else if (u) {
3054     ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
3055   }
3056   ierr = TSSetUp(ts);CHKERRQ(ierr); /*compute adj coefficients if the reverse mode is on*/
3057   /* reset time step and iteration counters */
3058   ts->steps             = 0;
3059   ts->ksp_its           = 0;
3060   ts->snes_its          = 0;
3061   ts->num_snes_failures = 0;
3062   ts->reject            = 0;
3063   ts->reason            = TS_CONVERGED_ITERATING;
3064 
3065   ierr = TSViewFromOptions(ts,NULL,"-ts_view_pre");CHKERRQ(ierr);
3066 
3067   if (ts->ops->solve) {         /* This private interface is transitional and should be removed when all implementations are updated. */
3068     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
3069     ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);
3070     ts->solvetime = ts->ptime;
3071   } else {
3072     /* steps the requested number of timesteps. */
3073     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
3074     else if (!ts->reverse_mode && ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3075     while (!ts->reason) {
3076       if(!ts->reverse_mode) {
3077         ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3078       }else {
3079         ierr = TSMonitor(ts,ts->max_steps-ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3080       }
3081       ierr = TSStep(ts);CHKERRQ(ierr);
3082       if (ts->event) {
3083 	ierr = TSEventMonitor(ts);CHKERRQ(ierr);
3084 	if (ts->event->status != TSEVENT_PROCESSING) {
3085 	  ierr = TSPostStep(ts);CHKERRQ(ierr);
3086 	}
3087       } else {
3088 	ierr = TSPostStep(ts);CHKERRQ(ierr);
3089       }
3090     }
3091     if (!ts->reverse_mode && ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
3092       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
3093       ts->solvetime = ts->max_time;
3094       solution = u;
3095     } else {
3096       if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
3097       ts->solvetime = ts->ptime;
3098       solution = ts->vec_sol;
3099     }
3100     if(!ts->reverse_mode) {
3101       ierr = TSMonitor(ts,ts->steps,ts->solvetime,solution);CHKERRQ(ierr);
3102     }
3103     ierr = VecViewFromOptions(u, ((PetscObject) ts)->prefix, "-ts_view_solution");CHKERRQ(ierr);
3104   }
3105 
3106   ierr = TSViewFromOptions(ts,NULL,"-ts_view");CHKERRQ(ierr);
3107   ierr = PetscObjectSAWsBlock((PetscObject)ts);CHKERRQ(ierr);
3108   PetscFunctionReturn(0);
3109 }
3110 
3111 #undef __FUNCT__
3112 #define __FUNCT__ "TSMonitor"
3113 /*@
3114    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
3115 
3116    Collective on TS
3117 
3118    Input Parameters:
3119 +  ts - time stepping context obtained from TSCreate()
3120 .  step - step number that has just completed
3121 .  ptime - model time of the state
3122 -  u - state at the current model time
3123 
3124    Notes:
3125    TSMonitor() is typically used within the time stepping implementations.
3126    Users might call this function when using the TSStep() interface instead of TSSolve().
3127 
3128    Level: advanced
3129 
3130 .keywords: TS, timestep
3131 @*/
3132 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
3133 {
3134   PetscErrorCode ierr;
3135   PetscInt       i,n = ts->numbermonitors;
3136 
3137   PetscFunctionBegin;
3138   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3139   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
3140   ierr = VecLockPush(u);CHKERRQ(ierr);
3141   for (i=0; i<n; i++) {
3142     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
3143   }
3144   ierr = VecLockPop(u);CHKERRQ(ierr);
3145   PetscFunctionReturn(0);
3146 }
3147 
3148 /* ------------------------------------------------------------------------*/
3149 #undef __FUNCT__
3150 #define __FUNCT__ "TSMonitorLGCtxCreate"
3151 /*@C
3152    TSMonitorLGCtxCreate - Creates a line graph context for use with
3153    TS to monitor the solution process graphically in various ways
3154 
3155    Collective on TS
3156 
3157    Input Parameters:
3158 +  host - the X display to open, or null for the local machine
3159 .  label - the title to put in the title bar
3160 .  x, y - the screen coordinates of the upper left coordinate of the window
3161 .  m, n - the screen width and height in pixels
3162 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
3163 
3164    Output Parameter:
3165 .  ctx - the context
3166 
3167    Options Database Key:
3168 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
3169 .  -ts_monitor_lg_solution -
3170 .  -ts_monitor_lg_error -
3171 .  -ts_monitor_lg_ksp_iterations -
3172 .  -ts_monitor_lg_snes_iterations -
3173 -  -lg_indicate_data_points <true,false> - indicate the data points (at each time step) on the plot; default is true
3174 
3175    Notes:
3176    Use TSMonitorLGCtxDestroy() to destroy.
3177 
3178    Level: intermediate
3179 
3180 .keywords: TS, monitor, line graph, residual, seealso
3181 
3182 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
3183 
3184 @*/
3185 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
3186 {
3187   PetscDraw      win;
3188   PetscErrorCode ierr;
3189 
3190   PetscFunctionBegin;
3191   ierr = PetscNew(ctx);CHKERRQ(ierr);
3192   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&win);CHKERRQ(ierr);
3193   ierr = PetscDrawSetFromOptions(win);CHKERRQ(ierr);
3194   ierr = PetscDrawLGCreate(win,1,&(*ctx)->lg);CHKERRQ(ierr);
3195   ierr = PetscLogObjectParent((PetscObject)(*ctx)->lg,(PetscObject)win);CHKERRQ(ierr);
3196   ierr = PetscDrawLGIndicateDataPoints((*ctx)->lg,PETSC_TRUE);CHKERRQ(ierr);
3197   ierr = PetscDrawLGSetFromOptions((*ctx)->lg);CHKERRQ(ierr);
3198   (*ctx)->howoften = howoften;
3199   PetscFunctionReturn(0);
3200 }
3201 
3202 #undef __FUNCT__
3203 #define __FUNCT__ "TSMonitorLGTimeStep"
3204 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
3205 {
3206   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
3207   PetscReal      x   = ptime,y;
3208   PetscErrorCode ierr;
3209 
3210   PetscFunctionBegin;
3211   if (!step) {
3212     PetscDrawAxis axis;
3213     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
3214     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time","Time step");CHKERRQ(ierr);
3215     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
3216     ierr = PetscDrawLGIndicateDataPoints(ctx->lg,PETSC_TRUE);CHKERRQ(ierr);
3217   }
3218   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
3219   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
3220   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
3221     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
3222   }
3223   PetscFunctionReturn(0);
3224 }
3225 
3226 #undef __FUNCT__
3227 #define __FUNCT__ "TSMonitorLGCtxDestroy"
3228 /*@C
3229    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
3230    with TSMonitorLGCtxCreate().
3231 
3232    Collective on TSMonitorLGCtx
3233 
3234    Input Parameter:
3235 .  ctx - the monitor context
3236 
3237    Level: intermediate
3238 
3239 .keywords: TS, monitor, line graph, destroy
3240 
3241 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
3242 @*/
3243 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
3244 {
3245   PetscDraw      draw;
3246   PetscErrorCode ierr;
3247 
3248   PetscFunctionBegin;
3249   ierr = PetscDrawLGGetDraw((*ctx)->lg,&draw);CHKERRQ(ierr);
3250   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
3251   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
3252   ierr = PetscFree(*ctx);CHKERRQ(ierr);
3253   PetscFunctionReturn(0);
3254 }
3255 
3256 #undef __FUNCT__
3257 #define __FUNCT__ "TSGetTime"
3258 /*@
3259    TSGetTime - Gets the time of the most recently completed step.
3260 
3261    Not Collective
3262 
3263    Input Parameter:
3264 .  ts - the TS context obtained from TSCreate()
3265 
3266    Output Parameter:
3267 .  t  - the current time
3268 
3269    Level: beginner
3270 
3271    Note:
3272    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
3273    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
3274 
3275 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
3276 
3277 .keywords: TS, get, time
3278 @*/
3279 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
3280 {
3281   PetscFunctionBegin;
3282   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3283   PetscValidRealPointer(t,2);
3284   *t = ts->ptime;
3285   PetscFunctionReturn(0);
3286 }
3287 
3288 #undef __FUNCT__
3289 #define __FUNCT__ "TSGetPrevTime"
3290 /*@
3291    TSGetPrevTime - Gets the starting time of the previously completed step.
3292 
3293    Not Collective
3294 
3295    Input Parameter:
3296 .  ts - the TS context obtained from TSCreate()
3297 
3298    Output Parameter:
3299 .  t  - the previous time
3300 
3301    Level: beginner
3302 
3303 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
3304 
3305 .keywords: TS, get, time
3306 @*/
3307 PetscErrorCode  TSGetPrevTime(TS ts,PetscReal *t)
3308 {
3309   PetscFunctionBegin;
3310   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3311   PetscValidRealPointer(t,2);
3312   *t = ts->ptime_prev;
3313   PetscFunctionReturn(0);
3314 }
3315 
3316 #undef __FUNCT__
3317 #define __FUNCT__ "TSSetTime"
3318 /*@
3319    TSSetTime - Allows one to reset the time.
3320 
3321    Logically Collective on TS
3322 
3323    Input Parameters:
3324 +  ts - the TS context obtained from TSCreate()
3325 -  time - the time
3326 
3327    Level: intermediate
3328 
3329 .seealso: TSGetTime(), TSSetDuration()
3330 
3331 .keywords: TS, set, time
3332 @*/
3333 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
3334 {
3335   PetscFunctionBegin;
3336   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3337   PetscValidLogicalCollectiveReal(ts,t,2);
3338   ts->ptime = t;
3339   PetscFunctionReturn(0);
3340 }
3341 
3342 #undef __FUNCT__
3343 #define __FUNCT__ "TSSetOptionsPrefix"
3344 /*@C
3345    TSSetOptionsPrefix - Sets the prefix used for searching for all
3346    TS options in the database.
3347 
3348    Logically Collective on TS
3349 
3350    Input Parameter:
3351 +  ts     - The TS context
3352 -  prefix - The prefix to prepend to all option names
3353 
3354    Notes:
3355    A hyphen (-) must NOT be given at the beginning of the prefix name.
3356    The first character of all runtime options is AUTOMATICALLY the
3357    hyphen.
3358 
3359    Level: advanced
3360 
3361 .keywords: TS, set, options, prefix, database
3362 
3363 .seealso: TSSetFromOptions()
3364 
3365 @*/
3366 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
3367 {
3368   PetscErrorCode ierr;
3369   SNES           snes;
3370 
3371   PetscFunctionBegin;
3372   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3373   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
3374   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3375   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
3376   PetscFunctionReturn(0);
3377 }
3378 
3379 
3380 #undef __FUNCT__
3381 #define __FUNCT__ "TSAppendOptionsPrefix"
3382 /*@C
3383    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
3384    TS options in the database.
3385 
3386    Logically Collective on TS
3387 
3388    Input Parameter:
3389 +  ts     - The TS context
3390 -  prefix - The prefix to prepend to all option names
3391 
3392    Notes:
3393    A hyphen (-) must NOT be given at the beginning of the prefix name.
3394    The first character of all runtime options is AUTOMATICALLY the
3395    hyphen.
3396 
3397    Level: advanced
3398 
3399 .keywords: TS, append, options, prefix, database
3400 
3401 .seealso: TSGetOptionsPrefix()
3402 
3403 @*/
3404 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
3405 {
3406   PetscErrorCode ierr;
3407   SNES           snes;
3408 
3409   PetscFunctionBegin;
3410   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3411   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
3412   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3413   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
3414   PetscFunctionReturn(0);
3415 }
3416 
3417 #undef __FUNCT__
3418 #define __FUNCT__ "TSGetOptionsPrefix"
3419 /*@C
3420    TSGetOptionsPrefix - Sets the prefix used for searching for all
3421    TS options in the database.
3422 
3423    Not Collective
3424 
3425    Input Parameter:
3426 .  ts - The TS context
3427 
3428    Output Parameter:
3429 .  prefix - A pointer to the prefix string used
3430 
3431    Notes: On the fortran side, the user should pass in a string 'prifix' of
3432    sufficient length to hold the prefix.
3433 
3434    Level: intermediate
3435 
3436 .keywords: TS, get, options, prefix, database
3437 
3438 .seealso: TSAppendOptionsPrefix()
3439 @*/
3440 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
3441 {
3442   PetscErrorCode ierr;
3443 
3444   PetscFunctionBegin;
3445   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3446   PetscValidPointer(prefix,2);
3447   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
3448   PetscFunctionReturn(0);
3449 }
3450 
3451 #undef __FUNCT__
3452 #define __FUNCT__ "TSGetRHSJacobian"
3453 /*@C
3454    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
3455 
3456    Not Collective, but parallel objects are returned if TS is parallel
3457 
3458    Input Parameter:
3459 .  ts  - The TS context obtained from TSCreate()
3460 
3461    Output Parameters:
3462 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
3463 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
3464 .  func - Function to compute the Jacobian of the RHS  (or NULL)
3465 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
3466 
3467    Notes: You can pass in NULL for any return argument you do not need.
3468 
3469    Level: intermediate
3470 
3471 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
3472 
3473 .keywords: TS, timestep, get, matrix, Jacobian
3474 @*/
3475 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
3476 {
3477   PetscErrorCode ierr;
3478   SNES           snes;
3479   DM             dm;
3480 
3481   PetscFunctionBegin;
3482   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3483   ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
3484   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3485   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
3486   PetscFunctionReturn(0);
3487 }
3488 
3489 #undef __FUNCT__
3490 #define __FUNCT__ "TSGetIJacobian"
3491 /*@C
3492    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
3493 
3494    Not Collective, but parallel objects are returned if TS is parallel
3495 
3496    Input Parameter:
3497 .  ts  - The TS context obtained from TSCreate()
3498 
3499    Output Parameters:
3500 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
3501 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
3502 .  f   - The function to compute the matrices
3503 - ctx - User-defined context for Jacobian evaluation routine
3504 
3505    Notes: You can pass in NULL for any return argument you do not need.
3506 
3507    Level: advanced
3508 
3509 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
3510 
3511 .keywords: TS, timestep, get, matrix, Jacobian
3512 @*/
3513 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
3514 {
3515   PetscErrorCode ierr;
3516   SNES           snes;
3517   DM             dm;
3518 
3519   PetscFunctionBegin;
3520   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3521   ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
3522   ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
3523   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3524   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
3525   PetscFunctionReturn(0);
3526 }
3527 
3528 
3529 #undef __FUNCT__
3530 #define __FUNCT__ "TSMonitorDrawSolution"
3531 /*@C
3532    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
3533    VecView() for the solution at each timestep
3534 
3535    Collective on TS
3536 
3537    Input Parameters:
3538 +  ts - the TS context
3539 .  step - current time-step
3540 .  ptime - current time
3541 -  dummy - either a viewer or NULL
3542 
3543    Options Database:
3544 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3545 
3546    Notes: the initial solution and current solution are not displayed with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
3547        will look bad
3548 
3549    Level: intermediate
3550 
3551 .keywords: TS,  vector, monitor, view
3552 
3553 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3554 @*/
3555 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3556 {
3557   PetscErrorCode   ierr;
3558   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
3559   PetscDraw        draw;
3560 
3561   PetscFunctionBegin;
3562   if (!step && ictx->showinitial) {
3563     if (!ictx->initialsolution) {
3564       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
3565     }
3566     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
3567   }
3568   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
3569 
3570   if (ictx->showinitial) {
3571     PetscReal pause;
3572     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
3573     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
3574     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
3575     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
3576     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
3577   }
3578   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
3579   if (ictx->showtimestepandtime) {
3580     PetscReal xl,yl,xr,yr,tw,w,h;
3581     char      time[32];
3582     size_t    len;
3583 
3584     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
3585     ierr = PetscSNPrintf(time,32,"Timestep %d Time %f",(int)step,(double)ptime);CHKERRQ(ierr);
3586     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
3587     ierr =  PetscStrlen(time,&len);CHKERRQ(ierr);
3588     ierr = PetscDrawStringGetSize(draw,&tw,NULL);CHKERRQ(ierr);
3589     w    = xl + .5*(xr - xl) - .5*len*tw;
3590     h    = yl + .95*(yr - yl);
3591     ierr = PetscDrawString(draw,w,h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
3592     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
3593   }
3594 
3595   if (ictx->showinitial) {
3596     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
3597   }
3598   PetscFunctionReturn(0);
3599 }
3600 
3601 #undef __FUNCT__
3602 #define __FUNCT__ "TSMonitorDrawSolutionPhase"
3603 /*@C
3604    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
3605 
3606    Collective on TS
3607 
3608    Input Parameters:
3609 +  ts - the TS context
3610 .  step - current time-step
3611 .  ptime - current time
3612 -  dummy - either a viewer or NULL
3613 
3614    Level: intermediate
3615 
3616 .keywords: TS,  vector, monitor, view
3617 
3618 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3619 @*/
3620 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3621 {
3622   PetscErrorCode    ierr;
3623   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
3624   PetscDraw         draw;
3625   MPI_Comm          comm;
3626   PetscInt          n;
3627   PetscMPIInt       size;
3628   PetscReal         xl,yl,xr,yr,tw,w,h;
3629   char              time[32];
3630   size_t            len;
3631   const PetscScalar *U;
3632 
3633   PetscFunctionBegin;
3634   ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
3635   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
3636   if (size != 1) SETERRQ(comm,PETSC_ERR_SUP,"Only allowed for sequential runs");
3637   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
3638   if (n != 2) SETERRQ(comm,PETSC_ERR_SUP,"Only for ODEs with two unknowns");
3639 
3640   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
3641 
3642   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
3643   ierr = PetscDrawAxisGetLimits(ictx->axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
3644   if ((PetscRealPart(U[0]) < xl) || (PetscRealPart(U[1]) < yl) || (PetscRealPart(U[0]) > xr) || (PetscRealPart(U[1]) > yr)) {
3645       ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
3646       PetscFunctionReturn(0);
3647   }
3648   if (!step) ictx->color++;
3649   ierr = PetscDrawPoint(draw,PetscRealPart(U[0]),PetscRealPart(U[1]),ictx->color);CHKERRQ(ierr);
3650   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
3651 
3652   if (ictx->showtimestepandtime) {
3653     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
3654     ierr = PetscSNPrintf(time,32,"Timestep %d Time %f",(int)step,(double)ptime);CHKERRQ(ierr);
3655     ierr = PetscStrlen(time,&len);CHKERRQ(ierr);
3656     ierr = PetscDrawStringGetSize(draw,&tw,NULL);CHKERRQ(ierr);
3657     w    = xl + .5*(xr - xl) - .5*len*tw;
3658     h    = yl + .95*(yr - yl);
3659     ierr = PetscDrawString(draw,w,h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
3660   }
3661   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
3662   PetscFunctionReturn(0);
3663 }
3664 
3665 
3666 #undef __FUNCT__
3667 #define __FUNCT__ "TSMonitorDrawCtxDestroy"
3668 /*@C
3669    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
3670 
3671    Collective on TS
3672 
3673    Input Parameters:
3674 .    ctx - the monitor context
3675 
3676    Level: intermediate
3677 
3678 .keywords: TS,  vector, monitor, view
3679 
3680 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
3681 @*/
3682 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
3683 {
3684   PetscErrorCode ierr;
3685 
3686   PetscFunctionBegin;
3687   ierr = PetscDrawAxisDestroy(&(*ictx)->axis);CHKERRQ(ierr);
3688   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
3689   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
3690   ierr = PetscFree(*ictx);CHKERRQ(ierr);
3691   PetscFunctionReturn(0);
3692 }
3693 
3694 #undef __FUNCT__
3695 #define __FUNCT__ "TSMonitorDrawCtxCreate"
3696 /*@C
3697    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
3698 
3699    Collective on TS
3700 
3701    Input Parameter:
3702 .    ts - time-step context
3703 
3704    Output Patameter:
3705 .    ctx - the monitor context
3706 
3707    Options Database:
3708 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3709 
3710    Level: intermediate
3711 
3712 .keywords: TS,  vector, monitor, view
3713 
3714 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
3715 @*/
3716 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
3717 {
3718   PetscErrorCode   ierr;
3719 
3720   PetscFunctionBegin;
3721   ierr = PetscNew(ctx);CHKERRQ(ierr);
3722   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
3723   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
3724 
3725   (*ctx)->howoften    = howoften;
3726   (*ctx)->showinitial = PETSC_FALSE;
3727   ierr = PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
3728 
3729   (*ctx)->showtimestepandtime = PETSC_FALSE;
3730   ierr = PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
3731   (*ctx)->color = PETSC_DRAW_WHITE;
3732   PetscFunctionReturn(0);
3733 }
3734 
3735 #undef __FUNCT__
3736 #define __FUNCT__ "TSMonitorDrawError"
3737 /*@C
3738    TSMonitorDrawError - Monitors progress of the TS solvers by calling
3739    VecView() for the error at each timestep
3740 
3741    Collective on TS
3742 
3743    Input Parameters:
3744 +  ts - the TS context
3745 .  step - current time-step
3746 .  ptime - current time
3747 -  dummy - either a viewer or NULL
3748 
3749    Level: intermediate
3750 
3751 .keywords: TS,  vector, monitor, view
3752 
3753 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3754 @*/
3755 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3756 {
3757   PetscErrorCode   ierr;
3758   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
3759   PetscViewer      viewer = ctx->viewer;
3760   Vec              work;
3761 
3762   PetscFunctionBegin;
3763   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
3764   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
3765   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
3766   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
3767   ierr = VecView(work,viewer);CHKERRQ(ierr);
3768   ierr = VecDestroy(&work);CHKERRQ(ierr);
3769   PetscFunctionReturn(0);
3770 }
3771 
3772 #include <petsc-private/dmimpl.h>
3773 #undef __FUNCT__
3774 #define __FUNCT__ "TSSetDM"
3775 /*@
3776    TSSetDM - Sets the DM that may be used by some preconditioners
3777 
3778    Logically Collective on TS and DM
3779 
3780    Input Parameters:
3781 +  ts - the preconditioner context
3782 -  dm - the dm
3783 
3784    Level: intermediate
3785 
3786 
3787 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
3788 @*/
3789 PetscErrorCode  TSSetDM(TS ts,DM dm)
3790 {
3791   PetscErrorCode ierr;
3792   SNES           snes;
3793   DMTS           tsdm;
3794 
3795   PetscFunctionBegin;
3796   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3797   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
3798   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
3799     if (ts->dm->dmts && !dm->dmts) {
3800       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
3801       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
3802       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
3803         tsdm->originaldm = dm;
3804       }
3805     }
3806     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
3807   }
3808   ts->dm = dm;
3809 
3810   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3811   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
3812   PetscFunctionReturn(0);
3813 }
3814 
3815 #undef __FUNCT__
3816 #define __FUNCT__ "TSGetDM"
3817 /*@
3818    TSGetDM - Gets the DM that may be used by some preconditioners
3819 
3820    Not Collective
3821 
3822    Input Parameter:
3823 . ts - the preconditioner context
3824 
3825    Output Parameter:
3826 .  dm - the dm
3827 
3828    Level: intermediate
3829 
3830 
3831 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
3832 @*/
3833 PetscErrorCode  TSGetDM(TS ts,DM *dm)
3834 {
3835   PetscErrorCode ierr;
3836 
3837   PetscFunctionBegin;
3838   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3839   if (!ts->dm) {
3840     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
3841     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
3842   }
3843   *dm = ts->dm;
3844   PetscFunctionReturn(0);
3845 }
3846 
3847 #undef __FUNCT__
3848 #define __FUNCT__ "SNESTSFormFunction"
3849 /*@
3850    SNESTSFormFunction - Function to evaluate nonlinear residual
3851 
3852    Logically Collective on SNES
3853 
3854    Input Parameter:
3855 + snes - nonlinear solver
3856 . U - the current state at which to evaluate the residual
3857 - ctx - user context, must be a TS
3858 
3859    Output Parameter:
3860 . F - the nonlinear residual
3861 
3862    Notes:
3863    This function is not normally called by users and is automatically registered with the SNES used by TS.
3864    It is most frequently passed to MatFDColoringSetFunction().
3865 
3866    Level: advanced
3867 
3868 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
3869 @*/
3870 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
3871 {
3872   TS             ts = (TS)ctx;
3873   PetscErrorCode ierr;
3874 
3875   PetscFunctionBegin;
3876   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3877   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
3878   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
3879   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
3880   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
3881   PetscFunctionReturn(0);
3882 }
3883 
3884 #undef __FUNCT__
3885 #define __FUNCT__ "SNESTSFormJacobian"
3886 /*@
3887    SNESTSFormJacobian - Function to evaluate the Jacobian
3888 
3889    Collective on SNES
3890 
3891    Input Parameter:
3892 + snes - nonlinear solver
3893 . U - the current state at which to evaluate the residual
3894 - ctx - user context, must be a TS
3895 
3896    Output Parameter:
3897 + A - the Jacobian
3898 . B - the preconditioning matrix (may be the same as A)
3899 - flag - indicates any structure change in the matrix
3900 
3901    Notes:
3902    This function is not normally called by users and is automatically registered with the SNES used by TS.
3903 
3904    Level: developer
3905 
3906 .seealso: SNESSetJacobian()
3907 @*/
3908 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
3909 {
3910   TS             ts = (TS)ctx;
3911   PetscErrorCode ierr;
3912 
3913   PetscFunctionBegin;
3914   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3915   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
3916   PetscValidPointer(A,3);
3917   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
3918   PetscValidPointer(B,4);
3919   PetscValidHeaderSpecific(B,MAT_CLASSID,4);
3920   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
3921   ierr = (ts->ops->snesjacobian)(snes,U,A,B,ts);CHKERRQ(ierr);
3922   PetscFunctionReturn(0);
3923 }
3924 
3925 #undef __FUNCT__
3926 #define __FUNCT__ "TSComputeRHSFunctionLinear"
3927 /*@C
3928    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems only
3929 
3930    Collective on TS
3931 
3932    Input Arguments:
3933 +  ts - time stepping context
3934 .  t - time at which to evaluate
3935 .  U - state at which to evaluate
3936 -  ctx - context
3937 
3938    Output Arguments:
3939 .  F - right hand side
3940 
3941    Level: intermediate
3942 
3943    Notes:
3944    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
3945    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
3946 
3947 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
3948 @*/
3949 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
3950 {
3951   PetscErrorCode ierr;
3952   Mat            Arhs,Brhs;
3953 
3954   PetscFunctionBegin;
3955   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
3956   ierr = TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);CHKERRQ(ierr);
3957   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
3958   PetscFunctionReturn(0);
3959 }
3960 
3961 #undef __FUNCT__
3962 #define __FUNCT__ "TSComputeRHSJacobianConstant"
3963 /*@C
3964    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
3965 
3966    Collective on TS
3967 
3968    Input Arguments:
3969 +  ts - time stepping context
3970 .  t - time at which to evaluate
3971 .  U - state at which to evaluate
3972 -  ctx - context
3973 
3974    Output Arguments:
3975 +  A - pointer to operator
3976 .  B - pointer to preconditioning matrix
3977 -  flg - matrix structure flag
3978 
3979    Level: intermediate
3980 
3981    Notes:
3982    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
3983 
3984 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
3985 @*/
3986 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
3987 {
3988   PetscFunctionBegin;
3989   PetscFunctionReturn(0);
3990 }
3991 
3992 #undef __FUNCT__
3993 #define __FUNCT__ "TSComputeIFunctionLinear"
3994 /*@C
3995    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
3996 
3997    Collective on TS
3998 
3999    Input Arguments:
4000 +  ts - time stepping context
4001 .  t - time at which to evaluate
4002 .  U - state at which to evaluate
4003 .  Udot - time derivative of state vector
4004 -  ctx - context
4005 
4006    Output Arguments:
4007 .  F - left hand side
4008 
4009    Level: intermediate
4010 
4011    Notes:
4012    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
4013    user is required to write their own TSComputeIFunction.
4014    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
4015    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
4016 
4017 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant()
4018 @*/
4019 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
4020 {
4021   PetscErrorCode ierr;
4022   Mat            A,B;
4023 
4024   PetscFunctionBegin;
4025   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
4026   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE);CHKERRQ(ierr);
4027   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
4028   PetscFunctionReturn(0);
4029 }
4030 
4031 #undef __FUNCT__
4032 #define __FUNCT__ "TSComputeIJacobianConstant"
4033 /*@C
4034    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
4035 
4036    Collective on TS
4037 
4038    Input Arguments:
4039 +  ts - time stepping context
4040 .  t - time at which to evaluate
4041 .  U - state at which to evaluate
4042 .  Udot - time derivative of state vector
4043 .  shift - shift to apply
4044 -  ctx - context
4045 
4046    Output Arguments:
4047 +  A - pointer to operator
4048 .  B - pointer to preconditioning matrix
4049 -  flg - matrix structure flag
4050 
4051    Level: advanced
4052 
4053    Notes:
4054    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
4055 
4056    It is only appropriate for problems of the form
4057 
4058 $     M Udot = F(U,t)
4059 
4060   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
4061   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
4062   an implicit operator of the form
4063 
4064 $    shift*M + J
4065 
4066   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
4067   a copy of M or reassemble it when requested.
4068 
4069 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
4070 @*/
4071 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
4072 {
4073   PetscErrorCode ierr;
4074 
4075   PetscFunctionBegin;
4076   ierr = MatScale(A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
4077   ts->ijacobian.shift = shift;
4078   PetscFunctionReturn(0);
4079 }
4080 
4081 #undef __FUNCT__
4082 #define __FUNCT__ "TSGetEquationType"
4083 /*@
4084    TSGetEquationType - Gets the type of the equation that TS is solving.
4085 
4086    Not Collective
4087 
4088    Input Parameter:
4089 .  ts - the TS context
4090 
4091    Output Parameter:
4092 .  equation_type - see TSEquationType
4093 
4094    Level: beginner
4095 
4096 .keywords: TS, equation type
4097 
4098 .seealso: TSSetEquationType(), TSEquationType
4099 @*/
4100 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
4101 {
4102   PetscFunctionBegin;
4103   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4104   PetscValidPointer(equation_type,2);
4105   *equation_type = ts->equation_type;
4106   PetscFunctionReturn(0);
4107 }
4108 
4109 #undef __FUNCT__
4110 #define __FUNCT__ "TSSetEquationType"
4111 /*@
4112    TSSetEquationType - Sets the type of the equation that TS is solving.
4113 
4114    Not Collective
4115 
4116    Input Parameter:
4117 +  ts - the TS context
4118 .  equation_type - see TSEquationType
4119 
4120    Level: advanced
4121 
4122 .keywords: TS, equation type
4123 
4124 .seealso: TSGetEquationType(), TSEquationType
4125 @*/
4126 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
4127 {
4128   PetscFunctionBegin;
4129   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4130   ts->equation_type = equation_type;
4131   PetscFunctionReturn(0);
4132 }
4133 
4134 #undef __FUNCT__
4135 #define __FUNCT__ "TSGetConvergedReason"
4136 /*@
4137    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
4138 
4139    Not Collective
4140 
4141    Input Parameter:
4142 .  ts - the TS context
4143 
4144    Output Parameter:
4145 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4146             manual pages for the individual convergence tests for complete lists
4147 
4148    Level: beginner
4149 
4150    Notes:
4151    Can only be called after the call to TSSolve() is complete.
4152 
4153 .keywords: TS, nonlinear, set, convergence, test
4154 
4155 .seealso: TSSetConvergenceTest(), TSConvergedReason
4156 @*/
4157 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
4158 {
4159   PetscFunctionBegin;
4160   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4161   PetscValidPointer(reason,2);
4162   *reason = ts->reason;
4163   PetscFunctionReturn(0);
4164 }
4165 
4166 #undef __FUNCT__
4167 #define __FUNCT__ "TSSetConvergedReason"
4168 /*@
4169    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
4170 
4171    Not Collective
4172 
4173    Input Parameter:
4174 +  ts - the TS context
4175 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4176             manual pages for the individual convergence tests for complete lists
4177 
4178    Level: advanced
4179 
4180    Notes:
4181    Can only be called during TSSolve() is active.
4182 
4183 .keywords: TS, nonlinear, set, convergence, test
4184 
4185 .seealso: TSConvergedReason
4186 @*/
4187 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
4188 {
4189   PetscFunctionBegin;
4190   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4191   ts->reason = reason;
4192   PetscFunctionReturn(0);
4193 }
4194 
4195 #undef __FUNCT__
4196 #define __FUNCT__ "TSGetSolveTime"
4197 /*@
4198    TSGetSolveTime - Gets the time after a call to TSSolve()
4199 
4200    Not Collective
4201 
4202    Input Parameter:
4203 .  ts - the TS context
4204 
4205    Output Parameter:
4206 .  ftime - the final time. This time should correspond to the final time set with TSSetDuration()
4207 
4208    Level: beginner
4209 
4210    Notes:
4211    Can only be called after the call to TSSolve() is complete.
4212 
4213 .keywords: TS, nonlinear, set, convergence, test
4214 
4215 .seealso: TSSetConvergenceTest(), TSConvergedReason
4216 @*/
4217 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
4218 {
4219   PetscFunctionBegin;
4220   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4221   PetscValidPointer(ftime,2);
4222   *ftime = ts->solvetime;
4223   PetscFunctionReturn(0);
4224 }
4225 
4226 #undef __FUNCT__
4227 #define __FUNCT__ "TSGetSNESIterations"
4228 /*@
4229    TSGetSNESIterations - Gets the total number of nonlinear iterations
4230    used by the time integrator.
4231 
4232    Not Collective
4233 
4234    Input Parameter:
4235 .  ts - TS context
4236 
4237    Output Parameter:
4238 .  nits - number of nonlinear iterations
4239 
4240    Notes:
4241    This counter is reset to zero for each successive call to TSSolve().
4242 
4243    Level: intermediate
4244 
4245 .keywords: TS, get, number, nonlinear, iterations
4246 
4247 .seealso:  TSGetKSPIterations()
4248 @*/
4249 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
4250 {
4251   PetscFunctionBegin;
4252   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4253   PetscValidIntPointer(nits,2);
4254   *nits = ts->snes_its;
4255   PetscFunctionReturn(0);
4256 }
4257 
4258 #undef __FUNCT__
4259 #define __FUNCT__ "TSGetKSPIterations"
4260 /*@
4261    TSGetKSPIterations - Gets the total number of linear iterations
4262    used by the time integrator.
4263 
4264    Not Collective
4265 
4266    Input Parameter:
4267 .  ts - TS context
4268 
4269    Output Parameter:
4270 .  lits - number of linear iterations
4271 
4272    Notes:
4273    This counter is reset to zero for each successive call to TSSolve().
4274 
4275    Level: intermediate
4276 
4277 .keywords: TS, get, number, linear, iterations
4278 
4279 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
4280 @*/
4281 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
4282 {
4283   PetscFunctionBegin;
4284   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4285   PetscValidIntPointer(lits,2);
4286   *lits = ts->ksp_its;
4287   PetscFunctionReturn(0);
4288 }
4289 
4290 #undef __FUNCT__
4291 #define __FUNCT__ "TSGetStepRejections"
4292 /*@
4293    TSGetStepRejections - Gets the total number of rejected steps.
4294 
4295    Not Collective
4296 
4297    Input Parameter:
4298 .  ts - TS context
4299 
4300    Output Parameter:
4301 .  rejects - number of steps rejected
4302 
4303    Notes:
4304    This counter is reset to zero for each successive call to TSSolve().
4305 
4306    Level: intermediate
4307 
4308 .keywords: TS, get, number
4309 
4310 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
4311 @*/
4312 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
4313 {
4314   PetscFunctionBegin;
4315   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4316   PetscValidIntPointer(rejects,2);
4317   *rejects = ts->reject;
4318   PetscFunctionReturn(0);
4319 }
4320 
4321 #undef __FUNCT__
4322 #define __FUNCT__ "TSGetSNESFailures"
4323 /*@
4324    TSGetSNESFailures - Gets the total number of failed SNES solves
4325 
4326    Not Collective
4327 
4328    Input Parameter:
4329 .  ts - TS context
4330 
4331    Output Parameter:
4332 .  fails - number of failed nonlinear solves
4333 
4334    Notes:
4335    This counter is reset to zero for each successive call to TSSolve().
4336 
4337    Level: intermediate
4338 
4339 .keywords: TS, get, number
4340 
4341 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
4342 @*/
4343 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
4344 {
4345   PetscFunctionBegin;
4346   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4347   PetscValidIntPointer(fails,2);
4348   *fails = ts->num_snes_failures;
4349   PetscFunctionReturn(0);
4350 }
4351 
4352 #undef __FUNCT__
4353 #define __FUNCT__ "TSSetMaxStepRejections"
4354 /*@
4355    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
4356 
4357    Not Collective
4358 
4359    Input Parameter:
4360 +  ts - TS context
4361 -  rejects - maximum number of rejected steps, pass -1 for unlimited
4362 
4363    Notes:
4364    The counter is reset to zero for each step
4365 
4366    Options Database Key:
4367  .  -ts_max_reject - Maximum number of step rejections before a step fails
4368 
4369    Level: intermediate
4370 
4371 .keywords: TS, set, maximum, number
4372 
4373 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
4374 @*/
4375 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
4376 {
4377   PetscFunctionBegin;
4378   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4379   ts->max_reject = rejects;
4380   PetscFunctionReturn(0);
4381 }
4382 
4383 #undef __FUNCT__
4384 #define __FUNCT__ "TSSetMaxSNESFailures"
4385 /*@
4386    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
4387 
4388    Not Collective
4389 
4390    Input Parameter:
4391 +  ts - TS context
4392 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
4393 
4394    Notes:
4395    The counter is reset to zero for each successive call to TSSolve().
4396 
4397    Options Database Key:
4398  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
4399 
4400    Level: intermediate
4401 
4402 .keywords: TS, set, maximum, number
4403 
4404 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
4405 @*/
4406 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
4407 {
4408   PetscFunctionBegin;
4409   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4410   ts->max_snes_failures = fails;
4411   PetscFunctionReturn(0);
4412 }
4413 
4414 #undef __FUNCT__
4415 #define __FUNCT__ "TSSetErrorIfStepFails"
4416 /*@
4417    TSSetErrorIfStepFails - Error if no step succeeds
4418 
4419    Not Collective
4420 
4421    Input Parameter:
4422 +  ts - TS context
4423 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
4424 
4425    Options Database Key:
4426  .  -ts_error_if_step_fails - Error if no step succeeds
4427 
4428    Level: intermediate
4429 
4430 .keywords: TS, set, error
4431 
4432 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
4433 @*/
4434 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
4435 {
4436   PetscFunctionBegin;
4437   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4438   ts->errorifstepfailed = err;
4439   PetscFunctionReturn(0);
4440 }
4441 
4442 #undef __FUNCT__
4443 #define __FUNCT__ "TSMonitorSolutionBinary"
4444 /*@C
4445    TSMonitorSolutionBinary - Monitors progress of the TS solvers by VecView() for the solution at each timestep. Normally the viewer is a binary file
4446 
4447    Collective on TS
4448 
4449    Input Parameters:
4450 +  ts - the TS context
4451 .  step - current time-step
4452 .  ptime - current time
4453 .  u - current state
4454 -  viewer - binary viewer
4455 
4456    Level: intermediate
4457 
4458 .keywords: TS,  vector, monitor, view
4459 
4460 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4461 @*/
4462 PetscErrorCode  TSMonitorSolutionBinary(TS ts,PetscInt step,PetscReal ptime,Vec u,void *viewer)
4463 {
4464   PetscErrorCode ierr;
4465   PetscViewer    v = (PetscViewer)viewer;
4466 
4467   PetscFunctionBegin;
4468   ierr = VecView(u,v);CHKERRQ(ierr);
4469   PetscFunctionReturn(0);
4470 }
4471 
4472 #undef __FUNCT__
4473 #define __FUNCT__ "TSMonitorSolutionVTK"
4474 /*@C
4475    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
4476 
4477    Collective on TS
4478 
4479    Input Parameters:
4480 +  ts - the TS context
4481 .  step - current time-step
4482 .  ptime - current time
4483 .  u - current state
4484 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
4485 
4486    Level: intermediate
4487 
4488    Notes:
4489    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.
4490    These are named according to the file name template.
4491 
4492    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
4493 
4494 .keywords: TS,  vector, monitor, view
4495 
4496 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4497 @*/
4498 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
4499 {
4500   PetscErrorCode ierr;
4501   char           filename[PETSC_MAX_PATH_LEN];
4502   PetscViewer    viewer;
4503 
4504   PetscFunctionBegin;
4505   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
4506   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
4507   ierr = VecView(u,viewer);CHKERRQ(ierr);
4508   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4509   PetscFunctionReturn(0);
4510 }
4511 
4512 #undef __FUNCT__
4513 #define __FUNCT__ "TSMonitorSolutionVTKDestroy"
4514 /*@C
4515    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
4516 
4517    Collective on TS
4518 
4519    Input Parameters:
4520 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
4521 
4522    Level: intermediate
4523 
4524    Note:
4525    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
4526 
4527 .keywords: TS,  vector, monitor, view
4528 
4529 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
4530 @*/
4531 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
4532 {
4533   PetscErrorCode ierr;
4534 
4535   PetscFunctionBegin;
4536   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
4537   PetscFunctionReturn(0);
4538 }
4539 
4540 #undef __FUNCT__
4541 #define __FUNCT__ "TSGetAdapt"
4542 /*@
4543    TSGetAdapt - Get the adaptive controller context for the current method
4544 
4545    Collective on TS if controller has not been created yet
4546 
4547    Input Arguments:
4548 .  ts - time stepping context
4549 
4550    Output Arguments:
4551 .  adapt - adaptive controller
4552 
4553    Level: intermediate
4554 
4555 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
4556 @*/
4557 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
4558 {
4559   PetscErrorCode ierr;
4560 
4561   PetscFunctionBegin;
4562   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4563   PetscValidPointer(adapt,2);
4564   if (!ts->adapt) {
4565     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
4566     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt);CHKERRQ(ierr);
4567     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
4568   }
4569   *adapt = ts->adapt;
4570   PetscFunctionReturn(0);
4571 }
4572 
4573 #undef __FUNCT__
4574 #define __FUNCT__ "TSSetTolerances"
4575 /*@
4576    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
4577 
4578    Logically Collective
4579 
4580    Input Arguments:
4581 +  ts - time integration context
4582 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
4583 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
4584 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
4585 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
4586 
4587    Options Database keys:
4588 +  -ts_rtol <rtol> - relative tolerance for local truncation error
4589 -  -ts_atol <atol> Absolute tolerance for local truncation error
4590 
4591    Level: beginner
4592 
4593 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
4594 @*/
4595 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
4596 {
4597   PetscErrorCode ierr;
4598 
4599   PetscFunctionBegin;
4600   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
4601   if (vatol) {
4602     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
4603     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
4604 
4605     ts->vatol = vatol;
4606   }
4607   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
4608   if (vrtol) {
4609     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
4610     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
4611 
4612     ts->vrtol = vrtol;
4613   }
4614   PetscFunctionReturn(0);
4615 }
4616 
4617 #undef __FUNCT__
4618 #define __FUNCT__ "TSGetTolerances"
4619 /*@
4620    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
4621 
4622    Logically Collective
4623 
4624    Input Arguments:
4625 .  ts - time integration context
4626 
4627    Output Arguments:
4628 +  atol - scalar absolute tolerances, NULL to ignore
4629 .  vatol - vector of absolute tolerances, NULL to ignore
4630 .  rtol - scalar relative tolerances, NULL to ignore
4631 -  vrtol - vector of relative tolerances, NULL to ignore
4632 
4633    Level: beginner
4634 
4635 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
4636 @*/
4637 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
4638 {
4639   PetscFunctionBegin;
4640   if (atol)  *atol  = ts->atol;
4641   if (vatol) *vatol = ts->vatol;
4642   if (rtol)  *rtol  = ts->rtol;
4643   if (vrtol) *vrtol = ts->vrtol;
4644   PetscFunctionReturn(0);
4645 }
4646 
4647 #undef __FUNCT__
4648 #define __FUNCT__ "TSErrorNormWRMS"
4649 /*@
4650    TSErrorNormWRMS - compute a weighted norm of the difference between a vector and the current state
4651 
4652    Collective on TS
4653 
4654    Input Arguments:
4655 +  ts - time stepping context
4656 -  Y - state vector to be compared to ts->vec_sol
4657 
4658    Output Arguments:
4659 .  norm - weighted norm, a value of 1.0 is considered small
4660 
4661    Level: developer
4662 
4663 .seealso: TSSetTolerances()
4664 @*/
4665 PetscErrorCode TSErrorNormWRMS(TS ts,Vec Y,PetscReal *norm)
4666 {
4667   PetscErrorCode    ierr;
4668   PetscInt          i,n,N;
4669   const PetscScalar *u,*y;
4670   Vec               U;
4671   PetscReal         sum,gsum;
4672 
4673   PetscFunctionBegin;
4674   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4675   PetscValidHeaderSpecific(Y,VEC_CLASSID,2);
4676   PetscValidPointer(norm,3);
4677   U = ts->vec_sol;
4678   PetscCheckSameTypeAndComm(U,1,Y,2);
4679   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"Y cannot be the TS solution vector");
4680 
4681   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
4682   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
4683   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
4684   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
4685   sum  = 0.;
4686   if (ts->vatol && ts->vrtol) {
4687     const PetscScalar *atol,*rtol;
4688     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4689     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4690     for (i=0; i<n; i++) {
4691       PetscReal tol = PetscRealPart(atol[i]) + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4692       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4693     }
4694     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4695     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4696   } else if (ts->vatol) {       /* vector atol, scalar rtol */
4697     const PetscScalar *atol;
4698     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4699     for (i=0; i<n; i++) {
4700       PetscReal tol = PetscRealPart(atol[i]) + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4701       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4702     }
4703     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
4704   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
4705     const PetscScalar *rtol;
4706     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4707     for (i=0; i<n; i++) {
4708       PetscReal tol = ts->atol + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4709       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4710     }
4711     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
4712   } else {                      /* scalar atol, scalar rtol */
4713     for (i=0; i<n; i++) {
4714       PetscReal tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4715       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4716     }
4717   }
4718   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
4719   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
4720 
4721   ierr  = MPI_Allreduce(&sum,&gsum,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
4722   *norm = PetscSqrtReal(gsum / N);
4723   if (PetscIsInfOrNanReal(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
4724   PetscFunctionReturn(0);
4725 }
4726 
4727 #undef __FUNCT__
4728 #define __FUNCT__ "TSSetCFLTimeLocal"
4729 /*@
4730    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
4731 
4732    Logically Collective on TS
4733 
4734    Input Arguments:
4735 +  ts - time stepping context
4736 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
4737 
4738    Note:
4739    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
4740 
4741    Level: intermediate
4742 
4743 .seealso: TSGetCFLTime(), TSADAPTCFL
4744 @*/
4745 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
4746 {
4747   PetscFunctionBegin;
4748   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4749   ts->cfltime_local = cfltime;
4750   ts->cfltime       = -1.;
4751   PetscFunctionReturn(0);
4752 }
4753 
4754 #undef __FUNCT__
4755 #define __FUNCT__ "TSGetCFLTime"
4756 /*@
4757    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
4758 
4759    Collective on TS
4760 
4761    Input Arguments:
4762 .  ts - time stepping context
4763 
4764    Output Arguments:
4765 .  cfltime - maximum stable time step for forward Euler
4766 
4767    Level: advanced
4768 
4769 .seealso: TSSetCFLTimeLocal()
4770 @*/
4771 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
4772 {
4773   PetscErrorCode ierr;
4774 
4775   PetscFunctionBegin;
4776   if (ts->cfltime < 0) {
4777     ierr = MPI_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
4778   }
4779   *cfltime = ts->cfltime;
4780   PetscFunctionReturn(0);
4781 }
4782 
4783 #undef __FUNCT__
4784 #define __FUNCT__ "TSVISetVariableBounds"
4785 /*@
4786    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
4787 
4788    Input Parameters:
4789 .  ts   - the TS context.
4790 .  xl   - lower bound.
4791 .  xu   - upper bound.
4792 
4793    Notes:
4794    If this routine is not called then the lower and upper bounds are set to
4795    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
4796 
4797    Level: advanced
4798 
4799 @*/
4800 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
4801 {
4802   PetscErrorCode ierr;
4803   SNES           snes;
4804 
4805   PetscFunctionBegin;
4806   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4807   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
4808   PetscFunctionReturn(0);
4809 }
4810 
4811 #if defined(PETSC_HAVE_MATLAB_ENGINE)
4812 #include <mex.h>
4813 
4814 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
4815 
4816 #undef __FUNCT__
4817 #define __FUNCT__ "TSComputeFunction_Matlab"
4818 /*
4819    TSComputeFunction_Matlab - Calls the function that has been set with
4820                          TSSetFunctionMatlab().
4821 
4822    Collective on TS
4823 
4824    Input Parameters:
4825 +  snes - the TS context
4826 -  u - input vector
4827 
4828    Output Parameter:
4829 .  y - function vector, as set by TSSetFunction()
4830 
4831    Notes:
4832    TSComputeFunction() is typically used within nonlinear solvers
4833    implementations, so most users would not generally call this routine
4834    themselves.
4835 
4836    Level: developer
4837 
4838 .keywords: TS, nonlinear, compute, function
4839 
4840 .seealso: TSSetFunction(), TSGetFunction()
4841 */
4842 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
4843 {
4844   PetscErrorCode  ierr;
4845   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4846   int             nlhs  = 1,nrhs = 7;
4847   mxArray         *plhs[1],*prhs[7];
4848   long long int   lx = 0,lxdot = 0,ly = 0,ls = 0;
4849 
4850   PetscFunctionBegin;
4851   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
4852   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
4853   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
4854   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
4855   PetscCheckSameComm(snes,1,u,3);
4856   PetscCheckSameComm(snes,1,y,5);
4857 
4858   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
4859   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4860   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
4861   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
4862 
4863   prhs[0] =  mxCreateDoubleScalar((double)ls);
4864   prhs[1] =  mxCreateDoubleScalar(time);
4865   prhs[2] =  mxCreateDoubleScalar((double)lx);
4866   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
4867   prhs[4] =  mxCreateDoubleScalar((double)ly);
4868   prhs[5] =  mxCreateString(sctx->funcname);
4869   prhs[6] =  sctx->ctx;
4870   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
4871   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4872   mxDestroyArray(prhs[0]);
4873   mxDestroyArray(prhs[1]);
4874   mxDestroyArray(prhs[2]);
4875   mxDestroyArray(prhs[3]);
4876   mxDestroyArray(prhs[4]);
4877   mxDestroyArray(prhs[5]);
4878   mxDestroyArray(plhs[0]);
4879   PetscFunctionReturn(0);
4880 }
4881 
4882 
4883 #undef __FUNCT__
4884 #define __FUNCT__ "TSSetFunctionMatlab"
4885 /*
4886    TSSetFunctionMatlab - Sets the function evaluation routine and function
4887    vector for use by the TS routines in solving ODEs
4888    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
4889 
4890    Logically Collective on TS
4891 
4892    Input Parameters:
4893 +  ts - the TS context
4894 -  func - function evaluation routine
4895 
4896    Calling sequence of func:
4897 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
4898 
4899    Level: beginner
4900 
4901 .keywords: TS, nonlinear, set, function
4902 
4903 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4904 */
4905 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
4906 {
4907   PetscErrorCode  ierr;
4908   TSMatlabContext *sctx;
4909 
4910   PetscFunctionBegin;
4911   /* currently sctx is memory bleed */
4912   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
4913   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
4914   /*
4915      This should work, but it doesn't
4916   sctx->ctx = ctx;
4917   mexMakeArrayPersistent(sctx->ctx);
4918   */
4919   sctx->ctx = mxDuplicateArray(ctx);
4920 
4921   ierr = TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
4922   PetscFunctionReturn(0);
4923 }
4924 
4925 #undef __FUNCT__
4926 #define __FUNCT__ "TSComputeJacobian_Matlab"
4927 /*
4928    TSComputeJacobian_Matlab - Calls the function that has been set with
4929                          TSSetJacobianMatlab().
4930 
4931    Collective on TS
4932 
4933    Input Parameters:
4934 +  ts - the TS context
4935 .  u - input vector
4936 .  A, B - the matrices
4937 -  ctx - user context
4938 
4939    Level: developer
4940 
4941 .keywords: TS, nonlinear, compute, function
4942 
4943 .seealso: TSSetFunction(), TSGetFunction()
4944 @*/
4945 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat A,Mat B,void *ctx)
4946 {
4947   PetscErrorCode  ierr;
4948   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4949   int             nlhs  = 2,nrhs = 9;
4950   mxArray         *plhs[2],*prhs[9];
4951   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
4952 
4953   PetscFunctionBegin;
4954   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4955   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
4956 
4957   /* call Matlab function in ctx with arguments u and y */
4958 
4959   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
4960   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4961   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
4962   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
4963   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
4964 
4965   prhs[0] =  mxCreateDoubleScalar((double)ls);
4966   prhs[1] =  mxCreateDoubleScalar((double)time);
4967   prhs[2] =  mxCreateDoubleScalar((double)lx);
4968   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
4969   prhs[4] =  mxCreateDoubleScalar((double)shift);
4970   prhs[5] =  mxCreateDoubleScalar((double)lA);
4971   prhs[6] =  mxCreateDoubleScalar((double)lB);
4972   prhs[7] =  mxCreateString(sctx->funcname);
4973   prhs[8] =  sctx->ctx;
4974   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
4975   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4976   mxDestroyArray(prhs[0]);
4977   mxDestroyArray(prhs[1]);
4978   mxDestroyArray(prhs[2]);
4979   mxDestroyArray(prhs[3]);
4980   mxDestroyArray(prhs[4]);
4981   mxDestroyArray(prhs[5]);
4982   mxDestroyArray(prhs[6]);
4983   mxDestroyArray(prhs[7]);
4984   mxDestroyArray(plhs[0]);
4985   mxDestroyArray(plhs[1]);
4986   PetscFunctionReturn(0);
4987 }
4988 
4989 
4990 #undef __FUNCT__
4991 #define __FUNCT__ "TSSetJacobianMatlab"
4992 /*
4993    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
4994    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
4995 
4996    Logically Collective on TS
4997 
4998    Input Parameters:
4999 +  ts - the TS context
5000 .  A,B - Jacobian matrices
5001 .  func - function evaluation routine
5002 -  ctx - user context
5003 
5004    Calling sequence of func:
5005 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
5006 
5007 
5008    Level: developer
5009 
5010 .keywords: TS, nonlinear, set, function
5011 
5012 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
5013 */
5014 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
5015 {
5016   PetscErrorCode  ierr;
5017   TSMatlabContext *sctx;
5018 
5019   PetscFunctionBegin;
5020   /* currently sctx is memory bleed */
5021   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
5022   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
5023   /*
5024      This should work, but it doesn't
5025   sctx->ctx = ctx;
5026   mexMakeArrayPersistent(sctx->ctx);
5027   */
5028   sctx->ctx = mxDuplicateArray(ctx);
5029 
5030   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
5031   PetscFunctionReturn(0);
5032 }
5033 
5034 #undef __FUNCT__
5035 #define __FUNCT__ "TSMonitor_Matlab"
5036 /*
5037    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
5038 
5039    Collective on TS
5040 
5041 .seealso: TSSetFunction(), TSGetFunction()
5042 @*/
5043 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
5044 {
5045   PetscErrorCode  ierr;
5046   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
5047   int             nlhs  = 1,nrhs = 6;
5048   mxArray         *plhs[1],*prhs[6];
5049   long long int   lx = 0,ls = 0;
5050 
5051   PetscFunctionBegin;
5052   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5053   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
5054 
5055   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
5056   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
5057 
5058   prhs[0] =  mxCreateDoubleScalar((double)ls);
5059   prhs[1] =  mxCreateDoubleScalar((double)it);
5060   prhs[2] =  mxCreateDoubleScalar((double)time);
5061   prhs[3] =  mxCreateDoubleScalar((double)lx);
5062   prhs[4] =  mxCreateString(sctx->funcname);
5063   prhs[5] =  sctx->ctx;
5064   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
5065   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
5066   mxDestroyArray(prhs[0]);
5067   mxDestroyArray(prhs[1]);
5068   mxDestroyArray(prhs[2]);
5069   mxDestroyArray(prhs[3]);
5070   mxDestroyArray(prhs[4]);
5071   mxDestroyArray(plhs[0]);
5072   PetscFunctionReturn(0);
5073 }
5074 
5075 
5076 #undef __FUNCT__
5077 #define __FUNCT__ "TSMonitorSetMatlab"
5078 /*
5079    TSMonitorSetMatlab - Sets the monitor function from Matlab
5080 
5081    Level: developer
5082 
5083 .keywords: TS, nonlinear, set, function
5084 
5085 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
5086 */
5087 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
5088 {
5089   PetscErrorCode  ierr;
5090   TSMatlabContext *sctx;
5091 
5092   PetscFunctionBegin;
5093   /* currently sctx is memory bleed */
5094   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
5095   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
5096   /*
5097      This should work, but it doesn't
5098   sctx->ctx = ctx;
5099   mexMakeArrayPersistent(sctx->ctx);
5100   */
5101   sctx->ctx = mxDuplicateArray(ctx);
5102 
5103   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);CHKERRQ(ierr);
5104   PetscFunctionReturn(0);
5105 }
5106 #endif
5107 
5108 
5109 
5110 #undef __FUNCT__
5111 #define __FUNCT__ "TSMonitorLGSolution"
5112 /*@C
5113    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
5114        in a time based line graph
5115 
5116    Collective on TS
5117 
5118    Input Parameters:
5119 +  ts - the TS context
5120 .  step - current time-step
5121 .  ptime - current time
5122 -  lg - a line graph object
5123 
5124    Level: intermediate
5125 
5126     Notes: each process in a parallel run displays its component solutions in a separate window
5127 
5128 .keywords: TS,  vector, monitor, view
5129 
5130 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5131 @*/
5132 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5133 {
5134   PetscErrorCode    ierr;
5135   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
5136   const PetscScalar *yy;
5137   PetscInt          dim;
5138 
5139   PetscFunctionBegin;
5140   if (!step) {
5141     PetscDrawAxis axis;
5142     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
5143     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
5144     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
5145     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
5146     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
5147   }
5148   ierr = VecGetArrayRead(u,&yy);CHKERRQ(ierr);
5149 #if defined(PETSC_USE_COMPLEX)
5150   {
5151     PetscReal *yreal;
5152     PetscInt  i,n;
5153     ierr = VecGetLocalSize(u,&n);CHKERRQ(ierr);
5154     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
5155     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
5156     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
5157     ierr = PetscFree(yreal);CHKERRQ(ierr);
5158   }
5159 #else
5160   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
5161 #endif
5162   ierr = VecRestoreArrayRead(u,&yy);CHKERRQ(ierr);
5163   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
5164     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
5165   }
5166   PetscFunctionReturn(0);
5167 }
5168 
5169 #undef __FUNCT__
5170 #define __FUNCT__ "TSMonitorLGError"
5171 /*@C
5172    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the solution vector
5173        in a time based line graph
5174 
5175    Collective on TS
5176 
5177    Input Parameters:
5178 +  ts - the TS context
5179 .  step - current time-step
5180 .  ptime - current time
5181 -  lg - a line graph object
5182 
5183    Level: intermediate
5184 
5185    Notes:
5186    Only for sequential solves.
5187 
5188    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
5189 
5190    Options Database Keys:
5191 .  -ts_monitor_lg_error - create a graphical monitor of error history
5192 
5193 .keywords: TS,  vector, monitor, view
5194 
5195 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
5196 @*/
5197 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5198 {
5199   PetscErrorCode    ierr;
5200   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
5201   const PetscScalar *yy;
5202   Vec               y;
5203   PetscInt          dim;
5204 
5205   PetscFunctionBegin;
5206   if (!step) {
5207     PetscDrawAxis axis;
5208     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
5209     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Solution");CHKERRQ(ierr);
5210     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
5211     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
5212     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
5213   }
5214   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
5215   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
5216   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
5217   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
5218 #if defined(PETSC_USE_COMPLEX)
5219   {
5220     PetscReal *yreal;
5221     PetscInt  i,n;
5222     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
5223     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
5224     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
5225     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
5226     ierr = PetscFree(yreal);CHKERRQ(ierr);
5227   }
5228 #else
5229   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
5230 #endif
5231   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
5232   ierr = VecDestroy(&y);CHKERRQ(ierr);
5233   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
5234     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
5235   }
5236   PetscFunctionReturn(0);
5237 }
5238 
5239 #undef __FUNCT__
5240 #define __FUNCT__ "TSMonitorLGSNESIterations"
5241 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
5242 {
5243   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
5244   PetscReal      x   = ptime,y;
5245   PetscErrorCode ierr;
5246   PetscInt       its;
5247 
5248   PetscFunctionBegin;
5249   if (!n) {
5250     PetscDrawAxis axis;
5251 
5252     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
5253     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
5254     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
5255 
5256     ctx->snes_its = 0;
5257   }
5258   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
5259   y    = its - ctx->snes_its;
5260   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
5261   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
5262     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
5263   }
5264   ctx->snes_its = its;
5265   PetscFunctionReturn(0);
5266 }
5267 
5268 #undef __FUNCT__
5269 #define __FUNCT__ "TSMonitorLGKSPIterations"
5270 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
5271 {
5272   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
5273   PetscReal      x   = ptime,y;
5274   PetscErrorCode ierr;
5275   PetscInt       its;
5276 
5277   PetscFunctionBegin;
5278   if (!n) {
5279     PetscDrawAxis axis;
5280 
5281     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
5282     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
5283     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
5284 
5285     ctx->ksp_its = 0;
5286   }
5287   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
5288   y    = its - ctx->ksp_its;
5289   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
5290   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
5291     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
5292   }
5293   ctx->ksp_its = its;
5294   PetscFunctionReturn(0);
5295 }
5296 
5297 #undef __FUNCT__
5298 #define __FUNCT__ "TSComputeLinearStability"
5299 /*@
5300    TSComputeLinearStability - computes the linear stability function at a point
5301 
5302    Collective on TS and Vec
5303 
5304    Input Parameters:
5305 +  ts - the TS context
5306 -  xr,xi - real and imaginary part of input arguments
5307 
5308    Output Parameters:
5309 .  yr,yi - real and imaginary part of function value
5310 
5311    Level: developer
5312 
5313 .keywords: TS, compute
5314 
5315 .seealso: TSSetRHSFunction(), TSComputeIFunction()
5316 @*/
5317 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
5318 {
5319   PetscErrorCode ierr;
5320 
5321   PetscFunctionBegin;
5322   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5323   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
5324   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
5325   PetscFunctionReturn(0);
5326 }
5327 
5328 #undef __FUNCT__
5329 #define __FUNCT__ "TSRollBack"
5330 /*@
5331    TSRollBack - Rolls back one time step
5332 
5333    Collective on TS
5334 
5335    Input Parameter:
5336 .  ts - the TS context obtained from TSCreate()
5337 
5338    Level: advanced
5339 
5340 .keywords: TS, timestep, rollback
5341 
5342 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
5343 @*/
5344 PetscErrorCode  TSRollBack(TS ts)
5345 {
5346   PetscErrorCode ierr;
5347 
5348   PetscFunctionBegin;
5349   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
5350 
5351   if (!ts->ops->rollback) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
5352   ierr = (*ts->ops->rollback)(ts);CHKERRQ(ierr);
5353   ts->time_step = ts->ptime - ts->ptime_prev;
5354   ts->ptime = ts->ptime_prev;
5355   PetscFunctionReturn(0);
5356 }
5357 
5358 #undef __FUNCT__
5359 #define __FUNCT__ "TSGetStages"
5360 /*@
5361    TSGetStages - Get the number of stages and stage values
5362 
5363    Input Parameter:
5364 .  ts - the TS context obtained from TSCreate()
5365 
5366    Level: advanced
5367 
5368 .keywords: TS, getstages
5369 
5370 .seealso: TSCreate()
5371 @*/
5372 PetscErrorCode  TSGetStages(TS ts,PetscInt *ns, Vec **Y)
5373 {
5374   PetscErrorCode ierr;
5375 
5376   PetscFunctionBegin;
5377   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
5378   PetscValidPointer(ns,2);
5379 
5380   if (!ts->ops->getstages) *ns=0;
5381   else {
5382     ierr = (*ts->ops->getstages)(ts,ns,Y);CHKERRQ(ierr);
5383   }
5384   PetscFunctionReturn(0);
5385 }
5386 
5387 
5388 
5389