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