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