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