xref: /petsc/src/ts/interface/ts.c (revision 4ef6a029aa25b09a45e791656fccb2385233bf9b)
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 
1996   ierr = VecDestroyVecs(ts->numcost,&ts->vecs_drdy);CHKERRQ(ierr);
1997   if (ts->vecs_drdp){
1998     ierr = VecDestroyVecs(ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
1999   }
2000   ts->vecs_sensi  = NULL;
2001   ts->vecs_sensip = NULL;
2002   ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
2003   ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr);
2004   ierr = VecDestroy(&ts->vec_costintegrand);CHKERRQ(ierr);
2005   ts->setupcalled = PETSC_FALSE;
2006   PetscFunctionReturn(0);
2007 }
2008 
2009 #undef __FUNCT__
2010 #define __FUNCT__ "TSDestroy"
2011 /*@
2012    TSDestroy - Destroys the timestepper context that was created
2013    with TSCreate().
2014 
2015    Collective on TS
2016 
2017    Input Parameter:
2018 .  ts - the TS context obtained from TSCreate()
2019 
2020    Level: beginner
2021 
2022 .keywords: TS, timestepper, destroy
2023 
2024 .seealso: TSCreate(), TSSetUp(), TSSolve()
2025 @*/
2026 PetscErrorCode  TSDestroy(TS *ts)
2027 {
2028   PetscErrorCode ierr;
2029 
2030   PetscFunctionBegin;
2031   if (!*ts) PetscFunctionReturn(0);
2032   PetscValidHeaderSpecific((*ts),TS_CLASSID,1);
2033   if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; PetscFunctionReturn(0);}
2034 
2035   ierr = TSReset((*ts));CHKERRQ(ierr);
2036 
2037   /* if memory was published with SAWs then destroy it */
2038   ierr = PetscObjectSAWsViewOff((PetscObject)*ts);CHKERRQ(ierr);
2039   if ((*ts)->ops->destroy) {ierr = (*(*ts)->ops->destroy)((*ts));CHKERRQ(ierr);}
2040 
2041   ierr = TSTrajectoryDestroy(&(*ts)->trajectory);CHKERRQ(ierr);
2042 
2043   ierr = TSAdaptDestroy(&(*ts)->adapt);CHKERRQ(ierr);
2044   if ((*ts)->event) {
2045     ierr = TSEventMonitorDestroy(&(*ts)->event);CHKERRQ(ierr);
2046   }
2047   ierr = SNESDestroy(&(*ts)->snes);CHKERRQ(ierr);
2048   ierr = DMDestroy(&(*ts)->dm);CHKERRQ(ierr);
2049   ierr = TSMonitorCancel((*ts));CHKERRQ(ierr);
2050 
2051   ierr = PetscHeaderDestroy(ts);CHKERRQ(ierr);
2052   PetscFunctionReturn(0);
2053 }
2054 
2055 #undef __FUNCT__
2056 #define __FUNCT__ "TSGetSNES"
2057 /*@
2058    TSGetSNES - Returns the SNES (nonlinear solver) associated with
2059    a TS (timestepper) context. Valid only for nonlinear problems.
2060 
2061    Not Collective, but SNES is parallel if TS is parallel
2062 
2063    Input Parameter:
2064 .  ts - the TS context obtained from TSCreate()
2065 
2066    Output Parameter:
2067 .  snes - the nonlinear solver context
2068 
2069    Notes:
2070    The user can then directly manipulate the SNES context to set various
2071    options, etc.  Likewise, the user can then extract and manipulate the
2072    KSP, KSP, and PC contexts as well.
2073 
2074    TSGetSNES() does not work for integrators that do not use SNES; in
2075    this case TSGetSNES() returns NULL in snes.
2076 
2077    Level: beginner
2078 
2079 .keywords: timestep, get, SNES
2080 @*/
2081 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
2082 {
2083   PetscErrorCode ierr;
2084 
2085   PetscFunctionBegin;
2086   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2087   PetscValidPointer(snes,2);
2088   if (!ts->snes) {
2089     ierr = SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes);CHKERRQ(ierr);
2090     ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2091     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->snes);CHKERRQ(ierr);
2092     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);CHKERRQ(ierr);
2093     if (ts->dm) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
2094     if (ts->problem_type == TS_LINEAR) {
2095       ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr);
2096     }
2097   }
2098   *snes = ts->snes;
2099   PetscFunctionReturn(0);
2100 }
2101 
2102 #undef __FUNCT__
2103 #define __FUNCT__ "TSSetSNES"
2104 /*@
2105    TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
2106 
2107    Collective
2108 
2109    Input Parameter:
2110 +  ts - the TS context obtained from TSCreate()
2111 -  snes - the nonlinear solver context
2112 
2113    Notes:
2114    Most users should have the TS created by calling TSGetSNES()
2115 
2116    Level: developer
2117 
2118 .keywords: timestep, set, SNES
2119 @*/
2120 PetscErrorCode TSSetSNES(TS ts,SNES snes)
2121 {
2122   PetscErrorCode ierr;
2123   PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*);
2124 
2125   PetscFunctionBegin;
2126   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2127   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
2128   ierr = PetscObjectReference((PetscObject)snes);CHKERRQ(ierr);
2129   ierr = SNESDestroy(&ts->snes);CHKERRQ(ierr);
2130 
2131   ts->snes = snes;
2132 
2133   ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2134   ierr = SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL);CHKERRQ(ierr);
2135   if (func == SNESTSFormJacobian) {
2136     ierr = SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts);CHKERRQ(ierr);
2137   }
2138   PetscFunctionReturn(0);
2139 }
2140 
2141 #undef __FUNCT__
2142 #define __FUNCT__ "TSGetKSP"
2143 /*@
2144    TSGetKSP - Returns the KSP (linear solver) associated with
2145    a TS (timestepper) context.
2146 
2147    Not Collective, but KSP is parallel if TS is parallel
2148 
2149    Input Parameter:
2150 .  ts - the TS context obtained from TSCreate()
2151 
2152    Output Parameter:
2153 .  ksp - the nonlinear solver context
2154 
2155    Notes:
2156    The user can then directly manipulate the KSP context to set various
2157    options, etc.  Likewise, the user can then extract and manipulate the
2158    KSP and PC contexts as well.
2159 
2160    TSGetKSP() does not work for integrators that do not use KSP;
2161    in this case TSGetKSP() returns NULL in ksp.
2162 
2163    Level: beginner
2164 
2165 .keywords: timestep, get, KSP
2166 @*/
2167 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
2168 {
2169   PetscErrorCode ierr;
2170   SNES           snes;
2171 
2172   PetscFunctionBegin;
2173   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2174   PetscValidPointer(ksp,2);
2175   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
2176   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
2177   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2178   ierr = SNESGetKSP(snes,ksp);CHKERRQ(ierr);
2179   PetscFunctionReturn(0);
2180 }
2181 
2182 /* ----------- Routines to set solver parameters ---------- */
2183 
2184 #undef __FUNCT__
2185 #define __FUNCT__ "TSGetDuration"
2186 /*@
2187    TSGetDuration - Gets the maximum number of timesteps to use and
2188    maximum time for iteration.
2189 
2190    Not Collective
2191 
2192    Input Parameters:
2193 +  ts       - the TS context obtained from TSCreate()
2194 .  maxsteps - maximum number of iterations to use, or NULL
2195 -  maxtime  - final time to iterate to, or NULL
2196 
2197    Level: intermediate
2198 
2199 .keywords: TS, timestep, get, maximum, iterations, time
2200 @*/
2201 PetscErrorCode  TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
2202 {
2203   PetscFunctionBegin;
2204   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2205   if (maxsteps) {
2206     PetscValidIntPointer(maxsteps,2);
2207     *maxsteps = ts->max_steps;
2208   }
2209   if (maxtime) {
2210     PetscValidScalarPointer(maxtime,3);
2211     *maxtime = ts->max_time;
2212   }
2213   PetscFunctionReturn(0);
2214 }
2215 
2216 #undef __FUNCT__
2217 #define __FUNCT__ "TSSetDuration"
2218 /*@
2219    TSSetDuration - Sets the maximum number of timesteps to use and
2220    maximum time for iteration.
2221 
2222    Logically Collective on TS
2223 
2224    Input Parameters:
2225 +  ts - the TS context obtained from TSCreate()
2226 .  maxsteps - maximum number of iterations to use
2227 -  maxtime - final time to iterate to
2228 
2229    Options Database Keys:
2230 .  -ts_max_steps <maxsteps> - Sets maxsteps
2231 .  -ts_final_time <maxtime> - Sets maxtime
2232 
2233    Notes:
2234    The default maximum number of iterations is 5000. Default time is 5.0
2235 
2236    Level: intermediate
2237 
2238 .keywords: TS, timestep, set, maximum, iterations
2239 
2240 .seealso: TSSetExactFinalTime()
2241 @*/
2242 PetscErrorCode  TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
2243 {
2244   PetscFunctionBegin;
2245   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2246   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
2247   PetscValidLogicalCollectiveReal(ts,maxtime,2);
2248   if (maxsteps >= 0) ts->max_steps = maxsteps;
2249   if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
2250   PetscFunctionReturn(0);
2251 }
2252 
2253 #undef __FUNCT__
2254 #define __FUNCT__ "TSSetSolution"
2255 /*@
2256    TSSetSolution - Sets the initial solution vector
2257    for use by the TS routines.
2258 
2259    Logically Collective on TS and Vec
2260 
2261    Input Parameters:
2262 +  ts - the TS context obtained from TSCreate()
2263 -  u - the solution vector
2264 
2265    Level: beginner
2266 
2267 .keywords: TS, timestep, set, solution, initial conditions
2268 @*/
2269 PetscErrorCode  TSSetSolution(TS ts,Vec u)
2270 {
2271   PetscErrorCode ierr;
2272   DM             dm;
2273 
2274   PetscFunctionBegin;
2275   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2276   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
2277   ierr = PetscObjectReference((PetscObject)u);CHKERRQ(ierr);
2278   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
2279 
2280   ts->vec_sol = u;
2281 
2282   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2283   ierr = DMShellSetGlobalVector(dm,u);CHKERRQ(ierr);
2284   PetscFunctionReturn(0);
2285 }
2286 
2287 #undef __FUNCT__
2288 #define __FUNCT__ "TSAdjointSetSteps"
2289 /*@
2290    TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time
2291 
2292    Logically Collective on TS
2293 
2294    Input Parameters:
2295 +  ts - the TS context obtained from TSCreate()
2296 .  steps - number of steps to use
2297 
2298    Level: intermediate
2299 
2300    Notes: Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this
2301           so as to integrate back to less than the original timestep
2302 
2303 .keywords: TS, timestep, set, maximum, iterations
2304 
2305 .seealso: TSSetExactFinalTime()
2306 @*/
2307 PetscErrorCode  TSAdjointSetSteps(TS ts,PetscInt steps)
2308 {
2309   PetscFunctionBegin;
2310   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2311   PetscValidLogicalCollectiveInt(ts,steps,2);
2312   if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps");
2313   if (steps > ts->total_steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps");
2314   ts->adjoint_max_steps = steps;
2315   PetscFunctionReturn(0);
2316 }
2317 
2318 #undef __FUNCT__
2319 #define __FUNCT__ "TSSetCostGradients"
2320 /*@
2321    TSSetCostGradients - Sets the initial value of the gradients of the cost function w.r.t. initial conditions and w.r.t. the problem parameters
2322       for use by the TSAdjoint routines.
2323 
2324    Logically Collective on TS and Vec
2325 
2326    Input Parameters:
2327 +  ts - the TS context obtained from TSCreate()
2328 .  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
2329 -  mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
2330 
2331    Level: beginner
2332 
2333    Notes: the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime  mu_i = df/dp|finaltime
2334 
2335 .keywords: TS, timestep, set, sensitivity, initial conditions
2336 @*/
2337 PetscErrorCode  TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu)
2338 {
2339   PetscFunctionBegin;
2340   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2341   PetscValidPointer(lambda,2);
2342   ts->vecs_sensi  = lambda;
2343   ts->vecs_sensip = mu;
2344   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");
2345   ts->numcost  = numcost;
2346   PetscFunctionReturn(0);
2347 }
2348 
2349 #undef __FUNCT__
2350 #define __FUNCT__ "TSAdjointSetRHSJacobian"
2351 /*@C
2352   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.
2353 
2354   Logically Collective on TS
2355 
2356   Input Parameters:
2357 + ts   - The TS context obtained from TSCreate()
2358 - func - The function
2359 
2360   Calling sequence of func:
2361 $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx);
2362 +   t - current timestep
2363 .   y - input vector (current ODE solution)
2364 .   A - output matrix
2365 -   ctx - [optional] user-defined function context
2366 
2367   Level: intermediate
2368 
2369   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
2370 
2371 .keywords: TS, sensitivity
2372 .seealso:
2373 @*/
2374 PetscErrorCode  TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
2375 {
2376   PetscErrorCode ierr;
2377 
2378   PetscFunctionBegin;
2379   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2380   if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
2381 
2382   ts->rhsjacobianp    = func;
2383   ts->rhsjacobianpctx = ctx;
2384   if(Amat) {
2385     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
2386     ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
2387     ts->Jacp = Amat;
2388   }
2389   PetscFunctionReturn(0);
2390 }
2391 
2392 #undef __FUNCT__
2393 #define __FUNCT__ "TSAdjointComputeRHSJacobian"
2394 /*@C
2395   TSAdjointComputeRHSJacobian - Runs the user-defined Jacobian function.
2396 
2397   Collective on TS
2398 
2399   Input Parameters:
2400 . ts   - The TS context obtained from TSCreate()
2401 
2402   Level: developer
2403 
2404 .keywords: TS, sensitivity
2405 .seealso: TSAdjointSetRHSJacobian()
2406 @*/
2407 PetscErrorCode  TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec X,Mat Amat)
2408 {
2409   PetscErrorCode ierr;
2410 
2411   PetscFunctionBegin;
2412   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2413   PetscValidHeaderSpecific(X,VEC_CLASSID,3);
2414   PetscValidPointer(Amat,4);
2415 
2416   PetscStackPush("TS user JacobianP function for sensitivity analysis");
2417   ierr = (*ts->rhsjacobianp)(ts,t,X,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr);
2418   PetscStackPop;
2419   PetscFunctionReturn(0);
2420 }
2421 
2422 #undef __FUNCT__
2423 #define __FUNCT__ "TSSetCostIntegrand"
2424 /*@C
2425     TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions
2426 
2427     Logically Collective on TS
2428 
2429     Input Parameters:
2430 +   ts - the TS context obtained from TSCreate()
2431 .   numcost - number of gradients to be computed, this is the number of cost functions
2432 .   rf - routine for evaluating the integrand function
2433 .   drdyf - function that computes the gradients of the r's with respect to y,NULL if not a function y
2434 .   drdpf - function that computes the gradients of the r's with respect to p, NULL if not a function of p
2435 -   ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
2436 
2437     Calling sequence of rf:
2438 $     rf(TS ts,PetscReal t,Vec y,Vec f[],void *ctx);
2439 
2440 +   t - current timestep
2441 .   y - input vector
2442 .   f - function result; one vector entry for each cost function
2443 -   ctx - [optional] user-defined function context
2444 
2445    Calling sequence of drdyf:
2446 $    PetscErroCode drdyf(TS ts,PetscReal t,Vec y,Vec *drdy,void *ctx);
2447 
2448    Calling sequence of drdpf:
2449 $    PetscErroCode drdpf(TS ts,PetscReal t,Vec y,Vec *drdp,void *ctx);
2450 
2451     Level: intermediate
2452 
2453     Notes: For optimization there is generally a single cost function, numcost = 1. For sensitivities there may be multiple cost functions
2454 
2455 .keywords: TS, sensitivity analysis, timestep, set, quadrature, function
2456 
2457 .seealso: TSAdjointSetRHSJacobian(),TSGetCostGradients(), TSSetCostGradients()
2458 @*/
2459 PetscErrorCode  TSSetCostIntegrand(TS ts,PetscInt numcost, PetscErrorCode (*rf)(TS,PetscReal,Vec,Vec,void*),
2460                                                                   PetscErrorCode (*drdyf)(TS,PetscReal,Vec,Vec*,void*),
2461                                                                   PetscErrorCode (*drdpf)(TS,PetscReal,Vec,Vec*,void*),void *ctx)
2462 {
2463   PetscErrorCode ierr;
2464 
2465   PetscFunctionBegin;
2466   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2467   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()");
2468   if (!ts->numcost) ts->numcost=numcost;
2469 
2470   ierr                  = VecCreateSeq(PETSC_COMM_SELF,numcost,&ts->vec_costintegral);CHKERRQ(ierr);
2471   ierr                  = VecDuplicate(ts->vec_costintegral,&ts->vec_costintegrand);CHKERRQ(ierr);
2472   ts->costintegrand     = rf;
2473   ts->costintegrandctx  = ctx;
2474   ts->drdyfunction    = drdyf;
2475   ts->drdpfunction    = drdpf;
2476   PetscFunctionReturn(0);
2477 }
2478 
2479 #undef __FUNCT__
2480 #define __FUNCT__ "TSGetCostIntegral"
2481 /*@
2482    TSGetCostIntegral - Returns the values of the integral term in the cost functions.
2483    It is valid to call the routine after a backward run.
2484 
2485    Not Collective
2486 
2487    Input Parameter:
2488 .  ts - the TS context obtained from TSCreate()
2489 
2490    Output Parameter:
2491 .  v - the vector containing the integrals for each cost function
2492 
2493    Level: intermediate
2494 
2495 .seealso: TSSetCostIntegrand()
2496 
2497 .keywords: TS, sensitivity analysis
2498 @*/
2499 PetscErrorCode  TSGetCostIntegral(TS ts,Vec *v)
2500 {
2501   PetscFunctionBegin;
2502   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2503   PetscValidPointer(v,2);
2504   *v = ts->vec_costintegral;
2505   PetscFunctionReturn(0);
2506 }
2507 
2508 #undef __FUNCT__
2509 #define __FUNCT__ "TSAdjointComputeCostIntegrand"
2510 /*@
2511    TSAdjointComputeCostIntegrand - Evaluates the integral function in the cost functions.
2512 
2513    Input Parameters:
2514 +  ts - the TS context
2515 .  t - current time
2516 -  y - state vector, i.e. current solution
2517 
2518    Output Parameter:
2519 .  q - vector of size numcost to hold the outputs
2520 
2521    Note:
2522    Most users should not need to explicitly call this routine, as it
2523    is used internally within the sensitivity analysis context.
2524 
2525    Level: developer
2526 
2527 .keywords: TS, compute
2528 
2529 .seealso: TSSetCostIntegrand()
2530 @*/
2531 PetscErrorCode TSAdjointComputeCostIntegrand(TS ts,PetscReal t,Vec y,Vec q)
2532 {
2533   PetscErrorCode ierr;
2534 
2535   PetscFunctionBegin;
2536   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2537   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2538   PetscValidHeaderSpecific(q,VEC_CLASSID,4);
2539 
2540   ierr = PetscLogEventBegin(TS_FunctionEval,ts,y,q,0);CHKERRQ(ierr);
2541   if (ts->costintegrand) {
2542     PetscStackPush("TS user integrand in the cost function");
2543     ierr = (*ts->costintegrand)(ts,t,y,q,ts->costintegrandctx);CHKERRQ(ierr);
2544     PetscStackPop;
2545   } else {
2546     ierr = VecZeroEntries(q);CHKERRQ(ierr);
2547   }
2548 
2549   ierr = PetscLogEventEnd(TS_FunctionEval,ts,y,q,0);CHKERRQ(ierr);
2550   PetscFunctionReturn(0);
2551 }
2552 
2553 #undef __FUNCT__
2554 #define __FUNCT__ "TSAdjointComputeDRDYFunction"
2555 /*@
2556   TSAdjointComputeDRDYFunction - Runs the user-defined DRDY function.
2557 
2558   Collective on TS
2559 
2560   Input Parameters:
2561 . ts   - The TS context obtained from TSCreate()
2562 
2563   Notes:
2564   TSAdjointComputeDRDYFunction() is typically used for sensitivity implementation,
2565   so most users would not generally call this routine themselves.
2566 
2567   Level: developer
2568 
2569 .keywords: TS, sensitivity
2570 .seealso: TSAdjointComputeDRDYFunction()
2571 @*/
2572 PetscErrorCode  TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec y,Vec *drdy)
2573 {
2574   PetscErrorCode ierr;
2575 
2576   PetscFunctionBegin;
2577   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2578   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2579 
2580   PetscStackPush("TS user DRDY function for sensitivity analysis");
2581   ierr = (*ts->drdyfunction)(ts,t,y,drdy,ts->costintegrandctx); CHKERRQ(ierr);
2582   PetscStackPop;
2583   PetscFunctionReturn(0);
2584 }
2585 
2586 #undef __FUNCT__
2587 #define __FUNCT__ "TSAdjointComputeDRDPFunction"
2588 /*@
2589   TSAdjointComputeDRDPFunction - Runs the user-defined DRDP function.
2590 
2591   Collective on TS
2592 
2593   Input Parameters:
2594 . ts   - The TS context obtained from TSCreate()
2595 
2596   Notes:
2597   TSDRDPFunction() is typically used for sensitivity implementation,
2598   so most users would not generally call this routine themselves.
2599 
2600   Level: developer
2601 
2602 .keywords: TS, sensitivity
2603 .seealso: TSAdjointSetDRDPFunction()
2604 @*/
2605 PetscErrorCode  TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec y,Vec *drdp)
2606 {
2607   PetscErrorCode ierr;
2608 
2609   PetscFunctionBegin;
2610   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2611   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
2612 
2613   PetscStackPush("TS user DRDP function for sensitivity analysis");
2614   ierr = (*ts->drdpfunction)(ts,t,y,drdp,ts->costintegrandctx); CHKERRQ(ierr);
2615   PetscStackPop;
2616   PetscFunctionReturn(0);
2617 }
2618 
2619 #undef __FUNCT__
2620 #define __FUNCT__ "TSSetPreStep"
2621 /*@C
2622   TSSetPreStep - Sets the general-purpose function
2623   called once at the beginning of each time step.
2624 
2625   Logically Collective on TS
2626 
2627   Input Parameters:
2628 + ts   - The TS context obtained from TSCreate()
2629 - func - The function
2630 
2631   Calling sequence of func:
2632 . func (TS ts);
2633 
2634   Level: intermediate
2635 
2636   Note:
2637   If a step is rejected, TSStep() will call this routine again before each attempt.
2638   The last completed time step number can be queried using TSGetTimeStepNumber(), the
2639   size of the step being attempted can be obtained using TSGetTimeStep().
2640 
2641 .keywords: TS, timestep
2642 .seealso: TSSetPreStage(), TSSetPostStage(), TSSetPostStep(), TSStep()
2643 @*/
2644 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
2645 {
2646   PetscFunctionBegin;
2647   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2648   ts->prestep = func;
2649   PetscFunctionReturn(0);
2650 }
2651 
2652 #undef __FUNCT__
2653 #define __FUNCT__ "TSPreStep"
2654 /*@
2655   TSPreStep - Runs the user-defined pre-step function.
2656 
2657   Collective on TS
2658 
2659   Input Parameters:
2660 . ts   - The TS context obtained from TSCreate()
2661 
2662   Notes:
2663   TSPreStep() is typically used within time stepping implementations,
2664   so most users would not generally call this routine themselves.
2665 
2666   Level: developer
2667 
2668 .keywords: TS, timestep
2669 .seealso: TSSetPreStep(), TSPreStage(), TSPostStage(), TSPostStep()
2670 @*/
2671 PetscErrorCode  TSPreStep(TS ts)
2672 {
2673   PetscErrorCode ierr;
2674 
2675   PetscFunctionBegin;
2676   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2677   if (ts->prestep) {
2678     PetscStackCallStandard((*ts->prestep),(ts));
2679   }
2680   PetscFunctionReturn(0);
2681 }
2682 
2683 #undef __FUNCT__
2684 #define __FUNCT__ "TSSetPreStage"
2685 /*@C
2686   TSSetPreStage - Sets the general-purpose function
2687   called once at the beginning of each stage.
2688 
2689   Logically Collective on TS
2690 
2691   Input Parameters:
2692 + ts   - The TS context obtained from TSCreate()
2693 - func - The function
2694 
2695   Calling sequence of func:
2696 . PetscErrorCode func(TS ts, PetscReal stagetime);
2697 
2698   Level: intermediate
2699 
2700   Note:
2701   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
2702   The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
2703   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
2704 
2705 .keywords: TS, timestep
2706 .seealso: TSSetPostStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
2707 @*/
2708 PetscErrorCode  TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
2709 {
2710   PetscFunctionBegin;
2711   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2712   ts->prestage = func;
2713   PetscFunctionReturn(0);
2714 }
2715 
2716 #undef __FUNCT__
2717 #define __FUNCT__ "TSSetPostStage"
2718 /*@C
2719   TSSetPostStage - Sets the general-purpose function
2720   called once at the end of each stage.
2721 
2722   Logically Collective on TS
2723 
2724   Input Parameters:
2725 + ts   - The TS context obtained from TSCreate()
2726 - func - The function
2727 
2728   Calling sequence of func:
2729 . PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y);
2730 
2731   Level: intermediate
2732 
2733   Note:
2734   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
2735   The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
2736   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
2737 
2738 .keywords: TS, timestep
2739 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
2740 @*/
2741 PetscErrorCode  TSSetPostStage(TS ts, PetscErrorCode (*func)(TS,PetscReal,PetscInt,Vec*))
2742 {
2743   PetscFunctionBegin;
2744   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2745   ts->poststage = func;
2746   PetscFunctionReturn(0);
2747 }
2748 
2749 #undef __FUNCT__
2750 #define __FUNCT__ "TSPreStage"
2751 /*@
2752   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
2753 
2754   Collective on TS
2755 
2756   Input Parameters:
2757 . ts          - The TS context obtained from TSCreate()
2758   stagetime   - The absolute time of the current stage
2759 
2760   Notes:
2761   TSPreStage() is typically used within time stepping implementations,
2762   most users would not generally call this routine themselves.
2763 
2764   Level: developer
2765 
2766 .keywords: TS, timestep
2767 .seealso: TSPostStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
2768 @*/
2769 PetscErrorCode  TSPreStage(TS ts, PetscReal stagetime)
2770 {
2771   PetscErrorCode ierr;
2772 
2773   PetscFunctionBegin;
2774   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2775   if (ts->prestage) {
2776     PetscStackCallStandard((*ts->prestage),(ts,stagetime));
2777   }
2778   PetscFunctionReturn(0);
2779 }
2780 
2781 #undef __FUNCT__
2782 #define __FUNCT__ "TSPostStage"
2783 /*@
2784   TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage()
2785 
2786   Collective on TS
2787 
2788   Input Parameters:
2789 . ts          - The TS context obtained from TSCreate()
2790   stagetime   - The absolute time of the current stage
2791   stageindex  - Stage number
2792   Y           - Array of vectors (of size = total number
2793                 of stages) with the stage solutions
2794 
2795   Notes:
2796   TSPostStage() is typically used within time stepping implementations,
2797   most users would not generally call this routine themselves.
2798 
2799   Level: developer
2800 
2801 .keywords: TS, timestep
2802 .seealso: TSPreStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
2803 @*/
2804 PetscErrorCode  TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
2805 {
2806   PetscErrorCode ierr;
2807 
2808   PetscFunctionBegin;
2809   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2810   if (ts->poststage) {
2811     PetscStackCallStandard((*ts->poststage),(ts,stagetime,stageindex,Y));
2812   }
2813   PetscFunctionReturn(0);
2814 }
2815 
2816 #undef __FUNCT__
2817 #define __FUNCT__ "TSSetPostStep"
2818 /*@C
2819   TSSetPostStep - Sets the general-purpose function
2820   called once at the end of each time step.
2821 
2822   Logically Collective on TS
2823 
2824   Input Parameters:
2825 + ts   - The TS context obtained from TSCreate()
2826 - func - The function
2827 
2828   Calling sequence of func:
2829 $ func (TS ts);
2830 
2831   Level: intermediate
2832 
2833 .keywords: TS, timestep
2834 .seealso: TSSetPreStep(), TSSetPreStage(), TSGetTimeStep(), TSGetTimeStepNumber(), TSGetTime()
2835 @*/
2836 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
2837 {
2838   PetscFunctionBegin;
2839   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2840   ts->poststep = func;
2841   PetscFunctionReturn(0);
2842 }
2843 
2844 #undef __FUNCT__
2845 #define __FUNCT__ "TSPostStep"
2846 /*@
2847   TSPostStep - Runs the user-defined post-step function.
2848 
2849   Collective on TS
2850 
2851   Input Parameters:
2852 . ts   - The TS context obtained from TSCreate()
2853 
2854   Notes:
2855   TSPostStep() is typically used within time stepping implementations,
2856   so most users would not generally call this routine themselves.
2857 
2858   Level: developer
2859 
2860 .keywords: TS, timestep
2861 @*/
2862 PetscErrorCode  TSPostStep(TS ts)
2863 {
2864   PetscErrorCode ierr;
2865 
2866   PetscFunctionBegin;
2867   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2868   if (ts->poststep) {
2869     PetscStackCallStandard((*ts->poststep),(ts));
2870   }
2871   PetscFunctionReturn(0);
2872 }
2873 
2874 /* ------------ Routines to set performance monitoring options ----------- */
2875 
2876 #undef __FUNCT__
2877 #define __FUNCT__ "TSMonitorSet"
2878 /*@C
2879    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
2880    timestep to display the iteration's  progress.
2881 
2882    Logically Collective on TS
2883 
2884    Input Parameters:
2885 +  ts - the TS context obtained from TSCreate()
2886 .  monitor - monitoring routine
2887 .  mctx - [optional] user-defined context for private data for the
2888              monitor routine (use NULL if no context is desired)
2889 -  monitordestroy - [optional] routine that frees monitor context
2890           (may be NULL)
2891 
2892    Calling sequence of monitor:
2893 $    int monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
2894 
2895 +    ts - the TS context
2896 .    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
2897                                been interpolated to)
2898 .    time - current time
2899 .    u - current iterate
2900 -    mctx - [optional] monitoring context
2901 
2902    Notes:
2903    This routine adds an additional monitor to the list of monitors that
2904    already has been loaded.
2905 
2906    Fortran notes: Only a single monitor function can be set for each TS object
2907 
2908    Level: intermediate
2909 
2910 .keywords: TS, timestep, set, monitor
2911 
2912 .seealso: TSMonitorDefault(), TSMonitorCancel()
2913 @*/
2914 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
2915 {
2916   PetscFunctionBegin;
2917   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2918   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
2919   ts->monitor[ts->numbermonitors]          = monitor;
2920   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
2921   ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
2922   PetscFunctionReturn(0);
2923 }
2924 
2925 #undef __FUNCT__
2926 #define __FUNCT__ "TSMonitorCancel"
2927 /*@C
2928    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
2929 
2930    Logically Collective on TS
2931 
2932    Input Parameters:
2933 .  ts - the TS context obtained from TSCreate()
2934 
2935    Notes:
2936    There is no way to remove a single, specific monitor.
2937 
2938    Level: intermediate
2939 
2940 .keywords: TS, timestep, set, monitor
2941 
2942 .seealso: TSMonitorDefault(), TSMonitorSet()
2943 @*/
2944 PetscErrorCode  TSMonitorCancel(TS ts)
2945 {
2946   PetscErrorCode ierr;
2947   PetscInt       i;
2948 
2949   PetscFunctionBegin;
2950   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2951   for (i=0; i<ts->numbermonitors; i++) {
2952     if (ts->monitordestroy[i]) {
2953       ierr = (*ts->monitordestroy[i])(&ts->monitorcontext[i]);CHKERRQ(ierr);
2954     }
2955   }
2956   ts->numbermonitors = 0;
2957   PetscFunctionReturn(0);
2958 }
2959 
2960 #undef __FUNCT__
2961 #define __FUNCT__ "TSMonitorDefault"
2962 /*@
2963    TSMonitorDefault - Sets the Default monitor
2964 
2965    Level: intermediate
2966 
2967 .keywords: TS, set, monitor
2968 
2969 .seealso: TSMonitorDefault(), TSMonitorSet()
2970 @*/
2971 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *dummy)
2972 {
2973   PetscErrorCode ierr;
2974   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)ts));
2975 
2976   PetscFunctionBegin;
2977   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2978   ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr);
2979   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2980   PetscFunctionReturn(0);
2981 }
2982 
2983 #undef __FUNCT__
2984 #define __FUNCT__ "TSSetRetainStages"
2985 /*@
2986    TSSetRetainStages - Request that all stages in the upcoming step be stored so that interpolation will be available.
2987 
2988    Logically Collective on TS
2989 
2990    Input Argument:
2991 .  ts - time stepping context
2992 
2993    Output Argument:
2994 .  flg - PETSC_TRUE or PETSC_FALSE
2995 
2996    Level: intermediate
2997 
2998 .keywords: TS, set
2999 
3000 .seealso: TSInterpolate(), TSSetPostStep()
3001 @*/
3002 PetscErrorCode TSSetRetainStages(TS ts,PetscBool flg)
3003 {
3004   PetscFunctionBegin;
3005   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3006   ts->retain_stages = flg;
3007   PetscFunctionReturn(0);
3008 }
3009 
3010 #undef __FUNCT__
3011 #define __FUNCT__ "TSInterpolate"
3012 /*@
3013    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
3014 
3015    Collective on TS
3016 
3017    Input Argument:
3018 +  ts - time stepping context
3019 -  t - time to interpolate to
3020 
3021    Output Argument:
3022 .  U - state at given time
3023 
3024    Notes:
3025    The user should call TSSetRetainStages() before taking a step in which interpolation will be requested.
3026 
3027    Level: intermediate
3028 
3029    Developer Notes:
3030    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
3031 
3032 .keywords: TS, set
3033 
3034 .seealso: TSSetRetainStages(), TSSetPostStep()
3035 @*/
3036 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
3037 {
3038   PetscErrorCode ierr;
3039 
3040   PetscFunctionBegin;
3041   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3042   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3043   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);
3044   if (!ts->ops->interpolate) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
3045   ierr = (*ts->ops->interpolate)(ts,t,U);CHKERRQ(ierr);
3046   PetscFunctionReturn(0);
3047 }
3048 
3049 #undef __FUNCT__
3050 #define __FUNCT__ "TSStep"
3051 /*@
3052    TSStep - Steps one time step
3053 
3054    Collective on TS
3055 
3056    Input Parameter:
3057 .  ts - the TS context obtained from TSCreate()
3058 
3059    Level: developer
3060 
3061    Notes:
3062    The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine.
3063 
3064    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
3065    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3066 
3067    This may over-step the final time provided in TSSetDuration() depending on the time-step used. TSSolve() interpolates to exactly the
3068    time provided in TSSetDuration(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
3069 
3070 .keywords: TS, timestep, solve
3071 
3072 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate()
3073 @*/
3074 PetscErrorCode  TSStep(TS ts)
3075 {
3076   DM               dm;
3077   PetscErrorCode   ierr;
3078   static PetscBool cite = PETSC_FALSE;
3079 
3080   PetscFunctionBegin;
3081   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3082   ierr = PetscCitationsRegister("@techreport{tspaper,\n"
3083                                 "  title       = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3084                                 "  author      = {Shrirang Abhyankar and Jed Brown and Emil Constantinescu and Debojyoti Ghosh and Barry F. Smith},\n"
3085                                 "  type        = {Preprint},\n"
3086                                 "  number      = {ANL/MCS-P5061-0114},\n"
3087                                 "  institution = {Argonne National Laboratory},\n"
3088                                 "  year        = {2014}\n}\n",&cite);CHKERRQ(ierr);
3089 
3090   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
3091   ierr = TSSetUp(ts);CHKERRQ(ierr);
3092 
3093   ts->reason = TS_CONVERGED_ITERATING;
3094   ts->ptime_prev = ts->ptime;
3095   ierr = DMSetOutputSequenceNumber(dm, ts->steps, ts->ptime);CHKERRQ(ierr);
3096 
3097   if (!ts->ops->step) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3098   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3099   ierr = (*ts->ops->step)(ts);CHKERRQ(ierr);
3100   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3101 
3102   ts->time_step_prev = ts->ptime - ts->ptime_prev;
3103   ierr = DMSetOutputSequenceNumber(dm, ts->steps, ts->ptime);CHKERRQ(ierr);
3104 
3105   if (ts->reason < 0) {
3106     if (ts->errorifstepfailed) {
3107       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]);
3108       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
3109     }
3110   } else if (!ts->reason) {
3111     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
3112     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3113   }
3114   ts->total_steps++;
3115   ts->steprollback = PETSC_FALSE;
3116   PetscFunctionReturn(0);
3117 }
3118 
3119 #undef __FUNCT__
3120 #define __FUNCT__ "TSAdjointStep"
3121 /*@
3122    TSAdjointStep - Steps one time step
3123 
3124    Collective on TS
3125 
3126    Input Parameter:
3127 .  ts - the TS context obtained from TSCreate()
3128 
3129    Level: intermediate
3130 
3131    Notes:
3132    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
3133    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3134 
3135    This may over-step the final time provided in TSSetDuration() depending on the time-step used. TSSolve() interpolates to exactly the
3136    time provided in TSSetDuration(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
3137 
3138 .keywords: TS, timestep, solve
3139 
3140 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate()
3141 @*/
3142 PetscErrorCode  TSAdjointStep(TS ts)
3143 {
3144   DM               dm;
3145   PetscErrorCode   ierr;
3146 
3147   PetscFunctionBegin;
3148   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3149   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
3150   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
3151 
3152   ts->reason = TS_CONVERGED_ITERATING;
3153   ts->ptime_prev = ts->ptime;
3154   ierr = DMSetOutputSequenceNumber(dm, ts->steps, ts->ptime);CHKERRQ(ierr);
3155   ierr = VecViewFromOptions(ts->vec_sol, ((PetscObject) ts)->prefix, "-ts_view_solution");CHKERRQ(ierr);
3156 
3157   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3158   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);
3159   ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr);
3160   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3161 
3162   ts->time_step_prev = ts->ptime - ts->ptime_prev;
3163   ierr = DMSetOutputSequenceNumber(dm, ts->steps, ts->ptime);CHKERRQ(ierr);
3164 
3165   if (ts->reason < 0) {
3166     if (ts->errorifstepfailed) {
3167       if (ts->reason == TS_DIVERGED_NONLINEAR_SOLVE) {
3168         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]);
3169       } else if (ts->reason == TS_DIVERGED_STEP_REJECTED) {
3170         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]);
3171       } else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
3172     }
3173   } else if (!ts->reason) {
3174     if (ts->steps >= ts->adjoint_max_steps)     ts->reason = TS_CONVERGED_ITS;
3175     else if (ts->ptime >= ts->max_time)         ts->reason = TS_CONVERGED_TIME;
3176   }
3177   ts->total_steps--;
3178   PetscFunctionReturn(0);
3179 }
3180 
3181 #undef __FUNCT__
3182 #define __FUNCT__ "TSEvaluateStep"
3183 /*@
3184    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
3185 
3186    Collective on TS
3187 
3188    Input Arguments:
3189 +  ts - time stepping context
3190 .  order - desired order of accuracy
3191 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
3192 
3193    Output Arguments:
3194 .  U - state at the end of the current step
3195 
3196    Level: advanced
3197 
3198    Notes:
3199    This function cannot be called until all stages have been evaluated.
3200    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.
3201 
3202 .seealso: TSStep(), TSAdapt
3203 @*/
3204 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
3205 {
3206   PetscErrorCode ierr;
3207 
3208   PetscFunctionBegin;
3209   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3210   PetscValidType(ts,1);
3211   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3212   if (!ts->ops->evaluatestep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3213   ierr = (*ts->ops->evaluatestep)(ts,order,U,done);CHKERRQ(ierr);
3214   PetscFunctionReturn(0);
3215 }
3216 
3217 
3218 #undef __FUNCT__
3219 #define __FUNCT__ "TSSolve"
3220 /*@
3221    TSSolve - Steps the requested number of timesteps.
3222 
3223    Collective on TS
3224 
3225    Input Parameter:
3226 +  ts - the TS context obtained from TSCreate()
3227 -  u - the solution vector  (can be null if TSSetSolution() was used, otherwise must contain the initial conditions)
3228 
3229    Level: beginner
3230 
3231    Notes:
3232    The final time returned by this function may be different from the time of the internally
3233    held state accessible by TSGetSolution() and TSGetTime() because the method may have
3234    stepped over the final time.
3235 
3236 .keywords: TS, timestep, solve
3237 
3238 .seealso: TSCreate(), TSSetSolution(), TSStep()
3239 @*/
3240 PetscErrorCode TSSolve(TS ts,Vec u)
3241 {
3242   Vec               solution;
3243   PetscErrorCode    ierr;
3244 
3245   PetscFunctionBegin;
3246   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3247   if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3248   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 */
3249     PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3250     if (!ts->vec_sol || u == ts->vec_sol) {
3251       ierr = VecDuplicate(u,&solution);CHKERRQ(ierr);
3252       ierr = TSSetSolution(ts,solution);CHKERRQ(ierr);
3253       ierr = VecDestroy(&solution);CHKERRQ(ierr); /* grant ownership */
3254     }
3255     ierr = VecCopy(u,ts->vec_sol);CHKERRQ(ierr);
3256   } else if (u) {
3257     ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
3258   }
3259   ierr = TSSetUp(ts);CHKERRQ(ierr);
3260   /* reset time step and iteration counters */
3261   ts->steps             = 0;
3262   ts->ksp_its           = 0;
3263   ts->snes_its          = 0;
3264   ts->num_snes_failures = 0;
3265   ts->reject            = 0;
3266   ts->reason            = TS_CONVERGED_ITERATING;
3267 
3268   ierr = TSViewFromOptions(ts,NULL,"-ts_view_pre");CHKERRQ(ierr);
3269   {
3270     DM dm;
3271     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
3272     ierr = DMSetOutputSequenceNumber(dm, ts->steps, ts->ptime);CHKERRQ(ierr);
3273   }
3274 
3275   if (ts->ops->solve) {         /* This private interface is transitional and should be removed when all implementations are updated. */
3276     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
3277     ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);
3278     ts->solvetime = ts->ptime;
3279   } else {
3280     /* steps the requested number of timesteps. */
3281     if (ts->steps >= ts->max_steps)     ts->reason = TS_CONVERGED_ITS;
3282     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3283     ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3284     if (ts->vec_costintegral) ts->costintegralfwd=PETSC_TRUE;
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->adjoint_solve) {
3315     ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
3316   }
3317   PetscFunctionReturn(0);
3318 }
3319 
3320 #undef __FUNCT__
3321 #define __FUNCT__ "TSAdjointSolve"
3322 /*@
3323    TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
3324 
3325    Collective on TS
3326 
3327    Input Parameter:
3328 .  ts - the TS context obtained from TSCreate()
3329 
3330    Options Database:
3331 . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial conditions
3332 
3333    Level: intermediate
3334 
3335    Notes:
3336    This must be called after a call to TSSolve() that solves the forward problem
3337 
3338    By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time
3339 
3340 .keywords: TS, timestep, solve
3341 
3342 .seealso: TSCreate(), TSSetSolution(), TSStep()
3343 @*/
3344 PetscErrorCode TSAdjointSolve(TS ts)
3345 {
3346   PetscErrorCode    ierr;
3347 
3348   PetscFunctionBegin;
3349   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3350   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
3351   /* reset time step and iteration counters */
3352   ts->steps             = 0;
3353   ts->ksp_its           = 0;
3354   ts->snes_its          = 0;
3355   ts->num_snes_failures = 0;
3356   ts->reject            = 0;
3357   ts->reason            = TS_CONVERGED_ITERATING;
3358 
3359   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->total_steps;
3360 
3361   if (ts->steps >= ts->adjoint_max_steps)     ts->reason = TS_CONVERGED_ITS;
3362   while (!ts->reason) {
3363     ierr = TSTrajectoryGet(ts->trajectory,ts,ts->adjoint_max_steps-ts->steps,ts->ptime);CHKERRQ(ierr);
3364     ierr = TSMonitor(ts,ts->adjoint_max_steps-ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3365     ierr = TSAdjointStep(ts);CHKERRQ(ierr);
3366     if (ts->event) {
3367       ierr = TSAdjointEventMonitor(ts);CHKERRQ(ierr);
3368     }
3369 
3370 #if 0 /* I don't think PostStep is needed in AdjointSolve */
3371       if (ts->event->status != TSEVENT_PROCESSING) {
3372         ierr = TSPostStep(ts);CHKERRQ(ierr);
3373       }
3374     } else {
3375       ierr = TSPostStep(ts);CHKERRQ(ierr);
3376     }
3377 #endif
3378   }
3379   ts->solvetime = ts->ptime;
3380   ierr = VecViewFromOptions(ts->vecs_sensi[0], ((PetscObject) ts)->prefix, "-ts_adjoint_view_solution");CHKERRQ(ierr);
3381   PetscFunctionReturn(0);
3382 }
3383 
3384 #undef __FUNCT__
3385 #define __FUNCT__ "TSMonitor"
3386 /*@
3387    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
3388 
3389    Collective on TS
3390 
3391    Input Parameters:
3392 +  ts - time stepping context obtained from TSCreate()
3393 .  step - step number that has just completed
3394 .  ptime - model time of the state
3395 -  u - state at the current model time
3396 
3397    Notes:
3398    TSMonitor() is typically used within the time stepping implementations.
3399    Users might call this function when using the TSStep() interface instead of TSSolve().
3400 
3401    Level: advanced
3402 
3403 .keywords: TS, timestep
3404 @*/
3405 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
3406 {
3407   PetscErrorCode ierr;
3408   PetscInt       i,n = ts->numbermonitors;
3409 
3410   PetscFunctionBegin;
3411   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3412   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
3413   ierr = VecLockPush(u);CHKERRQ(ierr);
3414   for (i=0; i<n; i++) {
3415     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
3416   }
3417   ierr = VecLockPop(u);CHKERRQ(ierr);
3418   PetscFunctionReturn(0);
3419 }
3420 
3421 /* ------------------------------------------------------------------------*/
3422 #undef __FUNCT__
3423 #define __FUNCT__ "TSMonitorLGCtxCreate"
3424 /*@C
3425    TSMonitorLGCtxCreate - Creates a line graph context for use with
3426    TS to monitor the solution process graphically in various ways
3427 
3428    Collective on TS
3429 
3430    Input Parameters:
3431 +  host - the X display to open, or null for the local machine
3432 .  label - the title to put in the title bar
3433 .  x, y - the screen coordinates of the upper left coordinate of the window
3434 .  m, n - the screen width and height in pixels
3435 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
3436 
3437    Output Parameter:
3438 .  ctx - the context
3439 
3440    Options Database Key:
3441 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
3442 .  -ts_monitor_lg_solution -
3443 .  -ts_monitor_lg_error -
3444 .  -ts_monitor_lg_ksp_iterations -
3445 .  -ts_monitor_lg_snes_iterations -
3446 -  -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
3447 
3448    Notes:
3449    Use TSMonitorLGCtxDestroy() to destroy.
3450 
3451    Level: intermediate
3452 
3453 .keywords: TS, monitor, line graph, residual, seealso
3454 
3455 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
3456 
3457 @*/
3458 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
3459 {
3460   PetscDraw      win;
3461   PetscErrorCode ierr;
3462 
3463   PetscFunctionBegin;
3464   ierr = PetscNew(ctx);CHKERRQ(ierr);
3465   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&win);CHKERRQ(ierr);
3466   ierr = PetscDrawSetFromOptions(win);CHKERRQ(ierr);
3467   ierr = PetscDrawLGCreate(win,1,&(*ctx)->lg);CHKERRQ(ierr);
3468   ierr = PetscLogObjectParent((PetscObject)(*ctx)->lg,(PetscObject)win);CHKERRQ(ierr);
3469   ierr = PetscDrawLGSetUseMarkers((*ctx)->lg,PETSC_TRUE);CHKERRQ(ierr);
3470   ierr = PetscDrawLGSetFromOptions((*ctx)->lg);CHKERRQ(ierr);
3471   (*ctx)->howoften = howoften;
3472   PetscFunctionReturn(0);
3473 }
3474 
3475 #undef __FUNCT__
3476 #define __FUNCT__ "TSMonitorLGTimeStep"
3477 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
3478 {
3479   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
3480   PetscReal      x   = ptime,y;
3481   PetscErrorCode ierr;
3482 
3483   PetscFunctionBegin;
3484   if (!step) {
3485     PetscDrawAxis axis;
3486     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
3487     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time","Time step");CHKERRQ(ierr);
3488     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
3489   }
3490   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
3491   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
3492   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
3493     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
3494   }
3495   PetscFunctionReturn(0);
3496 }
3497 
3498 #undef __FUNCT__
3499 #define __FUNCT__ "TSMonitorLGCtxDestroy"
3500 /*@C
3501    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
3502    with TSMonitorLGCtxCreate().
3503 
3504    Collective on TSMonitorLGCtx
3505 
3506    Input Parameter:
3507 .  ctx - the monitor context
3508 
3509    Level: intermediate
3510 
3511 .keywords: TS, monitor, line graph, destroy
3512 
3513 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
3514 @*/
3515 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
3516 {
3517   PetscDraw      draw;
3518   PetscErrorCode ierr;
3519 
3520   PetscFunctionBegin;
3521   if ((*ctx)->transformdestroy) {
3522     ierr = ((*ctx)->transformdestroy)((*ctx)->transformctx);CHKERRQ(ierr);
3523   }
3524   ierr = PetscDrawLGGetDraw((*ctx)->lg,&draw);CHKERRQ(ierr);
3525   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
3526   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
3527   ierr = PetscStrArrayDestroy(&(*ctx)->names);CHKERRQ(ierr);
3528   ierr = PetscStrArrayDestroy(&(*ctx)->displaynames);CHKERRQ(ierr);
3529   ierr = PetscFree((*ctx)->displayvariables);CHKERRQ(ierr);
3530   ierr = PetscFree((*ctx)->displayvalues);CHKERRQ(ierr);
3531   ierr = PetscFree(*ctx);CHKERRQ(ierr);
3532   PetscFunctionReturn(0);
3533 }
3534 
3535 #undef __FUNCT__
3536 #define __FUNCT__ "TSGetTime"
3537 /*@
3538    TSGetTime - Gets the time of the most recently completed step.
3539 
3540    Not Collective
3541 
3542    Input Parameter:
3543 .  ts - the TS context obtained from TSCreate()
3544 
3545    Output Parameter:
3546 .  t  - the current time
3547 
3548    Level: beginner
3549 
3550    Note:
3551    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
3552    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
3553 
3554 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
3555 
3556 .keywords: TS, get, time
3557 @*/
3558 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
3559 {
3560   PetscFunctionBegin;
3561   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3562   PetscValidRealPointer(t,2);
3563   *t = ts->ptime;
3564   PetscFunctionReturn(0);
3565 }
3566 
3567 #undef __FUNCT__
3568 #define __FUNCT__ "TSGetPrevTime"
3569 /*@
3570    TSGetPrevTime - Gets the starting time of the previously completed step.
3571 
3572    Not Collective
3573 
3574    Input Parameter:
3575 .  ts - the TS context obtained from TSCreate()
3576 
3577    Output Parameter:
3578 .  t  - the previous time
3579 
3580    Level: beginner
3581 
3582 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
3583 
3584 .keywords: TS, get, time
3585 @*/
3586 PetscErrorCode  TSGetPrevTime(TS ts,PetscReal *t)
3587 {
3588   PetscFunctionBegin;
3589   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3590   PetscValidRealPointer(t,2);
3591   *t = ts->ptime_prev;
3592   PetscFunctionReturn(0);
3593 }
3594 
3595 #undef __FUNCT__
3596 #define __FUNCT__ "TSSetTime"
3597 /*@
3598    TSSetTime - Allows one to reset the time.
3599 
3600    Logically Collective on TS
3601 
3602    Input Parameters:
3603 +  ts - the TS context obtained from TSCreate()
3604 -  time - the time
3605 
3606    Level: intermediate
3607 
3608 .seealso: TSGetTime(), TSSetDuration()
3609 
3610 .keywords: TS, set, time
3611 @*/
3612 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
3613 {
3614   PetscFunctionBegin;
3615   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3616   PetscValidLogicalCollectiveReal(ts,t,2);
3617   ts->ptime = t;
3618   PetscFunctionReturn(0);
3619 }
3620 
3621 #undef __FUNCT__
3622 #define __FUNCT__ "TSSetOptionsPrefix"
3623 /*@C
3624    TSSetOptionsPrefix - Sets the prefix used for searching for all
3625    TS options in the database.
3626 
3627    Logically Collective on TS
3628 
3629    Input Parameter:
3630 +  ts     - The TS context
3631 -  prefix - The prefix to prepend to all option names
3632 
3633    Notes:
3634    A hyphen (-) must NOT be given at the beginning of the prefix name.
3635    The first character of all runtime options is AUTOMATICALLY the
3636    hyphen.
3637 
3638    Level: advanced
3639 
3640 .keywords: TS, set, options, prefix, database
3641 
3642 .seealso: TSSetFromOptions()
3643 
3644 @*/
3645 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
3646 {
3647   PetscErrorCode ierr;
3648   SNES           snes;
3649 
3650   PetscFunctionBegin;
3651   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3652   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
3653   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3654   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
3655   PetscFunctionReturn(0);
3656 }
3657 
3658 
3659 #undef __FUNCT__
3660 #define __FUNCT__ "TSAppendOptionsPrefix"
3661 /*@C
3662    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
3663    TS options in the database.
3664 
3665    Logically Collective on TS
3666 
3667    Input Parameter:
3668 +  ts     - The TS context
3669 -  prefix - The prefix to prepend to all option names
3670 
3671    Notes:
3672    A hyphen (-) must NOT be given at the beginning of the prefix name.
3673    The first character of all runtime options is AUTOMATICALLY the
3674    hyphen.
3675 
3676    Level: advanced
3677 
3678 .keywords: TS, append, options, prefix, database
3679 
3680 .seealso: TSGetOptionsPrefix()
3681 
3682 @*/
3683 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
3684 {
3685   PetscErrorCode ierr;
3686   SNES           snes;
3687 
3688   PetscFunctionBegin;
3689   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3690   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
3691   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3692   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
3693   PetscFunctionReturn(0);
3694 }
3695 
3696 #undef __FUNCT__
3697 #define __FUNCT__ "TSGetOptionsPrefix"
3698 /*@C
3699    TSGetOptionsPrefix - Sets the prefix used for searching for all
3700    TS options in the database.
3701 
3702    Not Collective
3703 
3704    Input Parameter:
3705 .  ts - The TS context
3706 
3707    Output Parameter:
3708 .  prefix - A pointer to the prefix string used
3709 
3710    Notes: On the fortran side, the user should pass in a string 'prifix' of
3711    sufficient length to hold the prefix.
3712 
3713    Level: intermediate
3714 
3715 .keywords: TS, get, options, prefix, database
3716 
3717 .seealso: TSAppendOptionsPrefix()
3718 @*/
3719 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
3720 {
3721   PetscErrorCode ierr;
3722 
3723   PetscFunctionBegin;
3724   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3725   PetscValidPointer(prefix,2);
3726   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
3727   PetscFunctionReturn(0);
3728 }
3729 
3730 #undef __FUNCT__
3731 #define __FUNCT__ "TSGetRHSJacobian"
3732 /*@C
3733    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
3734 
3735    Not Collective, but parallel objects are returned if TS is parallel
3736 
3737    Input Parameter:
3738 .  ts  - The TS context obtained from TSCreate()
3739 
3740    Output Parameters:
3741 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
3742 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
3743 .  func - Function to compute the Jacobian of the RHS  (or NULL)
3744 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
3745 
3746    Notes: You can pass in NULL for any return argument you do not need.
3747 
3748    Level: intermediate
3749 
3750 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
3751 
3752 .keywords: TS, timestep, get, matrix, Jacobian
3753 @*/
3754 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
3755 {
3756   PetscErrorCode ierr;
3757   SNES           snes;
3758   DM             dm;
3759 
3760   PetscFunctionBegin;
3761   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3762   ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
3763   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3764   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
3765   PetscFunctionReturn(0);
3766 }
3767 
3768 #undef __FUNCT__
3769 #define __FUNCT__ "TSGetIJacobian"
3770 /*@C
3771    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
3772 
3773    Not Collective, but parallel objects are returned if TS is parallel
3774 
3775    Input Parameter:
3776 .  ts  - The TS context obtained from TSCreate()
3777 
3778    Output Parameters:
3779 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
3780 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
3781 .  f   - The function to compute the matrices
3782 - ctx - User-defined context for Jacobian evaluation routine
3783 
3784    Notes: You can pass in NULL for any return argument you do not need.
3785 
3786    Level: advanced
3787 
3788 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
3789 
3790 .keywords: TS, timestep, get, matrix, Jacobian
3791 @*/
3792 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
3793 {
3794   PetscErrorCode ierr;
3795   SNES           snes;
3796   DM             dm;
3797 
3798   PetscFunctionBegin;
3799   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3800   ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
3801   ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
3802   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3803   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
3804   PetscFunctionReturn(0);
3805 }
3806 
3807 
3808 #undef __FUNCT__
3809 #define __FUNCT__ "TSMonitorDrawSolution"
3810 /*@C
3811    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
3812    VecView() for the solution at each timestep
3813 
3814    Collective on TS
3815 
3816    Input Parameters:
3817 +  ts - the TS context
3818 .  step - current time-step
3819 .  ptime - current time
3820 -  dummy - either a viewer or NULL
3821 
3822    Options Database:
3823 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3824 
3825    Notes: the initial solution and current solution are not display with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
3826        will look bad
3827 
3828    Level: intermediate
3829 
3830 .keywords: TS,  vector, monitor, view
3831 
3832 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3833 @*/
3834 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3835 {
3836   PetscErrorCode   ierr;
3837   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
3838   PetscDraw        draw;
3839 
3840   PetscFunctionBegin;
3841   if (!step && ictx->showinitial) {
3842     if (!ictx->initialsolution) {
3843       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
3844     }
3845     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
3846   }
3847   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
3848 
3849   if (ictx->showinitial) {
3850     PetscReal pause;
3851     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
3852     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
3853     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
3854     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
3855     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
3856   }
3857   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
3858   if (ictx->showtimestepandtime) {
3859     PetscReal xl,yl,xr,yr,h;
3860     char      time[32];
3861 
3862     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
3863     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
3864     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
3865     h    = yl + .95*(yr - yl);
3866     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
3867     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
3868   }
3869 
3870   if (ictx->showinitial) {
3871     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
3872   }
3873   PetscFunctionReturn(0);
3874 }
3875 
3876 #undef __FUNCT__
3877 #define __FUNCT__ "TSMonitorDrawSolutionPhase"
3878 /*@C
3879    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
3880 
3881    Collective on TS
3882 
3883    Input Parameters:
3884 +  ts - the TS context
3885 .  step - current time-step
3886 .  ptime - current time
3887 -  dummy - either a viewer or NULL
3888 
3889    Level: intermediate
3890 
3891 .keywords: TS,  vector, monitor, view
3892 
3893 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3894 @*/
3895 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3896 {
3897   PetscErrorCode    ierr;
3898   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
3899   PetscDraw         draw;
3900   MPI_Comm          comm;
3901   PetscInt          n;
3902   PetscMPIInt       size;
3903   PetscReal         xl,yl,xr,yr,h;
3904   char              time[32];
3905   const PetscScalar *U;
3906 
3907   PetscFunctionBegin;
3908   ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
3909   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
3910   if (size != 1) SETERRQ(comm,PETSC_ERR_SUP,"Only allowed for sequential runs");
3911   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
3912   if (n != 2) SETERRQ(comm,PETSC_ERR_SUP,"Only for ODEs with two unknowns");
3913 
3914   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
3915 
3916   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
3917   ierr = PetscDrawAxisGetLimits(ictx->axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
3918   if ((PetscRealPart(U[0]) < xl) || (PetscRealPart(U[1]) < yl) || (PetscRealPart(U[0]) > xr) || (PetscRealPart(U[1]) > yr)) {
3919       ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
3920       PetscFunctionReturn(0);
3921   }
3922   if (!step) ictx->color++;
3923   ierr = PetscDrawPoint(draw,PetscRealPart(U[0]),PetscRealPart(U[1]),ictx->color);CHKERRQ(ierr);
3924   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
3925 
3926   if (ictx->showtimestepandtime) {
3927     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
3928     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
3929     h    = yl + .95*(yr - yl);
3930     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
3931   }
3932   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
3933   PetscFunctionReturn(0);
3934 }
3935 
3936 
3937 #undef __FUNCT__
3938 #define __FUNCT__ "TSMonitorDrawCtxDestroy"
3939 /*@C
3940    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
3941 
3942    Collective on TS
3943 
3944    Input Parameters:
3945 .    ctx - the monitor context
3946 
3947    Level: intermediate
3948 
3949 .keywords: TS,  vector, monitor, view
3950 
3951 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
3952 @*/
3953 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
3954 {
3955   PetscErrorCode ierr;
3956 
3957   PetscFunctionBegin;
3958   ierr = PetscDrawAxisDestroy(&(*ictx)->axis);CHKERRQ(ierr);
3959   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
3960   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
3961   ierr = PetscFree(*ictx);CHKERRQ(ierr);
3962   PetscFunctionReturn(0);
3963 }
3964 
3965 #undef __FUNCT__
3966 #define __FUNCT__ "TSMonitorDrawCtxCreate"
3967 /*@C
3968    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
3969 
3970    Collective on TS
3971 
3972    Input Parameter:
3973 .    ts - time-step context
3974 
3975    Output Patameter:
3976 .    ctx - the monitor context
3977 
3978    Options Database:
3979 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3980 
3981    Level: intermediate
3982 
3983 .keywords: TS,  vector, monitor, view
3984 
3985 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
3986 @*/
3987 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
3988 {
3989   PetscErrorCode   ierr;
3990 
3991   PetscFunctionBegin;
3992   ierr = PetscNew(ctx);CHKERRQ(ierr);
3993   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
3994   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
3995 
3996   (*ctx)->howoften    = howoften;
3997   (*ctx)->showinitial = PETSC_FALSE;
3998   ierr = PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
3999 
4000   (*ctx)->showtimestepandtime = PETSC_FALSE;
4001   ierr = PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
4002   (*ctx)->color = PETSC_DRAW_WHITE;
4003   PetscFunctionReturn(0);
4004 }
4005 
4006 #undef __FUNCT__
4007 #define __FUNCT__ "TSMonitorDrawError"
4008 /*@C
4009    TSMonitorDrawError - Monitors progress of the TS solvers by calling
4010    VecView() for the error at each timestep
4011 
4012    Collective on TS
4013 
4014    Input Parameters:
4015 +  ts - the TS context
4016 .  step - current time-step
4017 .  ptime - current time
4018 -  dummy - either a viewer or NULL
4019 
4020    Level: intermediate
4021 
4022 .keywords: TS,  vector, monitor, view
4023 
4024 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4025 @*/
4026 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4027 {
4028   PetscErrorCode   ierr;
4029   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
4030   PetscViewer      viewer = ctx->viewer;
4031   Vec              work;
4032 
4033   PetscFunctionBegin;
4034   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4035   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
4036   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
4037   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
4038   ierr = VecView(work,viewer);CHKERRQ(ierr);
4039   ierr = VecDestroy(&work);CHKERRQ(ierr);
4040   PetscFunctionReturn(0);
4041 }
4042 
4043 #include <petsc/private/dmimpl.h>
4044 #undef __FUNCT__
4045 #define __FUNCT__ "TSSetDM"
4046 /*@
4047    TSSetDM - Sets the DM that may be used by some preconditioners
4048 
4049    Logically Collective on TS and DM
4050 
4051    Input Parameters:
4052 +  ts - the preconditioner context
4053 -  dm - the dm
4054 
4055    Level: intermediate
4056 
4057 
4058 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
4059 @*/
4060 PetscErrorCode  TSSetDM(TS ts,DM dm)
4061 {
4062   PetscErrorCode ierr;
4063   SNES           snes;
4064   DMTS           tsdm;
4065 
4066   PetscFunctionBegin;
4067   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4068   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
4069   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
4070     if (ts->dm->dmts && !dm->dmts) {
4071       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
4072       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
4073       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
4074         tsdm->originaldm = dm;
4075       }
4076     }
4077     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
4078   }
4079   ts->dm = dm;
4080 
4081   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4082   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
4083   PetscFunctionReturn(0);
4084 }
4085 
4086 #undef __FUNCT__
4087 #define __FUNCT__ "TSGetDM"
4088 /*@
4089    TSGetDM - Gets the DM that may be used by some preconditioners
4090 
4091    Not Collective
4092 
4093    Input Parameter:
4094 . ts - the preconditioner context
4095 
4096    Output Parameter:
4097 .  dm - the dm
4098 
4099    Level: intermediate
4100 
4101 
4102 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
4103 @*/
4104 PetscErrorCode  TSGetDM(TS ts,DM *dm)
4105 {
4106   PetscErrorCode ierr;
4107 
4108   PetscFunctionBegin;
4109   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4110   if (!ts->dm) {
4111     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
4112     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
4113   }
4114   *dm = ts->dm;
4115   PetscFunctionReturn(0);
4116 }
4117 
4118 #undef __FUNCT__
4119 #define __FUNCT__ "SNESTSFormFunction"
4120 /*@
4121    SNESTSFormFunction - Function to evaluate nonlinear residual
4122 
4123    Logically Collective on SNES
4124 
4125    Input Parameter:
4126 + snes - nonlinear solver
4127 . U - the current state at which to evaluate the residual
4128 - ctx - user context, must be a TS
4129 
4130    Output Parameter:
4131 . F - the nonlinear residual
4132 
4133    Notes:
4134    This function is not normally called by users and is automatically registered with the SNES used by TS.
4135    It is most frequently passed to MatFDColoringSetFunction().
4136 
4137    Level: advanced
4138 
4139 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
4140 @*/
4141 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
4142 {
4143   TS             ts = (TS)ctx;
4144   PetscErrorCode ierr;
4145 
4146   PetscFunctionBegin;
4147   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4148   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4149   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
4150   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
4151   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
4152   PetscFunctionReturn(0);
4153 }
4154 
4155 #undef __FUNCT__
4156 #define __FUNCT__ "SNESTSFormJacobian"
4157 /*@
4158    SNESTSFormJacobian - Function to evaluate the Jacobian
4159 
4160    Collective on SNES
4161 
4162    Input Parameter:
4163 + snes - nonlinear solver
4164 . U - the current state at which to evaluate the residual
4165 - ctx - user context, must be a TS
4166 
4167    Output Parameter:
4168 + A - the Jacobian
4169 . B - the preconditioning matrix (may be the same as A)
4170 - flag - indicates any structure change in the matrix
4171 
4172    Notes:
4173    This function is not normally called by users and is automatically registered with the SNES used by TS.
4174 
4175    Level: developer
4176 
4177 .seealso: SNESSetJacobian()
4178 @*/
4179 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
4180 {
4181   TS             ts = (TS)ctx;
4182   PetscErrorCode ierr;
4183 
4184   PetscFunctionBegin;
4185   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4186   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4187   PetscValidPointer(A,3);
4188   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
4189   PetscValidPointer(B,4);
4190   PetscValidHeaderSpecific(B,MAT_CLASSID,4);
4191   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
4192   ierr = (ts->ops->snesjacobian)(snes,U,A,B,ts);CHKERRQ(ierr);
4193   PetscFunctionReturn(0);
4194 }
4195 
4196 #undef __FUNCT__
4197 #define __FUNCT__ "TSComputeRHSFunctionLinear"
4198 /*@C
4199    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems only
4200 
4201    Collective on TS
4202 
4203    Input Arguments:
4204 +  ts - time stepping context
4205 .  t - time at which to evaluate
4206 .  U - state at which to evaluate
4207 -  ctx - context
4208 
4209    Output Arguments:
4210 .  F - right hand side
4211 
4212    Level: intermediate
4213 
4214    Notes:
4215    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
4216    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
4217 
4218 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
4219 @*/
4220 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
4221 {
4222   PetscErrorCode ierr;
4223   Mat            Arhs,Brhs;
4224 
4225   PetscFunctionBegin;
4226   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
4227   ierr = TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);CHKERRQ(ierr);
4228   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
4229   PetscFunctionReturn(0);
4230 }
4231 
4232 #undef __FUNCT__
4233 #define __FUNCT__ "TSComputeRHSJacobianConstant"
4234 /*@C
4235    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
4236 
4237    Collective on TS
4238 
4239    Input Arguments:
4240 +  ts - time stepping context
4241 .  t - time at which to evaluate
4242 .  U - state at which to evaluate
4243 -  ctx - context
4244 
4245    Output Arguments:
4246 +  A - pointer to operator
4247 .  B - pointer to preconditioning matrix
4248 -  flg - matrix structure flag
4249 
4250    Level: intermediate
4251 
4252    Notes:
4253    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
4254 
4255 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
4256 @*/
4257 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
4258 {
4259   PetscFunctionBegin;
4260   PetscFunctionReturn(0);
4261 }
4262 
4263 #undef __FUNCT__
4264 #define __FUNCT__ "TSComputeIFunctionLinear"
4265 /*@C
4266    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
4267 
4268    Collective on TS
4269 
4270    Input Arguments:
4271 +  ts - time stepping context
4272 .  t - time at which to evaluate
4273 .  U - state at which to evaluate
4274 .  Udot - time derivative of state vector
4275 -  ctx - context
4276 
4277    Output Arguments:
4278 .  F - left hand side
4279 
4280    Level: intermediate
4281 
4282    Notes:
4283    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
4284    user is required to write their own TSComputeIFunction.
4285    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
4286    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
4287 
4288 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant()
4289 @*/
4290 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
4291 {
4292   PetscErrorCode ierr;
4293   Mat            A,B;
4294 
4295   PetscFunctionBegin;
4296   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
4297   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE);CHKERRQ(ierr);
4298   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
4299   PetscFunctionReturn(0);
4300 }
4301 
4302 #undef __FUNCT__
4303 #define __FUNCT__ "TSComputeIJacobianConstant"
4304 /*@C
4305    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
4306 
4307    Collective on TS
4308 
4309    Input Arguments:
4310 +  ts - time stepping context
4311 .  t - time at which to evaluate
4312 .  U - state at which to evaluate
4313 .  Udot - time derivative of state vector
4314 .  shift - shift to apply
4315 -  ctx - context
4316 
4317    Output Arguments:
4318 +  A - pointer to operator
4319 .  B - pointer to preconditioning matrix
4320 -  flg - matrix structure flag
4321 
4322    Level: advanced
4323 
4324    Notes:
4325    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
4326 
4327    It is only appropriate for problems of the form
4328 
4329 $     M Udot = F(U,t)
4330 
4331   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
4332   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
4333   an implicit operator of the form
4334 
4335 $    shift*M + J
4336 
4337   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
4338   a copy of M or reassemble it when requested.
4339 
4340 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
4341 @*/
4342 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
4343 {
4344   PetscErrorCode ierr;
4345 
4346   PetscFunctionBegin;
4347   ierr = MatScale(A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
4348   ts->ijacobian.shift = shift;
4349   PetscFunctionReturn(0);
4350 }
4351 
4352 #undef __FUNCT__
4353 #define __FUNCT__ "TSGetEquationType"
4354 /*@
4355    TSGetEquationType - Gets the type of the equation that TS is solving.
4356 
4357    Not Collective
4358 
4359    Input Parameter:
4360 .  ts - the TS context
4361 
4362    Output Parameter:
4363 .  equation_type - see TSEquationType
4364 
4365    Level: beginner
4366 
4367 .keywords: TS, equation type
4368 
4369 .seealso: TSSetEquationType(), TSEquationType
4370 @*/
4371 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
4372 {
4373   PetscFunctionBegin;
4374   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4375   PetscValidPointer(equation_type,2);
4376   *equation_type = ts->equation_type;
4377   PetscFunctionReturn(0);
4378 }
4379 
4380 #undef __FUNCT__
4381 #define __FUNCT__ "TSSetEquationType"
4382 /*@
4383    TSSetEquationType - Sets the type of the equation that TS is solving.
4384 
4385    Not Collective
4386 
4387    Input Parameter:
4388 +  ts - the TS context
4389 .  equation_type - see TSEquationType
4390 
4391    Level: advanced
4392 
4393 .keywords: TS, equation type
4394 
4395 .seealso: TSGetEquationType(), TSEquationType
4396 @*/
4397 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
4398 {
4399   PetscFunctionBegin;
4400   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4401   ts->equation_type = equation_type;
4402   PetscFunctionReturn(0);
4403 }
4404 
4405 #undef __FUNCT__
4406 #define __FUNCT__ "TSGetConvergedReason"
4407 /*@
4408    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
4409 
4410    Not Collective
4411 
4412    Input Parameter:
4413 .  ts - the TS context
4414 
4415    Output Parameter:
4416 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4417             manual pages for the individual convergence tests for complete lists
4418 
4419    Level: beginner
4420 
4421    Notes:
4422    Can only be called after the call to TSSolve() is complete.
4423 
4424 .keywords: TS, nonlinear, set, convergence, test
4425 
4426 .seealso: TSSetConvergenceTest(), TSConvergedReason
4427 @*/
4428 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
4429 {
4430   PetscFunctionBegin;
4431   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4432   PetscValidPointer(reason,2);
4433   *reason = ts->reason;
4434   PetscFunctionReturn(0);
4435 }
4436 
4437 #undef __FUNCT__
4438 #define __FUNCT__ "TSSetConvergedReason"
4439 /*@
4440    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
4441 
4442    Not Collective
4443 
4444    Input Parameter:
4445 +  ts - the TS context
4446 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4447             manual pages for the individual convergence tests for complete lists
4448 
4449    Level: advanced
4450 
4451    Notes:
4452    Can only be called during TSSolve() is active.
4453 
4454 .keywords: TS, nonlinear, set, convergence, test
4455 
4456 .seealso: TSConvergedReason
4457 @*/
4458 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
4459 {
4460   PetscFunctionBegin;
4461   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4462   ts->reason = reason;
4463   PetscFunctionReturn(0);
4464 }
4465 
4466 #undef __FUNCT__
4467 #define __FUNCT__ "TSGetSolveTime"
4468 /*@
4469    TSGetSolveTime - Gets the time after a call to TSSolve()
4470 
4471    Not Collective
4472 
4473    Input Parameter:
4474 .  ts - the TS context
4475 
4476    Output Parameter:
4477 .  ftime - the final time. This time should correspond to the final time set with TSSetDuration()
4478 
4479    Level: beginner
4480 
4481    Notes:
4482    Can only be called after the call to TSSolve() is complete.
4483 
4484 .keywords: TS, nonlinear, set, convergence, test
4485 
4486 .seealso: TSSetConvergenceTest(), TSConvergedReason
4487 @*/
4488 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
4489 {
4490   PetscFunctionBegin;
4491   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4492   PetscValidPointer(ftime,2);
4493   *ftime = ts->solvetime;
4494   PetscFunctionReturn(0);
4495 }
4496 
4497 #undef __FUNCT__
4498 #define __FUNCT__ "TSGetTotalSteps"
4499 /*@
4500    TSGetTotalSteps - Gets the total number of steps done since the last call to TSSetUp() or TSCreate()
4501 
4502    Not Collective
4503 
4504    Input Parameter:
4505 .  ts - the TS context
4506 
4507    Output Parameter:
4508 .  steps - the number of steps
4509 
4510    Level: beginner
4511 
4512    Notes:
4513    Includes the number of steps for all calls to TSSolve() since TSSetUp() was called
4514 
4515 .keywords: TS, nonlinear, set, convergence, test
4516 
4517 .seealso: TSSetConvergenceTest(), TSConvergedReason
4518 @*/
4519 PetscErrorCode  TSGetTotalSteps(TS ts,PetscInt *steps)
4520 {
4521   PetscFunctionBegin;
4522   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4523   PetscValidPointer(steps,2);
4524   *steps = ts->total_steps;
4525   PetscFunctionReturn(0);
4526 }
4527 
4528 #undef __FUNCT__
4529 #define __FUNCT__ "TSGetSNESIterations"
4530 /*@
4531    TSGetSNESIterations - Gets the total number of nonlinear iterations
4532    used by the time integrator.
4533 
4534    Not Collective
4535 
4536    Input Parameter:
4537 .  ts - TS context
4538 
4539    Output Parameter:
4540 .  nits - number of nonlinear iterations
4541 
4542    Notes:
4543    This counter is reset to zero for each successive call to TSSolve().
4544 
4545    Level: intermediate
4546 
4547 .keywords: TS, get, number, nonlinear, iterations
4548 
4549 .seealso:  TSGetKSPIterations()
4550 @*/
4551 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
4552 {
4553   PetscFunctionBegin;
4554   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4555   PetscValidIntPointer(nits,2);
4556   *nits = ts->snes_its;
4557   PetscFunctionReturn(0);
4558 }
4559 
4560 #undef __FUNCT__
4561 #define __FUNCT__ "TSGetKSPIterations"
4562 /*@
4563    TSGetKSPIterations - Gets the total number of linear iterations
4564    used by the time integrator.
4565 
4566    Not Collective
4567 
4568    Input Parameter:
4569 .  ts - TS context
4570 
4571    Output Parameter:
4572 .  lits - number of linear iterations
4573 
4574    Notes:
4575    This counter is reset to zero for each successive call to TSSolve().
4576 
4577    Level: intermediate
4578 
4579 .keywords: TS, get, number, linear, iterations
4580 
4581 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
4582 @*/
4583 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
4584 {
4585   PetscFunctionBegin;
4586   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4587   PetscValidIntPointer(lits,2);
4588   *lits = ts->ksp_its;
4589   PetscFunctionReturn(0);
4590 }
4591 
4592 #undef __FUNCT__
4593 #define __FUNCT__ "TSGetStepRejections"
4594 /*@
4595    TSGetStepRejections - Gets the total number of rejected steps.
4596 
4597    Not Collective
4598 
4599    Input Parameter:
4600 .  ts - TS context
4601 
4602    Output Parameter:
4603 .  rejects - number of steps rejected
4604 
4605    Notes:
4606    This counter is reset to zero for each successive call to TSSolve().
4607 
4608    Level: intermediate
4609 
4610 .keywords: TS, get, number
4611 
4612 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
4613 @*/
4614 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
4615 {
4616   PetscFunctionBegin;
4617   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4618   PetscValidIntPointer(rejects,2);
4619   *rejects = ts->reject;
4620   PetscFunctionReturn(0);
4621 }
4622 
4623 #undef __FUNCT__
4624 #define __FUNCT__ "TSGetSNESFailures"
4625 /*@
4626    TSGetSNESFailures - Gets the total number of failed SNES solves
4627 
4628    Not Collective
4629 
4630    Input Parameter:
4631 .  ts - TS context
4632 
4633    Output Parameter:
4634 .  fails - number of failed nonlinear solves
4635 
4636    Notes:
4637    This counter is reset to zero for each successive call to TSSolve().
4638 
4639    Level: intermediate
4640 
4641 .keywords: TS, get, number
4642 
4643 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
4644 @*/
4645 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
4646 {
4647   PetscFunctionBegin;
4648   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4649   PetscValidIntPointer(fails,2);
4650   *fails = ts->num_snes_failures;
4651   PetscFunctionReturn(0);
4652 }
4653 
4654 #undef __FUNCT__
4655 #define __FUNCT__ "TSSetMaxStepRejections"
4656 /*@
4657    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
4658 
4659    Not Collective
4660 
4661    Input Parameter:
4662 +  ts - TS context
4663 -  rejects - maximum number of rejected steps, pass -1 for unlimited
4664 
4665    Notes:
4666    The counter is reset to zero for each step
4667 
4668    Options Database Key:
4669  .  -ts_max_reject - Maximum number of step rejections before a step fails
4670 
4671    Level: intermediate
4672 
4673 .keywords: TS, set, maximum, number
4674 
4675 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
4676 @*/
4677 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
4678 {
4679   PetscFunctionBegin;
4680   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4681   ts->max_reject = rejects;
4682   PetscFunctionReturn(0);
4683 }
4684 
4685 #undef __FUNCT__
4686 #define __FUNCT__ "TSSetMaxSNESFailures"
4687 /*@
4688    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
4689 
4690    Not Collective
4691 
4692    Input Parameter:
4693 +  ts - TS context
4694 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
4695 
4696    Notes:
4697    The counter is reset to zero for each successive call to TSSolve().
4698 
4699    Options Database Key:
4700  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
4701 
4702    Level: intermediate
4703 
4704 .keywords: TS, set, maximum, number
4705 
4706 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
4707 @*/
4708 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
4709 {
4710   PetscFunctionBegin;
4711   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4712   ts->max_snes_failures = fails;
4713   PetscFunctionReturn(0);
4714 }
4715 
4716 #undef __FUNCT__
4717 #define __FUNCT__ "TSSetErrorIfStepFails"
4718 /*@
4719    TSSetErrorIfStepFails - Error if no step succeeds
4720 
4721    Not Collective
4722 
4723    Input Parameter:
4724 +  ts - TS context
4725 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
4726 
4727    Options Database Key:
4728  .  -ts_error_if_step_fails - Error if no step succeeds
4729 
4730    Level: intermediate
4731 
4732 .keywords: TS, set, error
4733 
4734 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
4735 @*/
4736 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
4737 {
4738   PetscFunctionBegin;
4739   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4740   ts->errorifstepfailed = err;
4741   PetscFunctionReturn(0);
4742 }
4743 
4744 #undef __FUNCT__
4745 #define __FUNCT__ "TSMonitorSolutionBinary"
4746 /*@C
4747    TSMonitorSolutionBinary - Monitors progress of the TS solvers by VecView() for the solution at each timestep. Normally the viewer is a binary file
4748 
4749    Collective on TS
4750 
4751    Input Parameters:
4752 +  ts - the TS context
4753 .  step - current time-step
4754 .  ptime - current time
4755 .  u - current state
4756 -  viewer - binary viewer
4757 
4758    Level: intermediate
4759 
4760 .keywords: TS,  vector, monitor, view
4761 
4762 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4763 @*/
4764 PetscErrorCode  TSMonitorSolutionBinary(TS ts,PetscInt step,PetscReal ptime,Vec u,void *viewer)
4765 {
4766   PetscErrorCode ierr;
4767   PetscViewer    v = (PetscViewer)viewer;
4768 
4769   PetscFunctionBegin;
4770   ierr = VecView(u,v);CHKERRQ(ierr);
4771   PetscFunctionReturn(0);
4772 }
4773 
4774 #undef __FUNCT__
4775 #define __FUNCT__ "TSMonitorSolutionVTK"
4776 /*@C
4777    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
4778 
4779    Collective on TS
4780 
4781    Input Parameters:
4782 +  ts - the TS context
4783 .  step - current time-step
4784 .  ptime - current time
4785 .  u - current state
4786 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
4787 
4788    Level: intermediate
4789 
4790    Notes:
4791    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.
4792    These are named according to the file name template.
4793 
4794    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
4795 
4796 .keywords: TS,  vector, monitor, view
4797 
4798 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4799 @*/
4800 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
4801 {
4802   PetscErrorCode ierr;
4803   char           filename[PETSC_MAX_PATH_LEN];
4804   PetscViewer    viewer;
4805 
4806   PetscFunctionBegin;
4807   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
4808   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
4809   ierr = VecView(u,viewer);CHKERRQ(ierr);
4810   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4811   PetscFunctionReturn(0);
4812 }
4813 
4814 #undef __FUNCT__
4815 #define __FUNCT__ "TSMonitorSolutionVTKDestroy"
4816 /*@C
4817    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
4818 
4819    Collective on TS
4820 
4821    Input Parameters:
4822 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
4823 
4824    Level: intermediate
4825 
4826    Note:
4827    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
4828 
4829 .keywords: TS,  vector, monitor, view
4830 
4831 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
4832 @*/
4833 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
4834 {
4835   PetscErrorCode ierr;
4836 
4837   PetscFunctionBegin;
4838   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
4839   PetscFunctionReturn(0);
4840 }
4841 
4842 #undef __FUNCT__
4843 #define __FUNCT__ "TSGetAdapt"
4844 /*@
4845    TSGetAdapt - Get the adaptive controller context for the current method
4846 
4847    Collective on TS if controller has not been created yet
4848 
4849    Input Arguments:
4850 .  ts - time stepping context
4851 
4852    Output Arguments:
4853 .  adapt - adaptive controller
4854 
4855    Level: intermediate
4856 
4857 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
4858 @*/
4859 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
4860 {
4861   PetscErrorCode ierr;
4862 
4863   PetscFunctionBegin;
4864   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4865   PetscValidPointer(adapt,2);
4866   if (!ts->adapt) {
4867     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
4868     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt);CHKERRQ(ierr);
4869     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
4870   }
4871   *adapt = ts->adapt;
4872   PetscFunctionReturn(0);
4873 }
4874 
4875 #undef __FUNCT__
4876 #define __FUNCT__ "TSSetTolerances"
4877 /*@
4878    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
4879 
4880    Logically Collective
4881 
4882    Input Arguments:
4883 +  ts - time integration context
4884 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
4885 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
4886 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
4887 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
4888 
4889    Options Database keys:
4890 +  -ts_rtol <rtol> - relative tolerance for local truncation error
4891 -  -ts_atol <atol> Absolute tolerance for local truncation error
4892 
4893    Notes:
4894    With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
4895    (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
4896    computed only for the differential or the algebraic part then this can be done using the vector of
4897    tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
4898    differential part and infinity for the algebraic part, the LTE calculation will include only the
4899    differential variables.
4900 
4901    Level: beginner
4902 
4903 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
4904 @*/
4905 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
4906 {
4907   PetscErrorCode ierr;
4908 
4909   PetscFunctionBegin;
4910   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
4911   if (vatol) {
4912     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
4913     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
4914 
4915     ts->vatol = vatol;
4916   }
4917   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
4918   if (vrtol) {
4919     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
4920     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
4921 
4922     ts->vrtol = vrtol;
4923   }
4924   PetscFunctionReturn(0);
4925 }
4926 
4927 #undef __FUNCT__
4928 #define __FUNCT__ "TSGetTolerances"
4929 /*@
4930    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
4931 
4932    Logically Collective
4933 
4934    Input Arguments:
4935 .  ts - time integration context
4936 
4937    Output Arguments:
4938 +  atol - scalar absolute tolerances, NULL to ignore
4939 .  vatol - vector of absolute tolerances, NULL to ignore
4940 .  rtol - scalar relative tolerances, NULL to ignore
4941 -  vrtol - vector of relative tolerances, NULL to ignore
4942 
4943    Level: beginner
4944 
4945 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
4946 @*/
4947 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
4948 {
4949   PetscFunctionBegin;
4950   if (atol)  *atol  = ts->atol;
4951   if (vatol) *vatol = ts->vatol;
4952   if (rtol)  *rtol  = ts->rtol;
4953   if (vrtol) *vrtol = ts->vrtol;
4954   PetscFunctionReturn(0);
4955 }
4956 
4957 #undef __FUNCT__
4958 #define __FUNCT__ "TSErrorWeightedNorm2"
4959 /*@
4960    TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors
4961 
4962    Collective on TS
4963 
4964    Input Arguments:
4965 +  ts - time stepping context
4966 .  U - state vector, usually ts->vec_sol
4967 -  Y - state vector to be compared to U
4968 
4969    Output Arguments:
4970 .  norm - weighted norm, a value of 1.0 is considered small
4971 
4972    Level: developer
4973 
4974 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNormInfinity()
4975 @*/
4976 PetscErrorCode TSErrorWeightedNorm2(TS ts,Vec U,Vec Y,PetscReal *norm)
4977 {
4978   PetscErrorCode    ierr;
4979   PetscInt          i,n,N,rstart;
4980   const PetscScalar *u,*y;
4981   PetscReal         sum,gsum;
4982   PetscReal         tol;
4983 
4984   PetscFunctionBegin;
4985   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4986   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4987   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
4988   PetscValidType(U,2);
4989   PetscValidType(Y,3);
4990   PetscCheckSameComm(U,2,Y,3);
4991   PetscValidPointer(norm,4);
4992   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
4993 
4994   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
4995   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
4996   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
4997   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
4998   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
4999   sum  = 0.;
5000   if (ts->vatol && ts->vrtol) {
5001     const PetscScalar *atol,*rtol;
5002     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5003     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5004     for (i=0; i<n; i++) {
5005       tol = PetscRealPart(atol[i]) + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5006       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
5007     }
5008     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5009     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5010   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5011     const PetscScalar *atol;
5012     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5013     for (i=0; i<n; i++) {
5014       tol = PetscRealPart(atol[i]) + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5015       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
5016     }
5017     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5018   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5019     const PetscScalar *rtol;
5020     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5021     for (i=0; i<n; i++) {
5022       tol = ts->atol + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5023       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
5024     }
5025     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5026   } else {                      /* scalar atol, scalar rtol */
5027     for (i=0; i<n; i++) {
5028       tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5029       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
5030     }
5031   }
5032   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5033   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5034 
5035   ierr  = MPI_Allreduce(&sum,&gsum,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5036   *norm = PetscSqrtReal(gsum / N);
5037 
5038   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5039   PetscFunctionReturn(0);
5040 }
5041 
5042 #undef __FUNCT__
5043 #define __FUNCT__ "TSErrorWeightedNormInfinity"
5044 /*@
5045    TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors
5046 
5047    Collective on TS
5048 
5049    Input Arguments:
5050 +  ts - time stepping context
5051 .  U - state vector, usually ts->vec_sol
5052 -  Y - state vector to be compared to U
5053 
5054    Output Arguments:
5055 .  norm - weighted norm, a value of 1.0 is considered small
5056 
5057    Level: developer
5058 
5059 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNorm2()
5060 @*/
5061 PetscErrorCode TSErrorWeightedNormInfinity(TS ts,Vec U,Vec Y,PetscReal *norm)
5062 {
5063   PetscErrorCode    ierr;
5064   PetscInt          i,n,N,rstart,k;
5065   const PetscScalar *u,*y;
5066   PetscReal         max,gmax;
5067   PetscReal         tol;
5068 
5069   PetscFunctionBegin;
5070   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5071   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5072   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
5073   PetscValidType(U,2);
5074   PetscValidType(Y,3);
5075   PetscCheckSameComm(U,2,Y,3);
5076   PetscValidPointer(norm,4);
5077   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
5078 
5079   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
5080   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
5081   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
5082   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5083   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5084   if (ts->vatol && ts->vrtol) {
5085     const PetscScalar *atol,*rtol;
5086     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5087     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5088     k = 0;
5089     tol = PetscRealPart(atol[k]) + PetscRealPart(rtol[k]) * PetscMax(PetscAbsScalar(u[k]),PetscAbsScalar(y[k]));
5090     max = PetscAbsScalar(y[k] - u[k]) / tol;
5091     for (i=1; i<n; i++) {
5092       tol = PetscRealPart(atol[i]) + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5093       max = PetscMax(max,PetscAbsScalar(y[i] - u[i]) / tol);
5094     }
5095     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5096     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5097   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5098     const PetscScalar *atol;
5099     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5100     k = 0;
5101     tol = PetscRealPart(atol[k]) + ts->rtol * PetscMax(PetscAbsScalar(u[k]),PetscAbsScalar(y[k]));
5102     max = PetscAbsScalar(y[k] - u[k]) / tol;
5103     for (i=1; i<n; i++) {
5104       tol = PetscRealPart(atol[i]) + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5105       max = PetscMax(max,PetscAbsScalar(y[i] - u[i]) / tol);
5106     }
5107     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5108   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5109     const PetscScalar *rtol;
5110     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5111     k = 0;
5112     tol = ts->atol + PetscRealPart(rtol[k]) * PetscMax(PetscAbsScalar(u[k]),PetscAbsScalar(y[k]));
5113     max = PetscAbsScalar(y[k] - u[k]) / tol;
5114     for (i=1; i<n; i++) {
5115       tol = ts->atol + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5116       max = PetscMax(max,PetscAbsScalar(y[i] - u[i]) / tol);
5117     }
5118     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5119   } else {                      /* scalar atol, scalar rtol */
5120     k = 0;
5121     tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[k]),PetscAbsScalar(y[k]));
5122     max = PetscAbsScalar(y[k] - u[k]) / tol;
5123     for (i=1; i<n; i++) {
5124       tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5125       max = PetscMax(max,PetscAbsScalar(y[i] - u[i]) / tol);
5126     }
5127   }
5128   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5129   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5130 
5131   ierr  = MPI_Allreduce(&max,&gmax,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5132   *norm = gmax;
5133 
5134   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5135   PetscFunctionReturn(0);
5136 }
5137 
5138 #undef __FUNCT__
5139 #define __FUNCT__ "TSErrorWeightedNorm"
5140 /*@
5141    TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors
5142 
5143    Collective on TS
5144 
5145    Input Arguments:
5146 +  ts - time stepping context
5147 .  U - state vector, usually ts->vec_sol
5148 .  Y - state vector to be compared to U
5149 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
5150 
5151    Output Arguments:
5152 .  norm - weighted norm, a value of 1.0 is considered small
5153 
5154 
5155    Options Database Keys:
5156 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5157 
5158    Level: developer
5159 
5160 .seealso: TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2()
5161 @*/
5162 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec U,Vec Y,NormType wnormtype,PetscReal *norm)
5163 {
5164   PetscErrorCode ierr;
5165 
5166   PetscFunctionBegin;
5167   if (wnormtype == NORM_2) {
5168     ierr = TSErrorWeightedNorm2(ts,U,Y,norm);CHKERRQ(ierr);
5169   } else if(wnormtype == NORM_INFINITY) {
5170     ierr = TSErrorWeightedNormInfinity(ts,U,Y,norm);CHKERRQ(ierr);
5171   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
5172   PetscFunctionReturn(0);
5173 }
5174 
5175 #undef __FUNCT__
5176 #define __FUNCT__ "TSSetCFLTimeLocal"
5177 /*@
5178    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
5179 
5180    Logically Collective on TS
5181 
5182    Input Arguments:
5183 +  ts - time stepping context
5184 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
5185 
5186    Note:
5187    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
5188 
5189    Level: intermediate
5190 
5191 .seealso: TSGetCFLTime(), TSADAPTCFL
5192 @*/
5193 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
5194 {
5195   PetscFunctionBegin;
5196   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5197   ts->cfltime_local = cfltime;
5198   ts->cfltime       = -1.;
5199   PetscFunctionReturn(0);
5200 }
5201 
5202 #undef __FUNCT__
5203 #define __FUNCT__ "TSGetCFLTime"
5204 /*@
5205    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
5206 
5207    Collective on TS
5208 
5209    Input Arguments:
5210 .  ts - time stepping context
5211 
5212    Output Arguments:
5213 .  cfltime - maximum stable time step for forward Euler
5214 
5215    Level: advanced
5216 
5217 .seealso: TSSetCFLTimeLocal()
5218 @*/
5219 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
5220 {
5221   PetscErrorCode ierr;
5222 
5223   PetscFunctionBegin;
5224   if (ts->cfltime < 0) {
5225     ierr = MPI_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5226   }
5227   *cfltime = ts->cfltime;
5228   PetscFunctionReturn(0);
5229 }
5230 
5231 #undef __FUNCT__
5232 #define __FUNCT__ "TSVISetVariableBounds"
5233 /*@
5234    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
5235 
5236    Input Parameters:
5237 .  ts   - the TS context.
5238 .  xl   - lower bound.
5239 .  xu   - upper bound.
5240 
5241    Notes:
5242    If this routine is not called then the lower and upper bounds are set to
5243    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
5244 
5245    Level: advanced
5246 
5247 @*/
5248 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
5249 {
5250   PetscErrorCode ierr;
5251   SNES           snes;
5252 
5253   PetscFunctionBegin;
5254   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
5255   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
5256   PetscFunctionReturn(0);
5257 }
5258 
5259 #if defined(PETSC_HAVE_MATLAB_ENGINE)
5260 #include <mex.h>
5261 
5262 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
5263 
5264 #undef __FUNCT__
5265 #define __FUNCT__ "TSComputeFunction_Matlab"
5266 /*
5267    TSComputeFunction_Matlab - Calls the function that has been set with
5268                          TSSetFunctionMatlab().
5269 
5270    Collective on TS
5271 
5272    Input Parameters:
5273 +  snes - the TS context
5274 -  u - input vector
5275 
5276    Output Parameter:
5277 .  y - function vector, as set by TSSetFunction()
5278 
5279    Notes:
5280    TSComputeFunction() is typically used within nonlinear solvers
5281    implementations, so most users would not generally call this routine
5282    themselves.
5283 
5284    Level: developer
5285 
5286 .keywords: TS, nonlinear, compute, function
5287 
5288 .seealso: TSSetFunction(), TSGetFunction()
5289 */
5290 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
5291 {
5292   PetscErrorCode  ierr;
5293   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
5294   int             nlhs  = 1,nrhs = 7;
5295   mxArray         *plhs[1],*prhs[7];
5296   long long int   lx = 0,lxdot = 0,ly = 0,ls = 0;
5297 
5298   PetscFunctionBegin;
5299   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
5300   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
5301   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
5302   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
5303   PetscCheckSameComm(snes,1,u,3);
5304   PetscCheckSameComm(snes,1,y,5);
5305 
5306   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
5307   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
5308   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
5309   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
5310 
5311   prhs[0] =  mxCreateDoubleScalar((double)ls);
5312   prhs[1] =  mxCreateDoubleScalar(time);
5313   prhs[2] =  mxCreateDoubleScalar((double)lx);
5314   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
5315   prhs[4] =  mxCreateDoubleScalar((double)ly);
5316   prhs[5] =  mxCreateString(sctx->funcname);
5317   prhs[6] =  sctx->ctx;
5318   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
5319   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
5320   mxDestroyArray(prhs[0]);
5321   mxDestroyArray(prhs[1]);
5322   mxDestroyArray(prhs[2]);
5323   mxDestroyArray(prhs[3]);
5324   mxDestroyArray(prhs[4]);
5325   mxDestroyArray(prhs[5]);
5326   mxDestroyArray(plhs[0]);
5327   PetscFunctionReturn(0);
5328 }
5329 
5330 
5331 #undef __FUNCT__
5332 #define __FUNCT__ "TSSetFunctionMatlab"
5333 /*
5334    TSSetFunctionMatlab - Sets the function evaluation routine and function
5335    vector for use by the TS routines in solving ODEs
5336    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
5337 
5338    Logically Collective on TS
5339 
5340    Input Parameters:
5341 +  ts - the TS context
5342 -  func - function evaluation routine
5343 
5344    Calling sequence of func:
5345 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
5346 
5347    Level: beginner
5348 
5349 .keywords: TS, nonlinear, set, function
5350 
5351 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
5352 */
5353 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
5354 {
5355   PetscErrorCode  ierr;
5356   TSMatlabContext *sctx;
5357 
5358   PetscFunctionBegin;
5359   /* currently sctx is memory bleed */
5360   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
5361   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
5362   /*
5363      This should work, but it doesn't
5364   sctx->ctx = ctx;
5365   mexMakeArrayPersistent(sctx->ctx);
5366   */
5367   sctx->ctx = mxDuplicateArray(ctx);
5368 
5369   ierr = TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
5370   PetscFunctionReturn(0);
5371 }
5372 
5373 #undef __FUNCT__
5374 #define __FUNCT__ "TSComputeJacobian_Matlab"
5375 /*
5376    TSComputeJacobian_Matlab - Calls the function that has been set with
5377                          TSSetJacobianMatlab().
5378 
5379    Collective on TS
5380 
5381    Input Parameters:
5382 +  ts - the TS context
5383 .  u - input vector
5384 .  A, B - the matrices
5385 -  ctx - user context
5386 
5387    Level: developer
5388 
5389 .keywords: TS, nonlinear, compute, function
5390 
5391 .seealso: TSSetFunction(), TSGetFunction()
5392 @*/
5393 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat A,Mat B,void *ctx)
5394 {
5395   PetscErrorCode  ierr;
5396   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
5397   int             nlhs  = 2,nrhs = 9;
5398   mxArray         *plhs[2],*prhs[9];
5399   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
5400 
5401   PetscFunctionBegin;
5402   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5403   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
5404 
5405   /* call Matlab function in ctx with arguments u and y */
5406 
5407   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
5408   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
5409   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
5410   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
5411   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
5412 
5413   prhs[0] =  mxCreateDoubleScalar((double)ls);
5414   prhs[1] =  mxCreateDoubleScalar((double)time);
5415   prhs[2] =  mxCreateDoubleScalar((double)lx);
5416   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
5417   prhs[4] =  mxCreateDoubleScalar((double)shift);
5418   prhs[5] =  mxCreateDoubleScalar((double)lA);
5419   prhs[6] =  mxCreateDoubleScalar((double)lB);
5420   prhs[7] =  mxCreateString(sctx->funcname);
5421   prhs[8] =  sctx->ctx;
5422   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
5423   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
5424   mxDestroyArray(prhs[0]);
5425   mxDestroyArray(prhs[1]);
5426   mxDestroyArray(prhs[2]);
5427   mxDestroyArray(prhs[3]);
5428   mxDestroyArray(prhs[4]);
5429   mxDestroyArray(prhs[5]);
5430   mxDestroyArray(prhs[6]);
5431   mxDestroyArray(prhs[7]);
5432   mxDestroyArray(plhs[0]);
5433   mxDestroyArray(plhs[1]);
5434   PetscFunctionReturn(0);
5435 }
5436 
5437 
5438 #undef __FUNCT__
5439 #define __FUNCT__ "TSSetJacobianMatlab"
5440 /*
5441    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
5442    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
5443 
5444    Logically Collective on TS
5445 
5446    Input Parameters:
5447 +  ts - the TS context
5448 .  A,B - Jacobian matrices
5449 .  func - function evaluation routine
5450 -  ctx - user context
5451 
5452    Calling sequence of func:
5453 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
5454 
5455 
5456    Level: developer
5457 
5458 .keywords: TS, nonlinear, set, function
5459 
5460 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
5461 */
5462 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
5463 {
5464   PetscErrorCode  ierr;
5465   TSMatlabContext *sctx;
5466 
5467   PetscFunctionBegin;
5468   /* currently sctx is memory bleed */
5469   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
5470   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
5471   /*
5472      This should work, but it doesn't
5473   sctx->ctx = ctx;
5474   mexMakeArrayPersistent(sctx->ctx);
5475   */
5476   sctx->ctx = mxDuplicateArray(ctx);
5477 
5478   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
5479   PetscFunctionReturn(0);
5480 }
5481 
5482 #undef __FUNCT__
5483 #define __FUNCT__ "TSMonitor_Matlab"
5484 /*
5485    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
5486 
5487    Collective on TS
5488 
5489 .seealso: TSSetFunction(), TSGetFunction()
5490 @*/
5491 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
5492 {
5493   PetscErrorCode  ierr;
5494   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
5495   int             nlhs  = 1,nrhs = 6;
5496   mxArray         *plhs[1],*prhs[6];
5497   long long int   lx = 0,ls = 0;
5498 
5499   PetscFunctionBegin;
5500   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5501   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
5502 
5503   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
5504   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
5505 
5506   prhs[0] =  mxCreateDoubleScalar((double)ls);
5507   prhs[1] =  mxCreateDoubleScalar((double)it);
5508   prhs[2] =  mxCreateDoubleScalar((double)time);
5509   prhs[3] =  mxCreateDoubleScalar((double)lx);
5510   prhs[4] =  mxCreateString(sctx->funcname);
5511   prhs[5] =  sctx->ctx;
5512   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
5513   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
5514   mxDestroyArray(prhs[0]);
5515   mxDestroyArray(prhs[1]);
5516   mxDestroyArray(prhs[2]);
5517   mxDestroyArray(prhs[3]);
5518   mxDestroyArray(prhs[4]);
5519   mxDestroyArray(plhs[0]);
5520   PetscFunctionReturn(0);
5521 }
5522 
5523 
5524 #undef __FUNCT__
5525 #define __FUNCT__ "TSMonitorSetMatlab"
5526 /*
5527    TSMonitorSetMatlab - Sets the monitor function from Matlab
5528 
5529    Level: developer
5530 
5531 .keywords: TS, nonlinear, set, function
5532 
5533 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
5534 */
5535 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
5536 {
5537   PetscErrorCode  ierr;
5538   TSMatlabContext *sctx;
5539 
5540   PetscFunctionBegin;
5541   /* currently sctx is memory bleed */
5542   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
5543   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
5544   /*
5545      This should work, but it doesn't
5546   sctx->ctx = ctx;
5547   mexMakeArrayPersistent(sctx->ctx);
5548   */
5549   sctx->ctx = mxDuplicateArray(ctx);
5550 
5551   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);CHKERRQ(ierr);
5552   PetscFunctionReturn(0);
5553 }
5554 #endif
5555 
5556 #undef __FUNCT__
5557 #define __FUNCT__ "TSMonitorLGSolution"
5558 /*@C
5559    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
5560        in a time based line graph
5561 
5562    Collective on TS
5563 
5564    Input Parameters:
5565 +  ts - the TS context
5566 .  step - current time-step
5567 .  ptime - current time
5568 -  lg - a line graph object
5569 
5570    Options Database:
5571 .   -ts_monitor_lg_solution_variables
5572 
5573    Level: intermediate
5574 
5575     Notes: each process in a parallel run displays its component solutions in a separate window
5576 
5577 .keywords: TS,  vector, monitor, view
5578 
5579 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5580 @*/
5581 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5582 {
5583   PetscErrorCode    ierr;
5584   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
5585   const PetscScalar *yy;
5586   PetscInt          dim;
5587   Vec               v;
5588 
5589   PetscFunctionBegin;
5590   if (!step) {
5591     PetscDrawAxis axis;
5592     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
5593     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
5594     if (ctx->names && !ctx->displaynames) {
5595       char      **displaynames;
5596       PetscBool flg;
5597 
5598       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
5599       ierr = PetscMalloc((dim+1)*sizeof(char*),&displaynames);CHKERRQ(ierr);
5600       ierr = PetscMemzero(displaynames,(dim+1)*sizeof(char*));CHKERRQ(ierr);
5601       ierr = PetscOptionsGetStringArray(((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",displaynames,&dim,&flg);CHKERRQ(ierr);
5602       if (flg) {
5603         ierr = TSMonitorLGCtxSetDisplayVariables(ctx,(const char *const *)displaynames);CHKERRQ(ierr);
5604       }
5605       ierr = PetscStrArrayDestroy(&displaynames);CHKERRQ(ierr);
5606     }
5607     if (ctx->displaynames) {
5608       ierr = PetscDrawLGSetDimension(ctx->lg,ctx->ndisplayvariables);CHKERRQ(ierr);
5609       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->displaynames);CHKERRQ(ierr);
5610     } else if (ctx->names) {
5611       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
5612       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
5613       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->names);CHKERRQ(ierr);
5614     }
5615     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
5616   }
5617   if (ctx->transform) {
5618     ierr = (*ctx->transform)(ctx->transformctx,u,&v);CHKERRQ(ierr);
5619   } else {
5620     v = u;
5621   }
5622   ierr = VecGetArrayRead(v,&yy);CHKERRQ(ierr);
5623 #if defined(PETSC_USE_COMPLEX)
5624   {
5625     PetscReal *yreal;
5626     PetscInt  i,n;
5627     ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
5628     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
5629     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
5630     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
5631     ierr = PetscFree(yreal);CHKERRQ(ierr);
5632   }
5633 #else
5634   if (ctx->displaynames) {
5635     PetscInt i;
5636     for (i=0; i<ctx->ndisplayvariables; i++) {
5637       ctx->displayvalues[i] = yy[ctx->displayvariables[i]];
5638     }
5639     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,ctx->displayvalues);CHKERRQ(ierr);
5640   } else {
5641     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
5642   }
5643 #endif
5644   ierr = VecRestoreArrayRead(v,&yy);CHKERRQ(ierr);
5645   if (ctx->transform) {
5646     ierr = VecDestroy(&v);CHKERRQ(ierr);
5647   }
5648   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
5649     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
5650   }
5651   PetscFunctionReturn(0);
5652 }
5653 
5654 
5655 #undef __FUNCT__
5656 #define __FUNCT__ "TSMonitorLGSetVariableNames"
5657 /*@C
5658    TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
5659 
5660    Collective on TS
5661 
5662    Input Parameters:
5663 +  ts - the TS context
5664 -  names - the names of the components, final string must be NULL
5665 
5666    Level: intermediate
5667 
5668 .keywords: TS,  vector, monitor, view
5669 
5670 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetVariableNames()
5671 @*/
5672 PetscErrorCode  TSMonitorLGSetVariableNames(TS ts,const char * const *names)
5673 {
5674   PetscErrorCode    ierr;
5675   PetscInt          i;
5676 
5677   PetscFunctionBegin;
5678   for (i=0; i<ts->numbermonitors; i++) {
5679     if (ts->monitor[i] == TSMonitorLGSolution) {
5680       ierr = TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i],names);CHKERRQ(ierr);
5681       break;
5682     }
5683   }
5684   PetscFunctionReturn(0);
5685 }
5686 
5687 #undef __FUNCT__
5688 #define __FUNCT__ "TSMonitorLGCtxSetVariableNames"
5689 /*@C
5690    TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
5691 
5692    Collective on TS
5693 
5694    Input Parameters:
5695 +  ts - the TS context
5696 -  names - the names of the components, final string must be NULL
5697 
5698    Level: intermediate
5699 
5700 .keywords: TS,  vector, monitor, view
5701 
5702 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGSetVariableNames()
5703 @*/
5704 PetscErrorCode  TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx,const char * const *names)
5705 {
5706   PetscErrorCode    ierr;
5707 
5708   PetscFunctionBegin;
5709   ierr = PetscStrArrayDestroy(&ctx->names);CHKERRQ(ierr);
5710   ierr = PetscStrArrayallocpy(names,&ctx->names);CHKERRQ(ierr);
5711   PetscFunctionReturn(0);
5712 }
5713 
5714 #undef __FUNCT__
5715 #define __FUNCT__ "TSMonitorLGGetVariableNames"
5716 /*@C
5717    TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
5718 
5719    Collective on TS
5720 
5721    Input Parameter:
5722 .  ts - the TS context
5723 
5724    Output Parameter:
5725 .  names - the names of the components, final string must be NULL
5726 
5727    Level: intermediate
5728 
5729 .keywords: TS,  vector, monitor, view
5730 
5731 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
5732 @*/
5733 PetscErrorCode  TSMonitorLGGetVariableNames(TS ts,const char *const **names)
5734 {
5735   PetscInt       i;
5736 
5737   PetscFunctionBegin;
5738   *names = NULL;
5739   for (i=0; i<ts->numbermonitors; i++) {
5740     if (ts->monitor[i] == TSMonitorLGSolution) {
5741       TSMonitorLGCtx  ctx = (TSMonitorLGCtx) ts->monitorcontext[i];
5742       *names = (const char *const *)ctx->names;
5743       break;
5744     }
5745   }
5746   PetscFunctionReturn(0);
5747 }
5748 
5749 #undef __FUNCT__
5750 #define __FUNCT__ "TSMonitorLGCtxSetDisplayVariables"
5751 /*@C
5752    TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
5753 
5754    Collective on TS
5755 
5756    Input Parameters:
5757 +  ctx - the TSMonitorLG context
5758 .  displaynames - the names of the components, final string must be NULL
5759 
5760    Level: intermediate
5761 
5762 .keywords: TS,  vector, monitor, view
5763 
5764 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
5765 @*/
5766 PetscErrorCode  TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx,const char * const *displaynames)
5767 {
5768   PetscInt          j = 0,k;
5769   PetscErrorCode    ierr;
5770 
5771   PetscFunctionBegin;
5772   if (!ctx->names) PetscFunctionReturn(0);
5773   ierr = PetscStrArrayDestroy(&ctx->displaynames);CHKERRQ(ierr);
5774   ierr = PetscStrArrayallocpy(displaynames,&ctx->displaynames);CHKERRQ(ierr);
5775   while (displaynames[j]) j++;
5776   ctx->ndisplayvariables = j;
5777   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvariables);CHKERRQ(ierr);
5778   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvalues);CHKERRQ(ierr);
5779   j = 0;
5780   while (displaynames[j]) {
5781     k = 0;
5782     while (ctx->names[k]) {
5783       PetscBool flg;
5784       ierr = PetscStrcmp(displaynames[j],ctx->names[k],&flg);CHKERRQ(ierr);
5785       if (flg) {
5786         ctx->displayvariables[j] = k;
5787         break;
5788       }
5789       k++;
5790     }
5791     j++;
5792   }
5793   PetscFunctionReturn(0);
5794 }
5795 
5796 
5797 #undef __FUNCT__
5798 #define __FUNCT__ "TSMonitorLGSetDisplayVariables"
5799 /*@C
5800    TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
5801 
5802    Collective on TS
5803 
5804    Input Parameters:
5805 +  ts - the TS context
5806 .  displaynames - the names of the components, final string must be NULL
5807 
5808    Level: intermediate
5809 
5810 .keywords: TS,  vector, monitor, view
5811 
5812 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
5813 @*/
5814 PetscErrorCode  TSMonitorLGSetDisplayVariables(TS ts,const char * const *displaynames)
5815 {
5816   PetscInt          i;
5817   PetscErrorCode    ierr;
5818 
5819   PetscFunctionBegin;
5820   for (i=0; i<ts->numbermonitors; i++) {
5821     if (ts->monitor[i] == TSMonitorLGSolution) {
5822       ierr = TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i],displaynames);CHKERRQ(ierr);
5823       break;
5824     }
5825   }
5826   PetscFunctionReturn(0);
5827 }
5828 
5829 #undef __FUNCT__
5830 #define __FUNCT__ "TSMonitorLGSetTransform"
5831 /*@C
5832    TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
5833 
5834    Collective on TS
5835 
5836    Input Parameters:
5837 +  ts - the TS context
5838 .  transform - the transform function
5839 .  destroy - function to destroy the optional context
5840 -  ctx - optional context used by transform function
5841 
5842    Level: intermediate
5843 
5844 .keywords: TS,  vector, monitor, view
5845 
5846 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGCtxSetTransform()
5847 @*/
5848 PetscErrorCode  TSMonitorLGSetTransform(TS ts,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
5849 {
5850   PetscInt          i;
5851   PetscErrorCode    ierr;
5852 
5853   PetscFunctionBegin;
5854   for (i=0; i<ts->numbermonitors; i++) {
5855     if (ts->monitor[i] == TSMonitorLGSolution) {
5856       ierr = TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i],transform,destroy,tctx);CHKERRQ(ierr);
5857     }
5858   }
5859   PetscFunctionReturn(0);
5860 }
5861 
5862 #undef __FUNCT__
5863 #define __FUNCT__ "TSMonitorLGCtxSetTransform"
5864 /*@C
5865    TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
5866 
5867    Collective on TSLGCtx
5868 
5869    Input Parameters:
5870 +  ts - the TS context
5871 .  transform - the transform function
5872 .  destroy - function to destroy the optional context
5873 -  ctx - optional context used by transform function
5874 
5875    Level: intermediate
5876 
5877 .keywords: TS,  vector, monitor, view
5878 
5879 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGSetTransform()
5880 @*/
5881 PetscErrorCode  TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
5882 {
5883   PetscFunctionBegin;
5884   ctx->transform    = transform;
5885   ctx->transformdestroy = destroy;
5886   ctx->transformctx = tctx;
5887   PetscFunctionReturn(0);
5888 }
5889 
5890 #undef __FUNCT__
5891 #define __FUNCT__ "TSMonitorLGError"
5892 /*@C
5893    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the solution vector
5894        in a time based line graph
5895 
5896    Collective on TS
5897 
5898    Input Parameters:
5899 +  ts - the TS context
5900 .  step - current time-step
5901 .  ptime - current time
5902 -  lg - a line graph object
5903 
5904    Level: intermediate
5905 
5906    Notes:
5907    Only for sequential solves.
5908 
5909    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
5910 
5911    Options Database Keys:
5912 .  -ts_monitor_lg_error - create a graphical monitor of error history
5913 
5914 .keywords: TS,  vector, monitor, view
5915 
5916 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
5917 @*/
5918 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5919 {
5920   PetscErrorCode    ierr;
5921   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
5922   const PetscScalar *yy;
5923   Vec               y;
5924   PetscInt          dim;
5925 
5926   PetscFunctionBegin;
5927   if (!step) {
5928     PetscDrawAxis axis;
5929     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
5930     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Solution");CHKERRQ(ierr);
5931     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
5932     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
5933     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
5934   }
5935   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
5936   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
5937   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
5938   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
5939 #if defined(PETSC_USE_COMPLEX)
5940   {
5941     PetscReal *yreal;
5942     PetscInt  i,n;
5943     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
5944     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
5945     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
5946     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
5947     ierr = PetscFree(yreal);CHKERRQ(ierr);
5948   }
5949 #else
5950   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
5951 #endif
5952   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
5953   ierr = VecDestroy(&y);CHKERRQ(ierr);
5954   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
5955     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
5956   }
5957   PetscFunctionReturn(0);
5958 }
5959 
5960 #undef __FUNCT__
5961 #define __FUNCT__ "TSMonitorLGSNESIterations"
5962 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
5963 {
5964   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
5965   PetscReal      x   = ptime,y;
5966   PetscErrorCode ierr;
5967   PetscInt       its;
5968 
5969   PetscFunctionBegin;
5970   if (!n) {
5971     PetscDrawAxis axis;
5972 
5973     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
5974     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
5975     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
5976 
5977     ctx->snes_its = 0;
5978   }
5979   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
5980   y    = its - ctx->snes_its;
5981   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
5982   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
5983     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
5984   }
5985   ctx->snes_its = its;
5986   PetscFunctionReturn(0);
5987 }
5988 
5989 #undef __FUNCT__
5990 #define __FUNCT__ "TSMonitorLGKSPIterations"
5991 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
5992 {
5993   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
5994   PetscReal      x   = ptime,y;
5995   PetscErrorCode ierr;
5996   PetscInt       its;
5997 
5998   PetscFunctionBegin;
5999   if (!n) {
6000     PetscDrawAxis axis;
6001 
6002     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
6003     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
6004     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
6005 
6006     ctx->ksp_its = 0;
6007   }
6008   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
6009   y    = its - ctx->ksp_its;
6010   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
6011   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
6012     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
6013   }
6014   ctx->ksp_its = its;
6015   PetscFunctionReturn(0);
6016 }
6017 
6018 #undef __FUNCT__
6019 #define __FUNCT__ "TSComputeLinearStability"
6020 /*@
6021    TSComputeLinearStability - computes the linear stability function at a point
6022 
6023    Collective on TS and Vec
6024 
6025    Input Parameters:
6026 +  ts - the TS context
6027 -  xr,xi - real and imaginary part of input arguments
6028 
6029    Output Parameters:
6030 .  yr,yi - real and imaginary part of function value
6031 
6032    Level: developer
6033 
6034 .keywords: TS, compute
6035 
6036 .seealso: TSSetRHSFunction(), TSComputeIFunction()
6037 @*/
6038 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
6039 {
6040   PetscErrorCode ierr;
6041 
6042   PetscFunctionBegin;
6043   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6044   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
6045   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
6046   PetscFunctionReturn(0);
6047 }
6048 
6049 /* ------------------------------------------------------------------------*/
6050 #undef __FUNCT__
6051 #define __FUNCT__ "TSMonitorEnvelopeCtxCreate"
6052 /*@C
6053    TSMonitorEnvelopeCtxCreate - Creates a context for use with TSMonitorEnvelope()
6054 
6055    Collective on TS
6056 
6057    Input Parameters:
6058 .  ts  - the ODE solver object
6059 
6060    Output Parameter:
6061 .  ctx - the context
6062 
6063    Level: intermediate
6064 
6065 .keywords: TS, monitor, line graph, residual, seealso
6066 
6067 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
6068 
6069 @*/
6070 PetscErrorCode  TSMonitorEnvelopeCtxCreate(TS ts,TSMonitorEnvelopeCtx *ctx)
6071 {
6072   PetscErrorCode ierr;
6073 
6074   PetscFunctionBegin;
6075   ierr = PetscNew(ctx);CHKERRQ(ierr);
6076   PetscFunctionReturn(0);
6077 }
6078 
6079 #undef __FUNCT__
6080 #define __FUNCT__ "TSMonitorEnvelope"
6081 /*@C
6082    TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
6083 
6084    Collective on TS
6085 
6086    Input Parameters:
6087 +  ts - the TS context
6088 .  step - current time-step
6089 .  ptime - current time
6090 -  ctx - the envelope context
6091 
6092    Options Database:
6093 .  -ts_monitor_envelope
6094 
6095    Level: intermediate
6096 
6097    Notes: after a solve you can use TSMonitorEnvelopeGetBounds() to access the envelope
6098 
6099 .keywords: TS,  vector, monitor, view
6100 
6101 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorEnvelopeGetBounds()
6102 @*/
6103 PetscErrorCode  TSMonitorEnvelope(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
6104 {
6105   PetscErrorCode       ierr;
6106   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dummy;
6107 
6108   PetscFunctionBegin;
6109   if (!ctx->max) {
6110     ierr = VecDuplicate(u,&ctx->max);CHKERRQ(ierr);
6111     ierr = VecDuplicate(u,&ctx->min);CHKERRQ(ierr);
6112     ierr = VecCopy(u,ctx->max);CHKERRQ(ierr);
6113     ierr = VecCopy(u,ctx->min);CHKERRQ(ierr);
6114   } else {
6115     ierr = VecPointwiseMax(ctx->max,u,ctx->max);CHKERRQ(ierr);
6116     ierr = VecPointwiseMin(ctx->min,u,ctx->min);CHKERRQ(ierr);
6117   }
6118   PetscFunctionReturn(0);
6119 }
6120 
6121 
6122 #undef __FUNCT__
6123 #define __FUNCT__ "TSMonitorEnvelopeGetBounds"
6124 /*@C
6125    TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
6126 
6127    Collective on TS
6128 
6129    Input Parameter:
6130 .  ts - the TS context
6131 
6132    Output Parameter:
6133 +  max - the maximum values
6134 -  min - the minimum values
6135 
6136    Level: intermediate
6137 
6138 .keywords: TS,  vector, monitor, view
6139 
6140 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
6141 @*/
6142 PetscErrorCode  TSMonitorEnvelopeGetBounds(TS ts,Vec *max,Vec *min)
6143 {
6144   PetscInt i;
6145 
6146   PetscFunctionBegin;
6147   if (max) *max = NULL;
6148   if (min) *min = NULL;
6149   for (i=0; i<ts->numbermonitors; i++) {
6150     if (ts->monitor[i] == TSMonitorEnvelope) {
6151       TSMonitorEnvelopeCtx  ctx = (TSMonitorEnvelopeCtx) ts->monitorcontext[i];
6152       if (max) *max = ctx->max;
6153       if (min) *min = ctx->min;
6154       break;
6155     }
6156   }
6157   PetscFunctionReturn(0);
6158 }
6159 
6160 #undef __FUNCT__
6161 #define __FUNCT__ "TSMonitorEnvelopeCtxDestroy"
6162 /*@C
6163    TSMonitorEnvelopeCtxDestroy - Destroys a context that was created  with TSMonitorEnvelopeCtxCreate().
6164 
6165    Collective on TSMonitorEnvelopeCtx
6166 
6167    Input Parameter:
6168 .  ctx - the monitor context
6169 
6170    Level: intermediate
6171 
6172 .keywords: TS, monitor, line graph, destroy
6173 
6174 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
6175 @*/
6176 PetscErrorCode  TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
6177 {
6178   PetscErrorCode ierr;
6179 
6180   PetscFunctionBegin;
6181   ierr = VecDestroy(&(*ctx)->min);CHKERRQ(ierr);
6182   ierr = VecDestroy(&(*ctx)->max);CHKERRQ(ierr);
6183   ierr = PetscFree(*ctx);CHKERRQ(ierr);
6184   PetscFunctionReturn(0);
6185 }
6186 
6187 #undef __FUNCT__
6188 #define __FUNCT__ "TSRollBack"
6189 /*@
6190    TSRollBack - Rolls back one time step
6191 
6192    Collective on TS
6193 
6194    Input Parameter:
6195 .  ts - the TS context obtained from TSCreate()
6196 
6197    Level: advanced
6198 
6199 .keywords: TS, timestep, rollback
6200 
6201 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
6202 @*/
6203 PetscErrorCode  TSRollBack(TS ts)
6204 {
6205   PetscErrorCode ierr;
6206 
6207   PetscFunctionBegin;
6208   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
6209 
6210   if (!ts->ops->rollback) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
6211   ierr = (*ts->ops->rollback)(ts);CHKERRQ(ierr);
6212   ts->time_step = ts->ptime - ts->ptime_prev;
6213   ts->ptime = ts->ptime_prev;
6214   ts->steprollback = PETSC_TRUE; /* Flag to indicate that the step is rollbacked */
6215   PetscFunctionReturn(0);
6216 }
6217 
6218 #undef __FUNCT__
6219 #define __FUNCT__ "TSGetStages"
6220 /*@
6221    TSGetStages - Get the number of stages and stage values
6222 
6223    Input Parameter:
6224 .  ts - the TS context obtained from TSCreate()
6225 
6226    Level: advanced
6227 
6228 .keywords: TS, getstages
6229 
6230 .seealso: TSCreate()
6231 @*/
6232 PetscErrorCode  TSGetStages(TS ts,PetscInt *ns, Vec **Y)
6233 {
6234   PetscErrorCode ierr;
6235 
6236   PetscFunctionBegin;
6237   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
6238   PetscValidPointer(ns,2);
6239 
6240   if (!ts->ops->getstages) *ns=0;
6241   else {
6242     ierr = (*ts->ops->getstages)(ts,ns,Y);CHKERRQ(ierr);
6243   }
6244   PetscFunctionReturn(0);
6245 }
6246 
6247 
6248 #undef __FUNCT__
6249 #define __FUNCT__ "TSComputeIJacobianDefaultColor"
6250 /*@C
6251   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
6252 
6253   Collective on SNES
6254 
6255   Input Parameters:
6256 + ts - the TS context
6257 . t - current timestep
6258 . U - state vector
6259 . Udot - time derivative of state vector
6260 . shift - shift to apply, see note below
6261 - ctx - an optional user context
6262 
6263   Output Parameters:
6264 + J - Jacobian matrix (not altered in this routine)
6265 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
6266 
6267   Level: intermediate
6268 
6269   Notes:
6270   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
6271 
6272   dF/dU + shift*dF/dUdot
6273 
6274   Most users should not need to explicitly call this routine, as it
6275   is used internally within the nonlinear solvers.
6276 
6277   This will first try to get the coloring from the DM.  If the DM type has no coloring
6278   routine, then it will try to get the coloring from the matrix.  This requires that the
6279   matrix have nonzero entries precomputed.
6280 
6281 .keywords: TS, finite differences, Jacobian, coloring, sparse
6282 .seealso: TSSetIJacobian(), MatFDColoringCreate(), MatFDColoringSetFunction()
6283 @*/
6284 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat J,Mat B,void *ctx)
6285 {
6286   SNES           snes;
6287   MatFDColoring  color;
6288   PetscBool      hascolor, matcolor = PETSC_FALSE;
6289   PetscErrorCode ierr;
6290 
6291   PetscFunctionBegin;
6292   ierr = PetscOptionsGetBool(((PetscObject) ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL);CHKERRQ(ierr);
6293   ierr = PetscObjectQuery((PetscObject) B, "TSMatFDColoring", (PetscObject *) &color);CHKERRQ(ierr);
6294   if (!color) {
6295     DM         dm;
6296     ISColoring iscoloring;
6297 
6298     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
6299     ierr = DMHasColoring(dm, &hascolor);CHKERRQ(ierr);
6300     if (hascolor && !matcolor) {
6301       ierr = DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring);CHKERRQ(ierr);
6302       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
6303       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
6304       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
6305       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
6306       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
6307     } else {
6308       MatColoring mc;
6309 
6310       ierr = MatColoringCreate(B, &mc);CHKERRQ(ierr);
6311       ierr = MatColoringSetDistance(mc, 2);CHKERRQ(ierr);
6312       ierr = MatColoringSetType(mc, MATCOLORINGSL);CHKERRQ(ierr);
6313       ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr);
6314       ierr = MatColoringApply(mc, &iscoloring);CHKERRQ(ierr);
6315       ierr = MatColoringDestroy(&mc);CHKERRQ(ierr);
6316       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
6317       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
6318       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
6319       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
6320       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
6321     }
6322     ierr = PetscObjectCompose((PetscObject) B, "TSMatFDColoring", (PetscObject) color);CHKERRQ(ierr);
6323     ierr = PetscObjectDereference((PetscObject) color);CHKERRQ(ierr);
6324   }
6325   ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
6326   ierr = MatFDColoringApply(B, color, U, snes);CHKERRQ(ierr);
6327   if (J != B) {
6328     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6329     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6330   }
6331   PetscFunctionReturn(0);
6332 }
6333