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