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