xref: /petsc/src/ts/interface/ts.c (revision 0e9ea286fb2a802ae93ee195655c93a598b51114)
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   PetscFunctionBegin;
3265   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3266   if (ts->prestage) {
3267     PetscStackCallStandard((*ts->prestage),(ts,stagetime));
3268   }
3269   PetscFunctionReturn(0);
3270 }
3271 
3272 /*@
3273   TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage()
3274 
3275   Collective on TS
3276 
3277   Input Parameters:
3278 . ts          - The TS context obtained from TSCreate()
3279   stagetime   - The absolute time of the current stage
3280   stageindex  - Stage number
3281   Y           - Array of vectors (of size = total number
3282                 of stages) with the stage solutions
3283 
3284   Notes:
3285   TSPostStage() is typically used within time stepping implementations,
3286   most users would not generally call this routine themselves.
3287 
3288   Level: developer
3289 
3290 .keywords: TS, timestep
3291 .seealso: TSPreStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
3292 @*/
3293 PetscErrorCode  TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
3294 {
3295   PetscFunctionBegin;
3296   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3297   if (ts->poststage) {
3298     PetscStackCallStandard((*ts->poststage),(ts,stagetime,stageindex,Y));
3299   }
3300   PetscFunctionReturn(0);
3301 }
3302 
3303 /*@
3304   TSPostEvaluate - Runs the user-defined post-evaluate function set using TSSetPostEvaluate()
3305 
3306   Collective on TS
3307 
3308   Input Parameters:
3309 . ts          - The TS context obtained from TSCreate()
3310 
3311   Notes:
3312   TSPostEvaluate() is typically used within time stepping implementations,
3313   most users would not generally call this routine themselves.
3314 
3315   Level: developer
3316 
3317 .keywords: TS, timestep
3318 .seealso: TSSetPostEvaluate(), TSSetPreStep(), TSPreStep(), TSPostStep()
3319 @*/
3320 PetscErrorCode  TSPostEvaluate(TS ts)
3321 {
3322   PetscErrorCode ierr;
3323 
3324   PetscFunctionBegin;
3325   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3326   if (ts->postevaluate) {
3327     Vec              U;
3328     PetscObjectState sprev,spost;
3329 
3330     ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
3331     ierr = PetscObjectStateGet((PetscObject)U,&sprev);CHKERRQ(ierr);
3332     PetscStackCallStandard((*ts->postevaluate),(ts));
3333     ierr = PetscObjectStateGet((PetscObject)U,&spost);CHKERRQ(ierr);
3334     if (sprev != spost) {ierr = TSRestartStep(ts);CHKERRQ(ierr);}
3335   }
3336   PetscFunctionReturn(0);
3337 }
3338 
3339 /*@C
3340   TSSetPostStep - Sets the general-purpose function
3341   called once at the end of each time step.
3342 
3343   Logically Collective on TS
3344 
3345   Input Parameters:
3346 + ts   - The TS context obtained from TSCreate()
3347 - func - The function
3348 
3349   Calling sequence of func:
3350 $ func (TS ts);
3351 
3352   Notes:
3353   The function set by TSSetPostStep() is called after each successful step. The solution vector X
3354   obtained by TSGetSolution() may be different than that computed at the step end if the event handler
3355   locates an event and TSPostEvent() modifies it. Use TSSetPostEvaluate() if an unmodified solution is needed instead.
3356 
3357   Level: intermediate
3358 
3359 .keywords: TS, timestep
3360 .seealso: TSSetPreStep(), TSSetPreStage(), TSSetPostEvaluate(), TSGetTimeStep(), TSGetStepNumber(), TSGetTime(), TSRestartStep()
3361 @*/
3362 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
3363 {
3364   PetscFunctionBegin;
3365   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3366   ts->poststep = func;
3367   PetscFunctionReturn(0);
3368 }
3369 
3370 /*@
3371   TSPostStep - Runs the user-defined post-step function.
3372 
3373   Collective on TS
3374 
3375   Input Parameters:
3376 . ts   - The TS context obtained from TSCreate()
3377 
3378   Notes:
3379   TSPostStep() is typically used within time stepping implementations,
3380   so most users would not generally call this routine themselves.
3381 
3382   Level: developer
3383 
3384 .keywords: TS, timestep
3385 @*/
3386 PetscErrorCode  TSPostStep(TS ts)
3387 {
3388   PetscErrorCode ierr;
3389 
3390   PetscFunctionBegin;
3391   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3392   if (ts->poststep) {
3393     Vec              U;
3394     PetscObjectState sprev,spost;
3395 
3396     ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
3397     ierr = PetscObjectStateGet((PetscObject)U,&sprev);CHKERRQ(ierr);
3398     PetscStackCallStandard((*ts->poststep),(ts));
3399     ierr = PetscObjectStateGet((PetscObject)U,&spost);CHKERRQ(ierr);
3400     if (sprev != spost) {ierr = TSRestartStep(ts);CHKERRQ(ierr);}
3401   }
3402   PetscFunctionReturn(0);
3403 }
3404 
3405 /* ------------ Routines to set performance monitoring options ----------- */
3406 
3407 /*@C
3408    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
3409    timestep to display the iteration's  progress.
3410 
3411    Logically Collective on TS
3412 
3413    Input Parameters:
3414 +  ts - the TS context obtained from TSCreate()
3415 .  monitor - monitoring routine
3416 .  mctx - [optional] user-defined context for private data for the
3417              monitor routine (use NULL if no context is desired)
3418 -  monitordestroy - [optional] routine that frees monitor context
3419           (may be NULL)
3420 
3421    Calling sequence of monitor:
3422 $    PetscErrorCode monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
3423 
3424 +    ts - the TS context
3425 .    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)
3426 .    time - current time
3427 .    u - current iterate
3428 -    mctx - [optional] monitoring context
3429 
3430    Notes:
3431    This routine adds an additional monitor to the list of monitors that
3432    already has been loaded.
3433 
3434    Fortran Notes:
3435     Only a single monitor function can be set for each TS object
3436 
3437    Level: intermediate
3438 
3439 .keywords: TS, timestep, set, monitor
3440 
3441 .seealso: TSMonitorDefault(), TSMonitorCancel()
3442 @*/
3443 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
3444 {
3445   PetscErrorCode ierr;
3446   PetscInt       i;
3447   PetscBool      identical;
3448 
3449   PetscFunctionBegin;
3450   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3451   for (i=0; i<ts->numbermonitors;i++) {
3452     ierr = PetscMonitorCompare((PetscErrorCode (*)(void))monitor,mctx,mdestroy,(PetscErrorCode (*)(void))ts->monitor[i],ts->monitorcontext[i],ts->monitordestroy[i],&identical);CHKERRQ(ierr);
3453     if (identical) PetscFunctionReturn(0);
3454   }
3455   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
3456   ts->monitor[ts->numbermonitors]          = monitor;
3457   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
3458   ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
3459   PetscFunctionReturn(0);
3460 }
3461 
3462 /*@C
3463    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
3464 
3465    Logically Collective on TS
3466 
3467    Input Parameters:
3468 .  ts - the TS context obtained from TSCreate()
3469 
3470    Notes:
3471    There is no way to remove a single, specific monitor.
3472 
3473    Level: intermediate
3474 
3475 .keywords: TS, timestep, set, monitor
3476 
3477 .seealso: TSMonitorDefault(), TSMonitorSet()
3478 @*/
3479 PetscErrorCode  TSMonitorCancel(TS ts)
3480 {
3481   PetscErrorCode ierr;
3482   PetscInt       i;
3483 
3484   PetscFunctionBegin;
3485   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3486   for (i=0; i<ts->numbermonitors; i++) {
3487     if (ts->monitordestroy[i]) {
3488       ierr = (*ts->monitordestroy[i])(&ts->monitorcontext[i]);CHKERRQ(ierr);
3489     }
3490   }
3491   ts->numbermonitors = 0;
3492   PetscFunctionReturn(0);
3493 }
3494 
3495 /*@C
3496    TSMonitorDefault - The Default monitor, prints the timestep and time for each step
3497 
3498    Level: intermediate
3499 
3500 .keywords: TS, set, monitor
3501 
3502 .seealso:  TSMonitorSet()
3503 @*/
3504 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscViewerAndFormat *vf)
3505 {
3506   PetscErrorCode ierr;
3507   PetscViewer    viewer =  vf->viewer;
3508   PetscBool      iascii,ibinary;
3509 
3510   PetscFunctionBegin;
3511   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
3512   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
3513   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
3514   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
3515   if (iascii) {
3516     ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3517     if (step == -1){ /* this indicates it is an interpolated solution */
3518       ierr = PetscViewerASCIIPrintf(viewer,"Interpolated solution at time %g between steps %D and %D\n",(double)ptime,ts->steps-1,ts->steps);CHKERRQ(ierr);
3519     } else {
3520       ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr);
3521     }
3522     ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3523   } else if (ibinary) {
3524     PetscMPIInt rank;
3525     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
3526     if (!rank) {
3527       PetscBool skipHeader;
3528       PetscInt  classid = REAL_FILE_CLASSID;
3529 
3530       ierr = PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);CHKERRQ(ierr);
3531       if (!skipHeader) {
3532          ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
3533        }
3534       ierr = PetscRealView(1,&ptime,viewer);CHKERRQ(ierr);
3535     } else {
3536       ierr = PetscRealView(0,&ptime,viewer);CHKERRQ(ierr);
3537     }
3538   }
3539   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
3540   PetscFunctionReturn(0);
3541 }
3542 
3543 /*@C
3544    TSMonitorExtreme - Prints the extreme values of the solution at each timestep
3545 
3546    Level: intermediate
3547 
3548 .keywords: TS, set, monitor
3549 
3550 .seealso:  TSMonitorSet()
3551 @*/
3552 PetscErrorCode TSMonitorExtreme(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscViewerAndFormat *vf)
3553 {
3554   PetscErrorCode ierr;
3555   PetscViewer    viewer =  vf->viewer;
3556   PetscBool      iascii;
3557   PetscReal      max,min;
3558 
3559 
3560   PetscFunctionBegin;
3561   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
3562   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
3563   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
3564   if (iascii) {
3565     ierr = VecMax(v,NULL,&max);CHKERRQ(ierr);
3566     ierr = VecMin(v,NULL,&min);CHKERRQ(ierr);
3567     ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3568     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);
3569     ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3570   }
3571   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
3572   PetscFunctionReturn(0);
3573 }
3574 
3575 /*@
3576    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
3577 
3578    Collective on TS
3579 
3580    Input Argument:
3581 +  ts - time stepping context
3582 -  t - time to interpolate to
3583 
3584    Output Argument:
3585 .  U - state at given time
3586 
3587    Level: intermediate
3588 
3589    Developer Notes:
3590    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
3591 
3592 .keywords: TS, set
3593 
3594 .seealso: TSSetExactFinalTime(), TSSolve()
3595 @*/
3596 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
3597 {
3598   PetscErrorCode ierr;
3599 
3600   PetscFunctionBegin;
3601   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3602   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3603   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);
3604   if (!ts->ops->interpolate) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
3605   ierr = (*ts->ops->interpolate)(ts,t,U);CHKERRQ(ierr);
3606   PetscFunctionReturn(0);
3607 }
3608 
3609 /*@
3610    TSStep - Steps one time step
3611 
3612    Collective on TS
3613 
3614    Input Parameter:
3615 .  ts - the TS context obtained from TSCreate()
3616 
3617    Level: developer
3618 
3619    Notes:
3620    The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine.
3621 
3622    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
3623    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
3624 
3625    This may over-step the final time provided in TSSetMaxTime() depending on the time-step used. TSSolve() interpolates to exactly the
3626    time provided in TSSetMaxTime(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
3627 
3628 .keywords: TS, timestep, solve
3629 
3630 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate()
3631 @*/
3632 PetscErrorCode  TSStep(TS ts)
3633 {
3634   PetscErrorCode   ierr;
3635   static PetscBool cite = PETSC_FALSE;
3636   PetscReal        ptime;
3637 
3638   PetscFunctionBegin;
3639   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3640   ierr = PetscCitationsRegister("@techreport{tspaper,\n"
3641                                 "  title       = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3642                                 "  author      = {Shrirang Abhyankar and Jed Brown and Emil Constantinescu and Debojyoti Ghosh and Barry F. Smith},\n"
3643                                 "  type        = {Preprint},\n"
3644                                 "  number      = {ANL/MCS-P5061-0114},\n"
3645                                 "  institution = {Argonne National Laboratory},\n"
3646                                 "  year        = {2014}\n}\n",&cite);CHKERRQ(ierr);
3647 
3648   ierr = TSSetUp(ts);CHKERRQ(ierr);
3649   ierr = TSTrajectorySetUp(ts->trajectory,ts);CHKERRQ(ierr);
3650 
3651   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>");
3652   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()");
3653   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");
3654 
3655   if (!ts->steps) ts->ptime_prev = ts->ptime;
3656   ptime = ts->ptime; ts->ptime_prev_rollback = ts->ptime_prev;
3657   ts->reason = TS_CONVERGED_ITERATING;
3658   if (!ts->ops->step) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3659   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3660   ierr = (*ts->ops->step)(ts);CHKERRQ(ierr);
3661   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
3662   ts->ptime_prev = ptime;
3663   ts->steps++;
3664   ts->steprollback = PETSC_FALSE;
3665   ts->steprestart  = PETSC_FALSE;
3666 
3667   if (ts->reason < 0) {
3668     if (ts->errorifstepfailed) {
3669       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]);
3670       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
3671     }
3672   } else if (!ts->reason) {
3673     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
3674     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3675   }
3676   PetscFunctionReturn(0);
3677 }
3678 
3679 /*@
3680    TSEvaluateWLTE - Evaluate the weighted local truncation error norm
3681    at the end of a time step with a given order of accuracy.
3682 
3683    Collective on TS
3684 
3685    Input Arguments:
3686 +  ts - time stepping context
3687 .  wnormtype - norm type, either NORM_2 or NORM_INFINITY
3688 -  order - optional, desired order for the error evaluation or PETSC_DECIDE
3689 
3690    Output Arguments:
3691 +  order - optional, the actual order of the error evaluation
3692 -  wlte - the weighted local truncation error norm
3693 
3694    Level: advanced
3695 
3696    Notes:
3697    If the timestepper cannot evaluate the error in a particular step
3698    (eg. in the first step or restart steps after event handling),
3699    this routine returns wlte=-1.0 .
3700 
3701 .seealso: TSStep(), TSAdapt, TSErrorWeightedNorm()
3702 @*/
3703 PetscErrorCode TSEvaluateWLTE(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte)
3704 {
3705   PetscErrorCode ierr;
3706 
3707   PetscFunctionBegin;
3708   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3709   PetscValidType(ts,1);
3710   PetscValidLogicalCollectiveEnum(ts,wnormtype,4);
3711   if (order) PetscValidIntPointer(order,3);
3712   if (order) PetscValidLogicalCollectiveInt(ts,*order,3);
3713   PetscValidRealPointer(wlte,4);
3714   if (wnormtype != NORM_2 && wnormtype != NORM_INFINITY) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
3715   if (!ts->ops->evaluatewlte) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateWLTE not implemented for type '%s'",((PetscObject)ts)->type_name);
3716   ierr = (*ts->ops->evaluatewlte)(ts,wnormtype,order,wlte);CHKERRQ(ierr);
3717   PetscFunctionReturn(0);
3718 }
3719 
3720 /*@
3721    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
3722 
3723    Collective on TS
3724 
3725    Input Arguments:
3726 +  ts - time stepping context
3727 .  order - desired order of accuracy
3728 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
3729 
3730    Output Arguments:
3731 .  U - state at the end of the current step
3732 
3733    Level: advanced
3734 
3735    Notes:
3736    This function cannot be called until all stages have been evaluated.
3737    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.
3738 
3739 .seealso: TSStep(), TSAdapt
3740 @*/
3741 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
3742 {
3743   PetscErrorCode ierr;
3744 
3745   PetscFunctionBegin;
3746   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3747   PetscValidType(ts,1);
3748   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
3749   if (!ts->ops->evaluatestep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
3750   ierr = (*ts->ops->evaluatestep)(ts,order,U,done);CHKERRQ(ierr);
3751   PetscFunctionReturn(0);
3752 }
3753 
3754 /*@
3755    TSSolve - Steps the requested number of timesteps.
3756 
3757    Collective on TS
3758 
3759    Input Parameter:
3760 +  ts - the TS context obtained from TSCreate()
3761 -  u - the solution vector  (can be null if TSSetSolution() was used and TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP) was not used,
3762                              otherwise must contain the initial conditions and will contain the solution at the final requested time
3763 
3764    Level: beginner
3765 
3766    Notes:
3767    The final time returned by this function may be different from the time of the internally
3768    held state accessible by TSGetSolution() and TSGetTime() because the method may have
3769    stepped over the final time.
3770 
3771 .keywords: TS, timestep, solve
3772 
3773 .seealso: TSCreate(), TSSetSolution(), TSStep(), TSGetTime(), TSGetSolveTime()
3774 @*/
3775 PetscErrorCode TSSolve(TS ts,Vec u)
3776 {
3777   Vec               solution;
3778   PetscErrorCode    ierr;
3779 
3780   PetscFunctionBegin;
3781   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3782   if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3783 
3784   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 */
3785     if (!ts->vec_sol || u == ts->vec_sol) {
3786       ierr = VecDuplicate(u,&solution);CHKERRQ(ierr);
3787       ierr = TSSetSolution(ts,solution);CHKERRQ(ierr);
3788       ierr = VecDestroy(&solution);CHKERRQ(ierr); /* grant ownership */
3789     }
3790     ierr = VecCopy(u,ts->vec_sol);CHKERRQ(ierr);
3791     if (ts->forward_solve) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
3792   } else if (u) {
3793     ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
3794   }
3795   ierr = TSSetUp(ts);CHKERRQ(ierr);
3796   ierr = TSTrajectorySetUp(ts->trajectory,ts);CHKERRQ(ierr);
3797 
3798   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>");
3799   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()");
3800   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");
3801 
3802   if (ts->forward_solve) {
3803     ierr = TSForwardSetUp(ts);CHKERRQ(ierr);
3804   }
3805 
3806   /* reset number of steps only when the step is not restarted. ARKIMEX
3807      restarts the step after an event. Resetting these counters in such case causes
3808      TSTrajectory to incorrectly save the output files
3809   */
3810   /* reset time step and iteration counters */
3811   if (!ts->steps) {
3812     ts->ksp_its           = 0;
3813     ts->snes_its          = 0;
3814     ts->num_snes_failures = 0;
3815     ts->reject            = 0;
3816     ts->steprestart       = PETSC_TRUE;
3817     ts->steprollback      = PETSC_FALSE;
3818   }
3819   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP && ts->ptime + ts->time_step > ts->max_time) ts->time_step = ts->max_time - ts->ptime;
3820   ts->reason = TS_CONVERGED_ITERATING;
3821 
3822   ierr = TSViewFromOptions(ts,NULL,"-ts_view_pre");CHKERRQ(ierr);
3823 
3824   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
3825     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
3826     if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
3827     ts->solvetime = ts->ptime;
3828     solution = ts->vec_sol;
3829   } else { /* Step the requested number of timesteps. */
3830     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
3831     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
3832 
3833     if (!ts->steps) {
3834       ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3835       ierr = TSEventInitialize(ts->event,ts,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3836     }
3837 
3838     while (!ts->reason) {
3839       ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3840       if (!ts->steprollback) {
3841         ierr = TSPreStep(ts);CHKERRQ(ierr);
3842       }
3843       ierr = TSStep(ts);CHKERRQ(ierr);
3844       if (ts->testjacobian) {
3845         ierr = TSRHSJacobianTest(ts,NULL);CHKERRQ(ierr);
3846       }
3847       if (ts->testjacobiantranspose) {
3848         ierr = TSRHSJacobianTestTranspose(ts,NULL);CHKERRQ(ierr);
3849       }
3850       if (ts->vec_costintegral && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
3851         ierr = TSForwardCostIntegral(ts);CHKERRQ(ierr);
3852       }
3853       if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
3854         ierr = TSForwardStep(ts);CHKERRQ(ierr);
3855       }
3856       ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
3857       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. */
3858       if (ts->steprollback) {
3859         ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
3860       }
3861       if (!ts->steprollback) {
3862         ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3863         ierr = TSPostStep(ts);CHKERRQ(ierr);
3864       }
3865     }
3866     ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
3867 
3868     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
3869       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
3870       ts->solvetime = ts->max_time;
3871       solution = u;
3872       ierr = TSMonitor(ts,-1,ts->solvetime,solution);CHKERRQ(ierr);
3873     } else {
3874       if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
3875       ts->solvetime = ts->ptime;
3876       solution = ts->vec_sol;
3877     }
3878   }
3879 
3880   ierr = TSViewFromOptions(ts,NULL,"-ts_view");CHKERRQ(ierr);
3881   ierr = VecViewFromOptions(solution,NULL,"-ts_view_solution");CHKERRQ(ierr);
3882   ierr = PetscObjectSAWsBlock((PetscObject)ts);CHKERRQ(ierr);
3883   if (ts->adjoint_solve) {
3884     ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
3885   }
3886   PetscFunctionReturn(0);
3887 }
3888 
3889 /*@C
3890    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
3891 
3892    Collective on TS
3893 
3894    Input Parameters:
3895 +  ts - time stepping context obtained from TSCreate()
3896 .  step - step number that has just completed
3897 .  ptime - model time of the state
3898 -  u - state at the current model time
3899 
3900    Notes:
3901    TSMonitor() is typically used automatically within the time stepping implementations.
3902    Users would almost never call this routine directly.
3903 
3904    A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
3905 
3906    Level: developer
3907 
3908 .keywords: TS, timestep
3909 @*/
3910 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
3911 {
3912   DM             dm;
3913   PetscInt       i,n = ts->numbermonitors;
3914   PetscErrorCode ierr;
3915 
3916   PetscFunctionBegin;
3917   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3918   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
3919 
3920   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3921   ierr = DMSetOutputSequenceNumber(dm,step,ptime);CHKERRQ(ierr);
3922 
3923   ierr = VecLockPush(u);CHKERRQ(ierr);
3924   for (i=0; i<n; i++) {
3925     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
3926   }
3927   ierr = VecLockPop(u);CHKERRQ(ierr);
3928   PetscFunctionReturn(0);
3929 }
3930 
3931 /* ------------------------------------------------------------------------*/
3932 /*@C
3933    TSMonitorLGCtxCreate - Creates a TSMonitorLGCtx context for use with
3934    TS to monitor the solution process graphically in various ways
3935 
3936    Collective on TS
3937 
3938    Input Parameters:
3939 +  host - the X display to open, or null for the local machine
3940 .  label - the title to put in the title bar
3941 .  x, y - the screen coordinates of the upper left coordinate of the window
3942 .  m, n - the screen width and height in pixels
3943 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
3944 
3945    Output Parameter:
3946 .  ctx - the context
3947 
3948    Options Database Key:
3949 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
3950 +  -ts_monitor_lg_timestep_log - automatically sets line graph monitor
3951 .  -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling TSMonitorLGSetDisplayVariables() or TSMonitorLGCtxSetDisplayVariables())
3952 .  -ts_monitor_lg_error -  monitor the error
3953 .  -ts_monitor_lg_ksp_iterations - monitor the number of KSP iterations needed for each timestep
3954 .  -ts_monitor_lg_snes_iterations - monitor the number of SNES iterations needed for each timestep
3955 -  -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
3956 
3957    Notes:
3958    Use TSMonitorLGCtxDestroy() to destroy.
3959 
3960    One can provide a function that transforms the solution before plotting it with TSMonitorLGCtxSetTransform() or TSMonitorLGSetTransform()
3961 
3962    Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a TS object as the
3963    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
3964    as the first argument.
3965 
3966    One can control the names displayed for each solution or error variable with TSMonitorLGCtxSetVariableNames() or TSMonitorLGSetVariableNames()
3967 
3968    Level: intermediate
3969 
3970 .keywords: TS, monitor, line graph, residual
3971 
3972 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError(), TSMonitorDefault(), VecView(),
3973            TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
3974            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
3975            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
3976            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
3977 
3978 @*/
3979 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
3980 {
3981   PetscDraw      draw;
3982   PetscErrorCode ierr;
3983 
3984   PetscFunctionBegin;
3985   ierr = PetscNew(ctx);CHKERRQ(ierr);
3986   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&draw);CHKERRQ(ierr);
3987   ierr = PetscDrawSetFromOptions(draw);CHKERRQ(ierr);
3988   ierr = PetscDrawLGCreate(draw,1,&(*ctx)->lg);CHKERRQ(ierr);
3989   ierr = PetscDrawLGSetFromOptions((*ctx)->lg);CHKERRQ(ierr);
3990   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
3991   (*ctx)->howoften = howoften;
3992   PetscFunctionReturn(0);
3993 }
3994 
3995 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
3996 {
3997   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
3998   PetscReal      x   = ptime,y;
3999   PetscErrorCode ierr;
4000 
4001   PetscFunctionBegin;
4002   if (step < 0) PetscFunctionReturn(0); /* -1 indicates an interpolated solution */
4003   if (!step) {
4004     PetscDrawAxis axis;
4005     const char *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
4006     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4007     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time",ylabel);CHKERRQ(ierr);
4008     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4009   }
4010   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
4011   if (ctx->semilogy) y = PetscLog10Real(y);
4012   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4013   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4014     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4015     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
4016   }
4017   PetscFunctionReturn(0);
4018 }
4019 
4020 /*@C
4021    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
4022    with TSMonitorLGCtxCreate().
4023 
4024    Collective on TSMonitorLGCtx
4025 
4026    Input Parameter:
4027 .  ctx - the monitor context
4028 
4029    Level: intermediate
4030 
4031 .keywords: TS, monitor, line graph, destroy
4032 
4033 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
4034 @*/
4035 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
4036 {
4037   PetscErrorCode ierr;
4038 
4039   PetscFunctionBegin;
4040   if ((*ctx)->transformdestroy) {
4041     ierr = ((*ctx)->transformdestroy)((*ctx)->transformctx);CHKERRQ(ierr);
4042   }
4043   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
4044   ierr = PetscStrArrayDestroy(&(*ctx)->names);CHKERRQ(ierr);
4045   ierr = PetscStrArrayDestroy(&(*ctx)->displaynames);CHKERRQ(ierr);
4046   ierr = PetscFree((*ctx)->displayvariables);CHKERRQ(ierr);
4047   ierr = PetscFree((*ctx)->displayvalues);CHKERRQ(ierr);
4048   ierr = PetscFree(*ctx);CHKERRQ(ierr);
4049   PetscFunctionReturn(0);
4050 }
4051 
4052 /*@
4053    TSGetTime - Gets the time of the most recently completed step.
4054 
4055    Not Collective
4056 
4057    Input Parameter:
4058 .  ts - the TS context obtained from TSCreate()
4059 
4060    Output Parameter:
4061 .  t  - the current time. This time may not corresponds to the final time set with TSSetMaxTime(), use TSGetSolveTime().
4062 
4063    Level: beginner
4064 
4065    Note:
4066    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
4067    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
4068 
4069 .seealso:  TSGetSolveTime(), TSSetTime(), TSGetTimeStep()
4070 
4071 .keywords: TS, get, time
4072 @*/
4073 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
4074 {
4075   PetscFunctionBegin;
4076   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4077   PetscValidRealPointer(t,2);
4078   *t = ts->ptime;
4079   PetscFunctionReturn(0);
4080 }
4081 
4082 /*@
4083    TSGetPrevTime - Gets the starting time of the previously completed step.
4084 
4085    Not Collective
4086 
4087    Input Parameter:
4088 .  ts - the TS context obtained from TSCreate()
4089 
4090    Output Parameter:
4091 .  t  - the previous time
4092 
4093    Level: beginner
4094 
4095 .seealso: TSGetTime(), TSGetSolveTime(), TSGetTimeStep()
4096 
4097 .keywords: TS, get, time
4098 @*/
4099 PetscErrorCode  TSGetPrevTime(TS ts,PetscReal *t)
4100 {
4101   PetscFunctionBegin;
4102   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4103   PetscValidRealPointer(t,2);
4104   *t = ts->ptime_prev;
4105   PetscFunctionReturn(0);
4106 }
4107 
4108 /*@
4109    TSSetTime - Allows one to reset the time.
4110 
4111    Logically Collective on TS
4112 
4113    Input Parameters:
4114 +  ts - the TS context obtained from TSCreate()
4115 -  time - the time
4116 
4117    Level: intermediate
4118 
4119 .seealso: TSGetTime(), TSSetMaxSteps()
4120 
4121 .keywords: TS, set, time
4122 @*/
4123 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
4124 {
4125   PetscFunctionBegin;
4126   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4127   PetscValidLogicalCollectiveReal(ts,t,2);
4128   ts->ptime = t;
4129   PetscFunctionReturn(0);
4130 }
4131 
4132 /*@C
4133    TSSetOptionsPrefix - Sets the prefix used for searching for all
4134    TS options in the database.
4135 
4136    Logically Collective on TS
4137 
4138    Input Parameter:
4139 +  ts     - The TS context
4140 -  prefix - The prefix to prepend to all option names
4141 
4142    Notes:
4143    A hyphen (-) must NOT be given at the beginning of the prefix name.
4144    The first character of all runtime options is AUTOMATICALLY the
4145    hyphen.
4146 
4147    Level: advanced
4148 
4149 .keywords: TS, set, options, prefix, database
4150 
4151 .seealso: TSSetFromOptions()
4152 
4153 @*/
4154 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
4155 {
4156   PetscErrorCode ierr;
4157   SNES           snes;
4158 
4159   PetscFunctionBegin;
4160   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4161   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4162   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4163   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4164   PetscFunctionReturn(0);
4165 }
4166 
4167 /*@C
4168    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4169    TS options in the database.
4170 
4171    Logically Collective on TS
4172 
4173    Input Parameter:
4174 +  ts     - The TS context
4175 -  prefix - The prefix to prepend to all option names
4176 
4177    Notes:
4178    A hyphen (-) must NOT be given at the beginning of the prefix name.
4179    The first character of all runtime options is AUTOMATICALLY the
4180    hyphen.
4181 
4182    Level: advanced
4183 
4184 .keywords: TS, append, options, prefix, database
4185 
4186 .seealso: TSGetOptionsPrefix()
4187 
4188 @*/
4189 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
4190 {
4191   PetscErrorCode ierr;
4192   SNES           snes;
4193 
4194   PetscFunctionBegin;
4195   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4196   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4197   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4198   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4199   PetscFunctionReturn(0);
4200 }
4201 
4202 /*@C
4203    TSGetOptionsPrefix - Sets the prefix used for searching for all
4204    TS options in the database.
4205 
4206    Not Collective
4207 
4208    Input Parameter:
4209 .  ts - The TS context
4210 
4211    Output Parameter:
4212 .  prefix - A pointer to the prefix string used
4213 
4214    Notes:
4215     On the fortran side, the user should pass in a string 'prifix' of
4216    sufficient length to hold the prefix.
4217 
4218    Level: intermediate
4219 
4220 .keywords: TS, get, options, prefix, database
4221 
4222 .seealso: TSAppendOptionsPrefix()
4223 @*/
4224 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
4225 {
4226   PetscErrorCode ierr;
4227 
4228   PetscFunctionBegin;
4229   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4230   PetscValidPointer(prefix,2);
4231   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4232   PetscFunctionReturn(0);
4233 }
4234 
4235 /*@C
4236    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4237 
4238    Not Collective, but parallel objects are returned if TS is parallel
4239 
4240    Input Parameter:
4241 .  ts  - The TS context obtained from TSCreate()
4242 
4243    Output Parameters:
4244 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
4245 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
4246 .  func - Function to compute the Jacobian of the RHS  (or NULL)
4247 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
4248 
4249    Notes:
4250     You can pass in NULL for any return argument you do not need.
4251 
4252    Level: intermediate
4253 
4254 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4255 
4256 .keywords: TS, timestep, get, matrix, Jacobian
4257 @*/
4258 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
4259 {
4260   PetscErrorCode ierr;
4261   DM             dm;
4262 
4263   PetscFunctionBegin;
4264   if (Amat || Pmat) {
4265     SNES snes;
4266     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4267     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4268     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4269   }
4270   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4271   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
4272   PetscFunctionReturn(0);
4273 }
4274 
4275 /*@C
4276    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4277 
4278    Not Collective, but parallel objects are returned if TS is parallel
4279 
4280    Input Parameter:
4281 .  ts  - The TS context obtained from TSCreate()
4282 
4283    Output Parameters:
4284 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
4285 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
4286 .  f   - The function to compute the matrices
4287 - ctx - User-defined context for Jacobian evaluation routine
4288 
4289    Notes:
4290     You can pass in NULL for any return argument you do not need.
4291 
4292    Level: advanced
4293 
4294 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4295 
4296 .keywords: TS, timestep, get, matrix, Jacobian
4297 @*/
4298 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
4299 {
4300   PetscErrorCode ierr;
4301   DM             dm;
4302 
4303   PetscFunctionBegin;
4304   if (Amat || Pmat) {
4305     SNES snes;
4306     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4307     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4308     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4309   }
4310   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4311   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
4312   PetscFunctionReturn(0);
4313 }
4314 
4315 /*@C
4316    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
4317    VecView() for the solution at each timestep
4318 
4319    Collective on TS
4320 
4321    Input Parameters:
4322 +  ts - the TS context
4323 .  step - current time-step
4324 .  ptime - current time
4325 -  dummy - either a viewer or NULL
4326 
4327    Options Database:
4328 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
4329 
4330    Notes:
4331     the initial solution and current solution are not display with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
4332        will look bad
4333 
4334    Level: intermediate
4335 
4336 .keywords: TS,  vector, monitor, view
4337 
4338 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4339 @*/
4340 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4341 {
4342   PetscErrorCode   ierr;
4343   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
4344   PetscDraw        draw;
4345 
4346   PetscFunctionBegin;
4347   if (!step && ictx->showinitial) {
4348     if (!ictx->initialsolution) {
4349       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
4350     }
4351     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
4352   }
4353   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4354 
4355   if (ictx->showinitial) {
4356     PetscReal pause;
4357     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
4358     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
4359     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
4360     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
4361     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
4362   }
4363   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
4364   if (ictx->showtimestepandtime) {
4365     PetscReal xl,yl,xr,yr,h;
4366     char      time[32];
4367 
4368     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4369     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4370     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4371     h    = yl + .95*(yr - yl);
4372     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4373     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4374   }
4375 
4376   if (ictx->showinitial) {
4377     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
4378   }
4379   PetscFunctionReturn(0);
4380 }
4381 
4382 /*@C
4383    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
4384 
4385    Collective on TS
4386 
4387    Input Parameters:
4388 +  ts - the TS context
4389 .  step - current time-step
4390 .  ptime - current time
4391 -  dummy - either a viewer or NULL
4392 
4393    Level: intermediate
4394 
4395 .keywords: TS,  vector, monitor, view
4396 
4397 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4398 @*/
4399 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4400 {
4401   PetscErrorCode    ierr;
4402   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
4403   PetscDraw         draw;
4404   PetscDrawAxis     axis;
4405   PetscInt          n;
4406   PetscMPIInt       size;
4407   PetscReal         U0,U1,xl,yl,xr,yr,h;
4408   char              time[32];
4409   const PetscScalar *U;
4410 
4411   PetscFunctionBegin;
4412   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)ts),&size);CHKERRQ(ierr);
4413   if (size != 1) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only allowed for sequential runs");
4414   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
4415   if (n != 2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only for ODEs with two unknowns");
4416 
4417   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4418   ierr = PetscViewerDrawGetDrawAxis(ictx->viewer,0,&axis);CHKERRQ(ierr);
4419   ierr = PetscDrawAxisGetLimits(axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
4420   if (!step) {
4421     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
4422     ierr = PetscDrawAxisDraw(axis);CHKERRQ(ierr);
4423   }
4424 
4425   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
4426   U0 = PetscRealPart(U[0]);
4427   U1 = PetscRealPart(U[1]);
4428   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
4429   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(0);
4430 
4431   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
4432   ierr = PetscDrawPoint(draw,U0,U1,PETSC_DRAW_BLACK);CHKERRQ(ierr);
4433   if (ictx->showtimestepandtime) {
4434     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4435     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4436     h    = yl + .95*(yr - yl);
4437     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4438   }
4439   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
4440   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4441   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
4442   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
4443   PetscFunctionReturn(0);
4444 }
4445 
4446 /*@C
4447    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
4448 
4449    Collective on TS
4450 
4451    Input Parameters:
4452 .    ctx - the monitor context
4453 
4454    Level: intermediate
4455 
4456 .keywords: TS,  vector, monitor, view
4457 
4458 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
4459 @*/
4460 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
4461 {
4462   PetscErrorCode ierr;
4463 
4464   PetscFunctionBegin;
4465   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
4466   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
4467   ierr = PetscFree(*ictx);CHKERRQ(ierr);
4468   PetscFunctionReturn(0);
4469 }
4470 
4471 /*@C
4472    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
4473 
4474    Collective on TS
4475 
4476    Input Parameter:
4477 .    ts - time-step context
4478 
4479    Output Patameter:
4480 .    ctx - the monitor context
4481 
4482    Options Database:
4483 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
4484 
4485    Level: intermediate
4486 
4487 .keywords: TS,  vector, monitor, view
4488 
4489 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
4490 @*/
4491 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
4492 {
4493   PetscErrorCode   ierr;
4494 
4495   PetscFunctionBegin;
4496   ierr = PetscNew(ctx);CHKERRQ(ierr);
4497   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
4498   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
4499 
4500   (*ctx)->howoften    = howoften;
4501   (*ctx)->showinitial = PETSC_FALSE;
4502   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
4503 
4504   (*ctx)->showtimestepandtime = PETSC_FALSE;
4505   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
4506   PetscFunctionReturn(0);
4507 }
4508 
4509 /*@C
4510    TSMonitorDrawSolutionFunction - Monitors progress of the TS solvers by calling
4511    VecView() for the solution provided by TSSetSolutionFunction() at each timestep
4512 
4513    Collective on TS
4514 
4515    Input Parameters:
4516 +  ts - the TS context
4517 .  step - current time-step
4518 .  ptime - current time
4519 -  dummy - either a viewer or NULL
4520 
4521    Options Database:
4522 .  -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
4523 
4524    Level: intermediate
4525 
4526 .keywords: TS,  vector, monitor, view
4527 
4528 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4529 @*/
4530 PetscErrorCode  TSMonitorDrawSolutionFunction(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4531 {
4532   PetscErrorCode   ierr;
4533   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
4534   PetscViewer      viewer = ctx->viewer;
4535   Vec              work;
4536 
4537   PetscFunctionBegin;
4538   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4539   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
4540   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
4541   ierr = VecView(work,viewer);CHKERRQ(ierr);
4542   ierr = VecDestroy(&work);CHKERRQ(ierr);
4543   PetscFunctionReturn(0);
4544 }
4545 
4546 /*@C
4547    TSMonitorDrawError - Monitors progress of the TS solvers by calling
4548    VecView() for the error at each timestep
4549 
4550    Collective on TS
4551 
4552    Input Parameters:
4553 +  ts - the TS context
4554 .  step - current time-step
4555 .  ptime - current time
4556 -  dummy - either a viewer or NULL
4557 
4558    Options Database:
4559 .  -ts_monitor_draw_error - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
4560 
4561    Level: intermediate
4562 
4563 .keywords: TS,  vector, monitor, view
4564 
4565 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4566 @*/
4567 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4568 {
4569   PetscErrorCode   ierr;
4570   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
4571   PetscViewer      viewer = ctx->viewer;
4572   Vec              work;
4573 
4574   PetscFunctionBegin;
4575   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4576   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
4577   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
4578   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
4579   ierr = VecView(work,viewer);CHKERRQ(ierr);
4580   ierr = VecDestroy(&work);CHKERRQ(ierr);
4581   PetscFunctionReturn(0);
4582 }
4583 
4584 #include <petsc/private/dmimpl.h>
4585 /*@
4586    TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS
4587 
4588    Logically Collective on TS and DM
4589 
4590    Input Parameters:
4591 +  ts - the ODE integrator object
4592 -  dm - the dm, cannot be NULL
4593 
4594    Notes:
4595    A DM can only be used for solving one problem at a time because information about the problem is stored on the DM,
4596    even when not using interfaces like DMTSSetIFunction().  Use DMClone() to get a distinct DM when solving
4597    different problems using the same function space.
4598 
4599    Level: intermediate
4600 
4601 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
4602 @*/
4603 PetscErrorCode  TSSetDM(TS ts,DM dm)
4604 {
4605   PetscErrorCode ierr;
4606   SNES           snes;
4607   DMTS           tsdm;
4608 
4609   PetscFunctionBegin;
4610   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4611   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
4612   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
4613   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
4614     if (ts->dm->dmts && !dm->dmts) {
4615       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
4616       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
4617       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
4618         tsdm->originaldm = dm;
4619       }
4620     }
4621     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
4622   }
4623   ts->dm = dm;
4624 
4625   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4626   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
4627   PetscFunctionReturn(0);
4628 }
4629 
4630 /*@
4631    TSGetDM - Gets the DM that may be used by some preconditioners
4632 
4633    Not Collective
4634 
4635    Input Parameter:
4636 . ts - the preconditioner context
4637 
4638    Output Parameter:
4639 .  dm - the dm
4640 
4641    Level: intermediate
4642 
4643 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
4644 @*/
4645 PetscErrorCode  TSGetDM(TS ts,DM *dm)
4646 {
4647   PetscErrorCode ierr;
4648 
4649   PetscFunctionBegin;
4650   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4651   if (!ts->dm) {
4652     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
4653     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
4654   }
4655   *dm = ts->dm;
4656   PetscFunctionReturn(0);
4657 }
4658 
4659 /*@
4660    SNESTSFormFunction - Function to evaluate nonlinear residual
4661 
4662    Logically Collective on SNES
4663 
4664    Input Parameter:
4665 + snes - nonlinear solver
4666 . U - the current state at which to evaluate the residual
4667 - ctx - user context, must be a TS
4668 
4669    Output Parameter:
4670 . F - the nonlinear residual
4671 
4672    Notes:
4673    This function is not normally called by users and is automatically registered with the SNES used by TS.
4674    It is most frequently passed to MatFDColoringSetFunction().
4675 
4676    Level: advanced
4677 
4678 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
4679 @*/
4680 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
4681 {
4682   TS             ts = (TS)ctx;
4683   PetscErrorCode ierr;
4684 
4685   PetscFunctionBegin;
4686   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4687   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4688   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
4689   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
4690   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
4691   PetscFunctionReturn(0);
4692 }
4693 
4694 /*@
4695    SNESTSFormJacobian - Function to evaluate the Jacobian
4696 
4697    Collective on SNES
4698 
4699    Input Parameter:
4700 + snes - nonlinear solver
4701 . U - the current state at which to evaluate the residual
4702 - ctx - user context, must be a TS
4703 
4704    Output Parameter:
4705 + A - the Jacobian
4706 . B - the preconditioning matrix (may be the same as A)
4707 - flag - indicates any structure change in the matrix
4708 
4709    Notes:
4710    This function is not normally called by users and is automatically registered with the SNES used by TS.
4711 
4712    Level: developer
4713 
4714 .seealso: SNESSetJacobian()
4715 @*/
4716 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
4717 {
4718   TS             ts = (TS)ctx;
4719   PetscErrorCode ierr;
4720 
4721   PetscFunctionBegin;
4722   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4723   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4724   PetscValidPointer(A,3);
4725   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
4726   PetscValidPointer(B,4);
4727   PetscValidHeaderSpecific(B,MAT_CLASSID,4);
4728   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
4729   ierr = (ts->ops->snesjacobian)(snes,U,A,B,ts);CHKERRQ(ierr);
4730   PetscFunctionReturn(0);
4731 }
4732 
4733 /*@C
4734    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only
4735 
4736    Collective on TS
4737 
4738    Input Arguments:
4739 +  ts - time stepping context
4740 .  t - time at which to evaluate
4741 .  U - state at which to evaluate
4742 -  ctx - context
4743 
4744    Output Arguments:
4745 .  F - right hand side
4746 
4747    Level: intermediate
4748 
4749    Notes:
4750    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
4751    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
4752 
4753 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
4754 @*/
4755 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
4756 {
4757   PetscErrorCode ierr;
4758   Mat            Arhs,Brhs;
4759 
4760   PetscFunctionBegin;
4761   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
4762   ierr = TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);CHKERRQ(ierr);
4763   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
4764   PetscFunctionReturn(0);
4765 }
4766 
4767 /*@C
4768    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
4769 
4770    Collective on TS
4771 
4772    Input Arguments:
4773 +  ts - time stepping context
4774 .  t - time at which to evaluate
4775 .  U - state at which to evaluate
4776 -  ctx - context
4777 
4778    Output Arguments:
4779 +  A - pointer to operator
4780 .  B - pointer to preconditioning matrix
4781 -  flg - matrix structure flag
4782 
4783    Level: intermediate
4784 
4785    Notes:
4786    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
4787 
4788 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
4789 @*/
4790 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
4791 {
4792   PetscFunctionBegin;
4793   PetscFunctionReturn(0);
4794 }
4795 
4796 /*@C
4797    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
4798 
4799    Collective on TS
4800 
4801    Input Arguments:
4802 +  ts - time stepping context
4803 .  t - time at which to evaluate
4804 .  U - state at which to evaluate
4805 .  Udot - time derivative of state vector
4806 -  ctx - context
4807 
4808    Output Arguments:
4809 .  F - left hand side
4810 
4811    Level: intermediate
4812 
4813    Notes:
4814    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
4815    user is required to write their own TSComputeIFunction.
4816    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
4817    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
4818 
4819    Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U
4820 
4821 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant(), TSComputeRHSFunctionLinear()
4822 @*/
4823 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
4824 {
4825   PetscErrorCode ierr;
4826   Mat            A,B;
4827 
4828   PetscFunctionBegin;
4829   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
4830   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE);CHKERRQ(ierr);
4831   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
4832   PetscFunctionReturn(0);
4833 }
4834 
4835 /*@C
4836    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
4837 
4838    Collective on TS
4839 
4840    Input Arguments:
4841 +  ts - time stepping context
4842 .  t - time at which to evaluate
4843 .  U - state at which to evaluate
4844 .  Udot - time derivative of state vector
4845 .  shift - shift to apply
4846 -  ctx - context
4847 
4848    Output Arguments:
4849 +  A - pointer to operator
4850 .  B - pointer to preconditioning matrix
4851 -  flg - matrix structure flag
4852 
4853    Level: advanced
4854 
4855    Notes:
4856    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
4857 
4858    It is only appropriate for problems of the form
4859 
4860 $     M Udot = F(U,t)
4861 
4862   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
4863   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
4864   an implicit operator of the form
4865 
4866 $    shift*M + J
4867 
4868   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
4869   a copy of M or reassemble it when requested.
4870 
4871 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
4872 @*/
4873 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
4874 {
4875   PetscErrorCode ierr;
4876 
4877   PetscFunctionBegin;
4878   ierr = MatScale(A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
4879   ts->ijacobian.shift = shift;
4880   PetscFunctionReturn(0);
4881 }
4882 
4883 /*@
4884    TSGetEquationType - Gets the type of the equation that TS is solving.
4885 
4886    Not Collective
4887 
4888    Input Parameter:
4889 .  ts - the TS context
4890 
4891    Output Parameter:
4892 .  equation_type - see TSEquationType
4893 
4894    Level: beginner
4895 
4896 .keywords: TS, equation type
4897 
4898 .seealso: TSSetEquationType(), TSEquationType
4899 @*/
4900 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
4901 {
4902   PetscFunctionBegin;
4903   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4904   PetscValidPointer(equation_type,2);
4905   *equation_type = ts->equation_type;
4906   PetscFunctionReturn(0);
4907 }
4908 
4909 /*@
4910    TSSetEquationType - Sets the type of the equation that TS is solving.
4911 
4912    Not Collective
4913 
4914    Input Parameter:
4915 +  ts - the TS context
4916 -  equation_type - see TSEquationType
4917 
4918    Level: advanced
4919 
4920 .keywords: TS, equation type
4921 
4922 .seealso: TSGetEquationType(), TSEquationType
4923 @*/
4924 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
4925 {
4926   PetscFunctionBegin;
4927   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4928   ts->equation_type = equation_type;
4929   PetscFunctionReturn(0);
4930 }
4931 
4932 /*@
4933    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
4934 
4935    Not Collective
4936 
4937    Input Parameter:
4938 .  ts - the TS context
4939 
4940    Output Parameter:
4941 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4942             manual pages for the individual convergence tests for complete lists
4943 
4944    Level: beginner
4945 
4946    Notes:
4947    Can only be called after the call to TSSolve() is complete.
4948 
4949 .keywords: TS, nonlinear, set, convergence, test
4950 
4951 .seealso: TSSetConvergenceTest(), TSConvergedReason
4952 @*/
4953 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
4954 {
4955   PetscFunctionBegin;
4956   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4957   PetscValidPointer(reason,2);
4958   *reason = ts->reason;
4959   PetscFunctionReturn(0);
4960 }
4961 
4962 /*@
4963    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
4964 
4965    Not Collective
4966 
4967    Input Parameter:
4968 +  ts - the TS context
4969 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
4970             manual pages for the individual convergence tests for complete lists
4971 
4972    Level: advanced
4973 
4974    Notes:
4975    Can only be called during TSSolve() is active.
4976 
4977 .keywords: TS, nonlinear, set, convergence, test
4978 
4979 .seealso: TSConvergedReason
4980 @*/
4981 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
4982 {
4983   PetscFunctionBegin;
4984   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4985   ts->reason = reason;
4986   PetscFunctionReturn(0);
4987 }
4988 
4989 /*@
4990    TSGetSolveTime - Gets the time after a call to TSSolve()
4991 
4992    Not Collective
4993 
4994    Input Parameter:
4995 .  ts - the TS context
4996 
4997    Output Parameter:
4998 .  ftime - the final time. This time corresponds to the final time set with TSSetMaxTime()
4999 
5000    Level: beginner
5001 
5002    Notes:
5003    Can only be called after the call to TSSolve() is complete.
5004 
5005 .keywords: TS, nonlinear, set, convergence, test
5006 
5007 .seealso: TSSetConvergenceTest(), TSConvergedReason
5008 @*/
5009 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
5010 {
5011   PetscFunctionBegin;
5012   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5013   PetscValidPointer(ftime,2);
5014   *ftime = ts->solvetime;
5015   PetscFunctionReturn(0);
5016 }
5017 
5018 /*@
5019    TSGetSNESIterations - Gets the total number of nonlinear iterations
5020    used by the time integrator.
5021 
5022    Not Collective
5023 
5024    Input Parameter:
5025 .  ts - TS context
5026 
5027    Output Parameter:
5028 .  nits - number of nonlinear iterations
5029 
5030    Notes:
5031    This counter is reset to zero for each successive call to TSSolve().
5032 
5033    Level: intermediate
5034 
5035 .keywords: TS, get, number, nonlinear, iterations
5036 
5037 .seealso:  TSGetKSPIterations()
5038 @*/
5039 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
5040 {
5041   PetscFunctionBegin;
5042   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5043   PetscValidIntPointer(nits,2);
5044   *nits = ts->snes_its;
5045   PetscFunctionReturn(0);
5046 }
5047 
5048 /*@
5049    TSGetKSPIterations - Gets the total number of linear iterations
5050    used by the time integrator.
5051 
5052    Not Collective
5053 
5054    Input Parameter:
5055 .  ts - TS context
5056 
5057    Output Parameter:
5058 .  lits - number of linear iterations
5059 
5060    Notes:
5061    This counter is reset to zero for each successive call to TSSolve().
5062 
5063    Level: intermediate
5064 
5065 .keywords: TS, get, number, linear, iterations
5066 
5067 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
5068 @*/
5069 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
5070 {
5071   PetscFunctionBegin;
5072   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5073   PetscValidIntPointer(lits,2);
5074   *lits = ts->ksp_its;
5075   PetscFunctionReturn(0);
5076 }
5077 
5078 /*@
5079    TSGetStepRejections - Gets the total number of rejected steps.
5080 
5081    Not Collective
5082 
5083    Input Parameter:
5084 .  ts - TS context
5085 
5086    Output Parameter:
5087 .  rejects - number of steps rejected
5088 
5089    Notes:
5090    This counter is reset to zero for each successive call to TSSolve().
5091 
5092    Level: intermediate
5093 
5094 .keywords: TS, get, number
5095 
5096 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
5097 @*/
5098 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
5099 {
5100   PetscFunctionBegin;
5101   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5102   PetscValidIntPointer(rejects,2);
5103   *rejects = ts->reject;
5104   PetscFunctionReturn(0);
5105 }
5106 
5107 /*@
5108    TSGetSNESFailures - Gets the total number of failed SNES solves
5109 
5110    Not Collective
5111 
5112    Input Parameter:
5113 .  ts - TS context
5114 
5115    Output Parameter:
5116 .  fails - number of failed nonlinear solves
5117 
5118    Notes:
5119    This counter is reset to zero for each successive call to TSSolve().
5120 
5121    Level: intermediate
5122 
5123 .keywords: TS, get, number
5124 
5125 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
5126 @*/
5127 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
5128 {
5129   PetscFunctionBegin;
5130   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5131   PetscValidIntPointer(fails,2);
5132   *fails = ts->num_snes_failures;
5133   PetscFunctionReturn(0);
5134 }
5135 
5136 /*@
5137    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
5138 
5139    Not Collective
5140 
5141    Input Parameter:
5142 +  ts - TS context
5143 -  rejects - maximum number of rejected steps, pass -1 for unlimited
5144 
5145    Notes:
5146    The counter is reset to zero for each step
5147 
5148    Options Database Key:
5149  .  -ts_max_reject - Maximum number of step rejections before a step fails
5150 
5151    Level: intermediate
5152 
5153 .keywords: TS, set, maximum, number
5154 
5155 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5156 @*/
5157 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
5158 {
5159   PetscFunctionBegin;
5160   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5161   ts->max_reject = rejects;
5162   PetscFunctionReturn(0);
5163 }
5164 
5165 /*@
5166    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
5167 
5168    Not Collective
5169 
5170    Input Parameter:
5171 +  ts - TS context
5172 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
5173 
5174    Notes:
5175    The counter is reset to zero for each successive call to TSSolve().
5176 
5177    Options Database Key:
5178  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
5179 
5180    Level: intermediate
5181 
5182 .keywords: TS, set, maximum, number
5183 
5184 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
5185 @*/
5186 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
5187 {
5188   PetscFunctionBegin;
5189   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5190   ts->max_snes_failures = fails;
5191   PetscFunctionReturn(0);
5192 }
5193 
5194 /*@
5195    TSSetErrorIfStepFails - Error if no step succeeds
5196 
5197    Not Collective
5198 
5199    Input Parameter:
5200 +  ts - TS context
5201 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
5202 
5203    Options Database Key:
5204  .  -ts_error_if_step_fails - Error if no step succeeds
5205 
5206    Level: intermediate
5207 
5208 .keywords: TS, set, error
5209 
5210 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5211 @*/
5212 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
5213 {
5214   PetscFunctionBegin;
5215   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5216   ts->errorifstepfailed = err;
5217   PetscFunctionReturn(0);
5218 }
5219 
5220 /*@C
5221    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
5222 
5223    Collective on TS
5224 
5225    Input Parameters:
5226 +  ts - the TS context
5227 .  step - current time-step
5228 .  ptime - current time
5229 .  u - current state
5230 -  vf - viewer and its format
5231 
5232    Level: intermediate
5233 
5234 .keywords: TS,  vector, monitor, view
5235 
5236 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5237 @*/
5238 PetscErrorCode  TSMonitorSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
5239 {
5240   PetscErrorCode ierr;
5241 
5242   PetscFunctionBegin;
5243   ierr = PetscViewerPushFormat(vf->viewer,vf->format);CHKERRQ(ierr);
5244   ierr = VecView(u,vf->viewer);CHKERRQ(ierr);
5245   ierr = PetscViewerPopFormat(vf->viewer);CHKERRQ(ierr);
5246   PetscFunctionReturn(0);
5247 }
5248 
5249 /*@C
5250    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
5251 
5252    Collective on TS
5253 
5254    Input Parameters:
5255 +  ts - the TS context
5256 .  step - current time-step
5257 .  ptime - current time
5258 .  u - current state
5259 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5260 
5261    Level: intermediate
5262 
5263    Notes:
5264    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.
5265    These are named according to the file name template.
5266 
5267    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
5268 
5269 .keywords: TS,  vector, monitor, view
5270 
5271 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5272 @*/
5273 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
5274 {
5275   PetscErrorCode ierr;
5276   char           filename[PETSC_MAX_PATH_LEN];
5277   PetscViewer    viewer;
5278 
5279   PetscFunctionBegin;
5280   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
5281   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
5282   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
5283   ierr = VecView(u,viewer);CHKERRQ(ierr);
5284   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5285   PetscFunctionReturn(0);
5286 }
5287 
5288 /*@C
5289    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
5290 
5291    Collective on TS
5292 
5293    Input Parameters:
5294 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5295 
5296    Level: intermediate
5297 
5298    Note:
5299    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
5300 
5301 .keywords: TS,  vector, monitor, view
5302 
5303 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
5304 @*/
5305 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
5306 {
5307   PetscErrorCode ierr;
5308 
5309   PetscFunctionBegin;
5310   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
5311   PetscFunctionReturn(0);
5312 }
5313 
5314 /*@
5315    TSGetAdapt - Get the adaptive controller context for the current method
5316 
5317    Collective on TS if controller has not been created yet
5318 
5319    Input Arguments:
5320 .  ts - time stepping context
5321 
5322    Output Arguments:
5323 .  adapt - adaptive controller
5324 
5325    Level: intermediate
5326 
5327 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
5328 @*/
5329 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
5330 {
5331   PetscErrorCode ierr;
5332 
5333   PetscFunctionBegin;
5334   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5335   PetscValidPointer(adapt,2);
5336   if (!ts->adapt) {
5337     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
5338     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt);CHKERRQ(ierr);
5339     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
5340   }
5341   *adapt = ts->adapt;
5342   PetscFunctionReturn(0);
5343 }
5344 
5345 /*@
5346    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
5347 
5348    Logically Collective
5349 
5350    Input Arguments:
5351 +  ts - time integration context
5352 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
5353 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
5354 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
5355 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
5356 
5357    Options Database keys:
5358 +  -ts_rtol <rtol> - relative tolerance for local truncation error
5359 -  -ts_atol <atol> Absolute tolerance for local truncation error
5360 
5361    Notes:
5362    With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5363    (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5364    computed only for the differential or the algebraic part then this can be done using the vector of
5365    tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5366    differential part and infinity for the algebraic part, the LTE calculation will include only the
5367    differential variables.
5368 
5369    Level: beginner
5370 
5371 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
5372 @*/
5373 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
5374 {
5375   PetscErrorCode ierr;
5376 
5377   PetscFunctionBegin;
5378   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
5379   if (vatol) {
5380     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
5381     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
5382     ts->vatol = vatol;
5383   }
5384   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
5385   if (vrtol) {
5386     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
5387     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
5388     ts->vrtol = vrtol;
5389   }
5390   PetscFunctionReturn(0);
5391 }
5392 
5393 /*@
5394    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
5395 
5396    Logically Collective
5397 
5398    Input Arguments:
5399 .  ts - time integration context
5400 
5401    Output Arguments:
5402 +  atol - scalar absolute tolerances, NULL to ignore
5403 .  vatol - vector of absolute tolerances, NULL to ignore
5404 .  rtol - scalar relative tolerances, NULL to ignore
5405 -  vrtol - vector of relative tolerances, NULL to ignore
5406 
5407    Level: beginner
5408 
5409 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
5410 @*/
5411 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
5412 {
5413   PetscFunctionBegin;
5414   if (atol)  *atol  = ts->atol;
5415   if (vatol) *vatol = ts->vatol;
5416   if (rtol)  *rtol  = ts->rtol;
5417   if (vrtol) *vrtol = ts->vrtol;
5418   PetscFunctionReturn(0);
5419 }
5420 
5421 /*@
5422    TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors
5423 
5424    Collective on TS
5425 
5426    Input Arguments:
5427 +  ts - time stepping context
5428 .  U - state vector, usually ts->vec_sol
5429 -  Y - state vector to be compared to U
5430 
5431    Output Arguments:
5432 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5433 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5434 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5435 
5436    Level: developer
5437 
5438 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNormInfinity()
5439 @*/
5440 PetscErrorCode TSErrorWeightedNorm2(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5441 {
5442   PetscErrorCode    ierr;
5443   PetscInt          i,n,N,rstart;
5444   PetscInt          n_loc,na_loc,nr_loc;
5445   PetscReal         n_glb,na_glb,nr_glb;
5446   const PetscScalar *u,*y;
5447   PetscReal         sum,suma,sumr,gsum,gsuma,gsumr,diff;
5448   PetscReal         tol,tola,tolr;
5449   PetscReal         err_loc[6],err_glb[6];
5450 
5451   PetscFunctionBegin;
5452   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5453   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5454   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
5455   PetscValidType(U,2);
5456   PetscValidType(Y,3);
5457   PetscCheckSameComm(U,2,Y,3);
5458   PetscValidPointer(norm,4);
5459   PetscValidPointer(norma,5);
5460   PetscValidPointer(normr,6);
5461   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
5462 
5463   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
5464   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
5465   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
5466   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5467   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5468   sum  = 0.; n_loc  = 0;
5469   suma = 0.; na_loc = 0;
5470   sumr = 0.; nr_loc = 0;
5471   if (ts->vatol && ts->vrtol) {
5472     const PetscScalar *atol,*rtol;
5473     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5474     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5475     for (i=0; i<n; i++) {
5476       diff = PetscAbsScalar(y[i] - u[i]);
5477       tola = PetscRealPart(atol[i]);
5478       if(tola>0.){
5479         suma  += PetscSqr(diff/tola);
5480         na_loc++;
5481       }
5482       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5483       if(tolr>0.){
5484         sumr  += PetscSqr(diff/tolr);
5485         nr_loc++;
5486       }
5487       tol=tola+tolr;
5488       if(tol>0.){
5489         sum  += PetscSqr(diff/tol);
5490         n_loc++;
5491       }
5492     }
5493     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5494     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5495   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5496     const PetscScalar *atol;
5497     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5498     for (i=0; i<n; i++) {
5499       diff = PetscAbsScalar(y[i] - u[i]);
5500       tola = PetscRealPart(atol[i]);
5501       if(tola>0.){
5502         suma  += PetscSqr(diff/tola);
5503         na_loc++;
5504       }
5505       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5506       if(tolr>0.){
5507         sumr  += PetscSqr(diff/tolr);
5508         nr_loc++;
5509       }
5510       tol=tola+tolr;
5511       if(tol>0.){
5512         sum  += PetscSqr(diff/tol);
5513         n_loc++;
5514       }
5515     }
5516     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5517   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5518     const PetscScalar *rtol;
5519     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5520     for (i=0; i<n; i++) {
5521       diff = PetscAbsScalar(y[i] - u[i]);
5522       tola = ts->atol;
5523       if(tola>0.){
5524         suma  += PetscSqr(diff/tola);
5525         na_loc++;
5526       }
5527       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5528       if(tolr>0.){
5529         sumr  += PetscSqr(diff/tolr);
5530         nr_loc++;
5531       }
5532       tol=tola+tolr;
5533       if(tol>0.){
5534         sum  += PetscSqr(diff/tol);
5535         n_loc++;
5536       }
5537     }
5538     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5539   } else {                      /* scalar atol, scalar rtol */
5540     for (i=0; i<n; i++) {
5541       diff = PetscAbsScalar(y[i] - u[i]);
5542      tola = ts->atol;
5543       if(tola>0.){
5544         suma  += PetscSqr(diff/tola);
5545         na_loc++;
5546       }
5547       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5548       if(tolr>0.){
5549         sumr  += PetscSqr(diff/tolr);
5550         nr_loc++;
5551       }
5552       tol=tola+tolr;
5553       if(tol>0.){
5554         sum  += PetscSqr(diff/tol);
5555         n_loc++;
5556       }
5557     }
5558   }
5559   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5560   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5561 
5562   err_loc[0] = sum;
5563   err_loc[1] = suma;
5564   err_loc[2] = sumr;
5565   err_loc[3] = (PetscReal)n_loc;
5566   err_loc[4] = (PetscReal)na_loc;
5567   err_loc[5] = (PetscReal)nr_loc;
5568 
5569   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5570 
5571   gsum   = err_glb[0];
5572   gsuma  = err_glb[1];
5573   gsumr  = err_glb[2];
5574   n_glb  = err_glb[3];
5575   na_glb = err_glb[4];
5576   nr_glb = err_glb[5];
5577 
5578   *norm  = 0.;
5579   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
5580   *norma = 0.;
5581   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
5582   *normr = 0.;
5583   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
5584 
5585   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5586   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5587   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5588   PetscFunctionReturn(0);
5589 }
5590 
5591 /*@
5592    TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors
5593 
5594    Collective on TS
5595 
5596    Input Arguments:
5597 +  ts - time stepping context
5598 .  U - state vector, usually ts->vec_sol
5599 -  Y - state vector to be compared to U
5600 
5601    Output Arguments:
5602 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5603 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5604 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5605 
5606    Level: developer
5607 
5608 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNorm2()
5609 @*/
5610 PetscErrorCode TSErrorWeightedNormInfinity(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5611 {
5612   PetscErrorCode    ierr;
5613   PetscInt          i,n,N,rstart;
5614   const PetscScalar *u,*y;
5615   PetscReal         max,gmax,maxa,gmaxa,maxr,gmaxr;
5616   PetscReal         tol,tola,tolr,diff;
5617   PetscReal         err_loc[3],err_glb[3];
5618 
5619   PetscFunctionBegin;
5620   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5621   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5622   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
5623   PetscValidType(U,2);
5624   PetscValidType(Y,3);
5625   PetscCheckSameComm(U,2,Y,3);
5626   PetscValidPointer(norm,4);
5627   PetscValidPointer(norma,5);
5628   PetscValidPointer(normr,6);
5629   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
5630 
5631   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
5632   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
5633   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
5634   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5635   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5636 
5637   max=0.;
5638   maxa=0.;
5639   maxr=0.;
5640 
5641   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
5642     const PetscScalar *atol,*rtol;
5643     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5644     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5645 
5646     for (i=0; i<n; i++) {
5647       diff = PetscAbsScalar(y[i] - u[i]);
5648       tola = PetscRealPart(atol[i]);
5649       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5650       tol  = tola+tolr;
5651       if(tola>0.){
5652         maxa = PetscMax(maxa,diff / tola);
5653       }
5654       if(tolr>0.){
5655         maxr = PetscMax(maxr,diff / tolr);
5656       }
5657       if(tol>0.){
5658         max = PetscMax(max,diff / tol);
5659       }
5660     }
5661     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5662     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5663   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5664     const PetscScalar *atol;
5665     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5666     for (i=0; i<n; i++) {
5667       diff = PetscAbsScalar(y[i] - u[i]);
5668       tola = PetscRealPart(atol[i]);
5669       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5670       tol  = tola+tolr;
5671       if(tola>0.){
5672         maxa = PetscMax(maxa,diff / tola);
5673       }
5674       if(tolr>0.){
5675         maxr = PetscMax(maxr,diff / tolr);
5676       }
5677       if(tol>0.){
5678         max = PetscMax(max,diff / tol);
5679       }
5680     }
5681     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5682   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5683     const PetscScalar *rtol;
5684     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5685 
5686     for (i=0; i<n; i++) {
5687       diff = PetscAbsScalar(y[i] - u[i]);
5688       tola = ts->atol;
5689       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5690       tol  = tola+tolr;
5691       if(tola>0.){
5692         maxa = PetscMax(maxa,diff / tola);
5693       }
5694       if(tolr>0.){
5695         maxr = PetscMax(maxr,diff / tolr);
5696       }
5697       if(tol>0.){
5698         max = PetscMax(max,diff / tol);
5699       }
5700     }
5701     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5702   } else {                      /* scalar atol, scalar rtol */
5703 
5704     for (i=0; i<n; i++) {
5705       diff = PetscAbsScalar(y[i] - u[i]);
5706       tola = ts->atol;
5707       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5708       tol  = tola+tolr;
5709       if(tola>0.){
5710         maxa = PetscMax(maxa,diff / tola);
5711       }
5712       if(tolr>0.){
5713         maxr = PetscMax(maxr,diff / tolr);
5714       }
5715       if(tol>0.){
5716         max = PetscMax(max,diff / tol);
5717       }
5718     }
5719   }
5720   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5721   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5722   err_loc[0] = max;
5723   err_loc[1] = maxa;
5724   err_loc[2] = maxr;
5725   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5726   gmax   = err_glb[0];
5727   gmaxa  = err_glb[1];
5728   gmaxr  = err_glb[2];
5729 
5730   *norm = gmax;
5731   *norma = gmaxa;
5732   *normr = gmaxr;
5733   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5734     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5735     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5736   PetscFunctionReturn(0);
5737 }
5738 
5739 /*@
5740    TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
5741 
5742    Collective on TS
5743 
5744    Input Arguments:
5745 +  ts - time stepping context
5746 .  U - state vector, usually ts->vec_sol
5747 .  Y - state vector to be compared to U
5748 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
5749 
5750    Output Arguments:
5751 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
5752 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
5753 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
5754 
5755    Options Database Keys:
5756 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
5757 
5758    Level: developer
5759 
5760 .seealso: TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2(), TSErrorWeightedENorm
5761 @*/
5762 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5763 {
5764   PetscErrorCode ierr;
5765 
5766   PetscFunctionBegin;
5767   if (wnormtype == NORM_2) {
5768     ierr = TSErrorWeightedNorm2(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
5769   } else if(wnormtype == NORM_INFINITY) {
5770     ierr = TSErrorWeightedNormInfinity(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
5771   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
5772   PetscFunctionReturn(0);
5773 }
5774 
5775 
5776 /*@
5777    TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances
5778 
5779    Collective on TS
5780 
5781    Input Arguments:
5782 +  ts - time stepping context
5783 .  E - error vector
5784 .  U - state vector, usually ts->vec_sol
5785 -  Y - state vector, previous time step
5786 
5787    Output Arguments:
5788 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5789 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5790 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5791 
5792    Level: developer
5793 
5794 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENormInfinity()
5795 @*/
5796 PetscErrorCode TSErrorWeightedENorm2(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5797 {
5798   PetscErrorCode    ierr;
5799   PetscInt          i,n,N,rstart;
5800   PetscInt          n_loc,na_loc,nr_loc;
5801   PetscReal         n_glb,na_glb,nr_glb;
5802   const PetscScalar *e,*u,*y;
5803   PetscReal         err,sum,suma,sumr,gsum,gsuma,gsumr;
5804   PetscReal         tol,tola,tolr;
5805   PetscReal         err_loc[6],err_glb[6];
5806 
5807   PetscFunctionBegin;
5808   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5809   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
5810   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
5811   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
5812   PetscValidType(E,2);
5813   PetscValidType(U,3);
5814   PetscValidType(Y,4);
5815   PetscCheckSameComm(E,2,U,3);
5816   PetscCheckSameComm(U,2,Y,3);
5817   PetscValidPointer(norm,5);
5818   PetscValidPointer(norma,6);
5819   PetscValidPointer(normr,7);
5820 
5821   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
5822   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
5823   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
5824   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
5825   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5826   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5827   sum  = 0.; n_loc  = 0;
5828   suma = 0.; na_loc = 0;
5829   sumr = 0.; nr_loc = 0;
5830   if (ts->vatol && ts->vrtol) {
5831     const PetscScalar *atol,*rtol;
5832     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5833     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5834     for (i=0; i<n; i++) {
5835       err = PetscAbsScalar(e[i]);
5836       tola = PetscRealPart(atol[i]);
5837       if(tola>0.){
5838         suma  += PetscSqr(err/tola);
5839         na_loc++;
5840       }
5841       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5842       if(tolr>0.){
5843         sumr  += PetscSqr(err/tolr);
5844         nr_loc++;
5845       }
5846       tol=tola+tolr;
5847       if(tol>0.){
5848         sum  += PetscSqr(err/tol);
5849         n_loc++;
5850       }
5851     }
5852     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5853     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5854   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5855     const PetscScalar *atol;
5856     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5857     for (i=0; i<n; i++) {
5858       err = PetscAbsScalar(e[i]);
5859       tola = PetscRealPart(atol[i]);
5860       if(tola>0.){
5861         suma  += PetscSqr(err/tola);
5862         na_loc++;
5863       }
5864       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5865       if(tolr>0.){
5866         sumr  += PetscSqr(err/tolr);
5867         nr_loc++;
5868       }
5869       tol=tola+tolr;
5870       if(tol>0.){
5871         sum  += PetscSqr(err/tol);
5872         n_loc++;
5873       }
5874     }
5875     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5876   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5877     const PetscScalar *rtol;
5878     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5879     for (i=0; i<n; i++) {
5880       err = PetscAbsScalar(e[i]);
5881       tola = ts->atol;
5882       if(tola>0.){
5883         suma  += PetscSqr(err/tola);
5884         na_loc++;
5885       }
5886       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5887       if(tolr>0.){
5888         sumr  += PetscSqr(err/tolr);
5889         nr_loc++;
5890       }
5891       tol=tola+tolr;
5892       if(tol>0.){
5893         sum  += PetscSqr(err/tol);
5894         n_loc++;
5895       }
5896     }
5897     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5898   } else {                      /* scalar atol, scalar rtol */
5899     for (i=0; i<n; i++) {
5900       err = PetscAbsScalar(e[i]);
5901      tola = ts->atol;
5902       if(tola>0.){
5903         suma  += PetscSqr(err/tola);
5904         na_loc++;
5905       }
5906       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5907       if(tolr>0.){
5908         sumr  += PetscSqr(err/tolr);
5909         nr_loc++;
5910       }
5911       tol=tola+tolr;
5912       if(tol>0.){
5913         sum  += PetscSqr(err/tol);
5914         n_loc++;
5915       }
5916     }
5917   }
5918   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
5919   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5920   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5921 
5922   err_loc[0] = sum;
5923   err_loc[1] = suma;
5924   err_loc[2] = sumr;
5925   err_loc[3] = (PetscReal)n_loc;
5926   err_loc[4] = (PetscReal)na_loc;
5927   err_loc[5] = (PetscReal)nr_loc;
5928 
5929   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5930 
5931   gsum   = err_glb[0];
5932   gsuma  = err_glb[1];
5933   gsumr  = err_glb[2];
5934   n_glb  = err_glb[3];
5935   na_glb = err_glb[4];
5936   nr_glb = err_glb[5];
5937 
5938   *norm  = 0.;
5939   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
5940   *norma = 0.;
5941   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
5942   *normr = 0.;
5943   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
5944 
5945   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5946   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5947   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5948   PetscFunctionReturn(0);
5949 }
5950 
5951 /*@
5952    TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances
5953    Collective on TS
5954 
5955    Input Arguments:
5956 +  ts - time stepping context
5957 .  E - error vector
5958 .  U - state vector, usually ts->vec_sol
5959 -  Y - state vector, previous time step
5960 
5961    Output Arguments:
5962 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5963 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5964 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5965 
5966    Level: developer
5967 
5968 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENorm2()
5969 @*/
5970 PetscErrorCode TSErrorWeightedENormInfinity(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5971 {
5972   PetscErrorCode    ierr;
5973   PetscInt          i,n,N,rstart;
5974   const PetscScalar *e,*u,*y;
5975   PetscReal         err,max,gmax,maxa,gmaxa,maxr,gmaxr;
5976   PetscReal         tol,tola,tolr;
5977   PetscReal         err_loc[3],err_glb[3];
5978 
5979   PetscFunctionBegin;
5980   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5981   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
5982   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
5983   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
5984   PetscValidType(E,2);
5985   PetscValidType(U,3);
5986   PetscValidType(Y,4);
5987   PetscCheckSameComm(E,2,U,3);
5988   PetscCheckSameComm(U,2,Y,3);
5989   PetscValidPointer(norm,5);
5990   PetscValidPointer(norma,6);
5991   PetscValidPointer(normr,7);
5992 
5993   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
5994   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
5995   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
5996   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
5997   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5998   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5999 
6000   max=0.;
6001   maxa=0.;
6002   maxr=0.;
6003 
6004   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
6005     const PetscScalar *atol,*rtol;
6006     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6007     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6008 
6009     for (i=0; i<n; i++) {
6010       err = PetscAbsScalar(e[i]);
6011       tola = PetscRealPart(atol[i]);
6012       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6013       tol  = tola+tolr;
6014       if(tola>0.){
6015         maxa = PetscMax(maxa,err / tola);
6016       }
6017       if(tolr>0.){
6018         maxr = PetscMax(maxr,err / tolr);
6019       }
6020       if(tol>0.){
6021         max = PetscMax(max,err / tol);
6022       }
6023     }
6024     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6025     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6026   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6027     const PetscScalar *atol;
6028     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6029     for (i=0; i<n; i++) {
6030       err = PetscAbsScalar(e[i]);
6031       tola = PetscRealPart(atol[i]);
6032       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6033       tol  = tola+tolr;
6034       if(tola>0.){
6035         maxa = PetscMax(maxa,err / tola);
6036       }
6037       if(tolr>0.){
6038         maxr = PetscMax(maxr,err / tolr);
6039       }
6040       if(tol>0.){
6041         max = PetscMax(max,err / tol);
6042       }
6043     }
6044     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6045   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6046     const PetscScalar *rtol;
6047     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6048 
6049     for (i=0; i<n; i++) {
6050       err = PetscAbsScalar(e[i]);
6051       tola = ts->atol;
6052       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6053       tol  = tola+tolr;
6054       if(tola>0.){
6055         maxa = PetscMax(maxa,err / tola);
6056       }
6057       if(tolr>0.){
6058         maxr = PetscMax(maxr,err / tolr);
6059       }
6060       if(tol>0.){
6061         max = PetscMax(max,err / tol);
6062       }
6063     }
6064     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6065   } else {                      /* scalar atol, scalar rtol */
6066 
6067     for (i=0; i<n; i++) {
6068       err = PetscAbsScalar(e[i]);
6069       tola = ts->atol;
6070       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6071       tol  = tola+tolr;
6072       if(tola>0.){
6073         maxa = PetscMax(maxa,err / tola);
6074       }
6075       if(tolr>0.){
6076         maxr = PetscMax(maxr,err / tolr);
6077       }
6078       if(tol>0.){
6079         max = PetscMax(max,err / tol);
6080       }
6081     }
6082   }
6083   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6084   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6085   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6086   err_loc[0] = max;
6087   err_loc[1] = maxa;
6088   err_loc[2] = maxr;
6089   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6090   gmax   = err_glb[0];
6091   gmaxa  = err_glb[1];
6092   gmaxr  = err_glb[2];
6093 
6094   *norm = gmax;
6095   *norma = gmaxa;
6096   *normr = gmaxr;
6097   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6098     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6099     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6100   PetscFunctionReturn(0);
6101 }
6102 
6103 /*@
6104    TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
6105 
6106    Collective on TS
6107 
6108    Input Arguments:
6109 +  ts - time stepping context
6110 .  E - error vector
6111 .  U - state vector, usually ts->vec_sol
6112 .  Y - state vector, previous time step
6113 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6114 
6115    Output Arguments:
6116 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6117 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6118 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6119 
6120    Options Database Keys:
6121 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6122 
6123    Level: developer
6124 
6125 .seealso: TSErrorWeightedENormInfinity(), TSErrorWeightedENorm2(), TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2()
6126 @*/
6127 PetscErrorCode TSErrorWeightedENorm(TS ts,Vec E,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6128 {
6129   PetscErrorCode ierr;
6130 
6131   PetscFunctionBegin;
6132   if (wnormtype == NORM_2) {
6133     ierr = TSErrorWeightedENorm2(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6134   } else if(wnormtype == NORM_INFINITY) {
6135     ierr = TSErrorWeightedENormInfinity(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6136   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6137   PetscFunctionReturn(0);
6138 }
6139 
6140 
6141 /*@
6142    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
6143 
6144    Logically Collective on TS
6145 
6146    Input Arguments:
6147 +  ts - time stepping context
6148 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
6149 
6150    Note:
6151    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
6152 
6153    Level: intermediate
6154 
6155 .seealso: TSGetCFLTime(), TSADAPTCFL
6156 @*/
6157 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
6158 {
6159   PetscFunctionBegin;
6160   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6161   ts->cfltime_local = cfltime;
6162   ts->cfltime       = -1.;
6163   PetscFunctionReturn(0);
6164 }
6165 
6166 /*@
6167    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
6168 
6169    Collective on TS
6170 
6171    Input Arguments:
6172 .  ts - time stepping context
6173 
6174    Output Arguments:
6175 .  cfltime - maximum stable time step for forward Euler
6176 
6177    Level: advanced
6178 
6179 .seealso: TSSetCFLTimeLocal()
6180 @*/
6181 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
6182 {
6183   PetscErrorCode ierr;
6184 
6185   PetscFunctionBegin;
6186   if (ts->cfltime < 0) {
6187     ierr = MPIU_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6188   }
6189   *cfltime = ts->cfltime;
6190   PetscFunctionReturn(0);
6191 }
6192 
6193 /*@
6194    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
6195 
6196    Input Parameters:
6197 .  ts   - the TS context.
6198 .  xl   - lower bound.
6199 .  xu   - upper bound.
6200 
6201    Notes:
6202    If this routine is not called then the lower and upper bounds are set to
6203    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
6204 
6205    Level: advanced
6206 
6207 @*/
6208 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
6209 {
6210   PetscErrorCode ierr;
6211   SNES           snes;
6212 
6213   PetscFunctionBegin;
6214   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
6215   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
6216   PetscFunctionReturn(0);
6217 }
6218 
6219 #if defined(PETSC_HAVE_MATLAB_ENGINE)
6220 #include <mex.h>
6221 
6222 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
6223 
6224 /*
6225    TSComputeFunction_Matlab - Calls the function that has been set with
6226                          TSSetFunctionMatlab().
6227 
6228    Collective on TS
6229 
6230    Input Parameters:
6231 +  snes - the TS context
6232 -  u - input vector
6233 
6234    Output Parameter:
6235 .  y - function vector, as set by TSSetFunction()
6236 
6237    Notes:
6238    TSComputeFunction() is typically used within nonlinear solvers
6239    implementations, so most users would not generally call this routine
6240    themselves.
6241 
6242    Level: developer
6243 
6244 .keywords: TS, nonlinear, compute, function
6245 
6246 .seealso: TSSetFunction(), TSGetFunction()
6247 */
6248 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
6249 {
6250   PetscErrorCode  ierr;
6251   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6252   int             nlhs  = 1,nrhs = 7;
6253   mxArray         *plhs[1],*prhs[7];
6254   long long int   lx = 0,lxdot = 0,ly = 0,ls = 0;
6255 
6256   PetscFunctionBegin;
6257   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
6258   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
6259   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
6260   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
6261   PetscCheckSameComm(snes,1,u,3);
6262   PetscCheckSameComm(snes,1,y,5);
6263 
6264   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
6265   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6266   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
6267   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
6268 
6269   prhs[0] =  mxCreateDoubleScalar((double)ls);
6270   prhs[1] =  mxCreateDoubleScalar(time);
6271   prhs[2] =  mxCreateDoubleScalar((double)lx);
6272   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
6273   prhs[4] =  mxCreateDoubleScalar((double)ly);
6274   prhs[5] =  mxCreateString(sctx->funcname);
6275   prhs[6] =  sctx->ctx;
6276   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
6277   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6278   mxDestroyArray(prhs[0]);
6279   mxDestroyArray(prhs[1]);
6280   mxDestroyArray(prhs[2]);
6281   mxDestroyArray(prhs[3]);
6282   mxDestroyArray(prhs[4]);
6283   mxDestroyArray(prhs[5]);
6284   mxDestroyArray(plhs[0]);
6285   PetscFunctionReturn(0);
6286 }
6287 
6288 /*
6289    TSSetFunctionMatlab - Sets the function evaluation routine and function
6290    vector for use by the TS routines in solving ODEs
6291    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
6292 
6293    Logically Collective on TS
6294 
6295    Input Parameters:
6296 +  ts - the TS context
6297 -  func - function evaluation routine
6298 
6299    Calling sequence of func:
6300 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
6301 
6302    Level: beginner
6303 
6304 .keywords: TS, nonlinear, set, function
6305 
6306 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6307 */
6308 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
6309 {
6310   PetscErrorCode  ierr;
6311   TSMatlabContext *sctx;
6312 
6313   PetscFunctionBegin;
6314   /* currently sctx is memory bleed */
6315   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6316   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6317   /*
6318      This should work, but it doesn't
6319   sctx->ctx = ctx;
6320   mexMakeArrayPersistent(sctx->ctx);
6321   */
6322   sctx->ctx = mxDuplicateArray(ctx);
6323 
6324   ierr = TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
6325   PetscFunctionReturn(0);
6326 }
6327 
6328 /*
6329    TSComputeJacobian_Matlab - Calls the function that has been set with
6330                          TSSetJacobianMatlab().
6331 
6332    Collective on TS
6333 
6334    Input Parameters:
6335 +  ts - the TS context
6336 .  u - input vector
6337 .  A, B - the matrices
6338 -  ctx - user context
6339 
6340    Level: developer
6341 
6342 .keywords: TS, nonlinear, compute, function
6343 
6344 .seealso: TSSetFunction(), TSGetFunction()
6345 @*/
6346 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat A,Mat B,void *ctx)
6347 {
6348   PetscErrorCode  ierr;
6349   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6350   int             nlhs  = 2,nrhs = 9;
6351   mxArray         *plhs[2],*prhs[9];
6352   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
6353 
6354   PetscFunctionBegin;
6355   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6356   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
6357 
6358   /* call Matlab function in ctx with arguments u and y */
6359 
6360   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
6361   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6362   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
6363   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
6364   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
6365 
6366   prhs[0] =  mxCreateDoubleScalar((double)ls);
6367   prhs[1] =  mxCreateDoubleScalar((double)time);
6368   prhs[2] =  mxCreateDoubleScalar((double)lx);
6369   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
6370   prhs[4] =  mxCreateDoubleScalar((double)shift);
6371   prhs[5] =  mxCreateDoubleScalar((double)lA);
6372   prhs[6] =  mxCreateDoubleScalar((double)lB);
6373   prhs[7] =  mxCreateString(sctx->funcname);
6374   prhs[8] =  sctx->ctx;
6375   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
6376   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6377   mxDestroyArray(prhs[0]);
6378   mxDestroyArray(prhs[1]);
6379   mxDestroyArray(prhs[2]);
6380   mxDestroyArray(prhs[3]);
6381   mxDestroyArray(prhs[4]);
6382   mxDestroyArray(prhs[5]);
6383   mxDestroyArray(prhs[6]);
6384   mxDestroyArray(prhs[7]);
6385   mxDestroyArray(plhs[0]);
6386   mxDestroyArray(plhs[1]);
6387   PetscFunctionReturn(0);
6388 }
6389 
6390 /*
6391    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
6392    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
6393 
6394    Logically Collective on TS
6395 
6396    Input Parameters:
6397 +  ts - the TS context
6398 .  A,B - Jacobian matrices
6399 .  func - function evaluation routine
6400 -  ctx - user context
6401 
6402    Calling sequence of func:
6403 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
6404 
6405    Level: developer
6406 
6407 .keywords: TS, nonlinear, set, function
6408 
6409 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6410 */
6411 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
6412 {
6413   PetscErrorCode  ierr;
6414   TSMatlabContext *sctx;
6415 
6416   PetscFunctionBegin;
6417   /* currently sctx is memory bleed */
6418   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6419   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6420   /*
6421      This should work, but it doesn't
6422   sctx->ctx = ctx;
6423   mexMakeArrayPersistent(sctx->ctx);
6424   */
6425   sctx->ctx = mxDuplicateArray(ctx);
6426 
6427   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
6428   PetscFunctionReturn(0);
6429 }
6430 
6431 /*
6432    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
6433 
6434    Collective on TS
6435 
6436 .seealso: TSSetFunction(), TSGetFunction()
6437 @*/
6438 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
6439 {
6440   PetscErrorCode  ierr;
6441   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6442   int             nlhs  = 1,nrhs = 6;
6443   mxArray         *plhs[1],*prhs[6];
6444   long long int   lx = 0,ls = 0;
6445 
6446   PetscFunctionBegin;
6447   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6448   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
6449 
6450   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
6451   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6452 
6453   prhs[0] =  mxCreateDoubleScalar((double)ls);
6454   prhs[1] =  mxCreateDoubleScalar((double)it);
6455   prhs[2] =  mxCreateDoubleScalar((double)time);
6456   prhs[3] =  mxCreateDoubleScalar((double)lx);
6457   prhs[4] =  mxCreateString(sctx->funcname);
6458   prhs[5] =  sctx->ctx;
6459   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
6460   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6461   mxDestroyArray(prhs[0]);
6462   mxDestroyArray(prhs[1]);
6463   mxDestroyArray(prhs[2]);
6464   mxDestroyArray(prhs[3]);
6465   mxDestroyArray(prhs[4]);
6466   mxDestroyArray(plhs[0]);
6467   PetscFunctionReturn(0);
6468 }
6469 
6470 /*
6471    TSMonitorSetMatlab - Sets the monitor function from Matlab
6472 
6473    Level: developer
6474 
6475 .keywords: TS, nonlinear, set, function
6476 
6477 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
6478 */
6479 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
6480 {
6481   PetscErrorCode  ierr;
6482   TSMatlabContext *sctx;
6483 
6484   PetscFunctionBegin;
6485   /* currently sctx is memory bleed */
6486   ierr = PetscNew(&sctx);CHKERRQ(ierr);
6487   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
6488   /*
6489      This should work, but it doesn't
6490   sctx->ctx = ctx;
6491   mexMakeArrayPersistent(sctx->ctx);
6492   */
6493   sctx->ctx = mxDuplicateArray(ctx);
6494 
6495   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);CHKERRQ(ierr);
6496   PetscFunctionReturn(0);
6497 }
6498 #endif
6499 
6500 /*@C
6501    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
6502        in a time based line graph
6503 
6504    Collective on TS
6505 
6506    Input Parameters:
6507 +  ts - the TS context
6508 .  step - current time-step
6509 .  ptime - current time
6510 .  u - current solution
6511 -  dctx - the TSMonitorLGCtx object that contains all the options for the monitoring, this is created with TSMonitorLGCtxCreate()
6512 
6513    Options Database:
6514 .   -ts_monitor_lg_solution_variables
6515 
6516    Level: intermediate
6517 
6518    Notes:
6519     Each process in a parallel run displays its component solutions in a separate window
6520 
6521 .keywords: TS,  vector, monitor, view
6522 
6523 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
6524            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
6525            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
6526            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
6527 @*/
6528 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
6529 {
6530   PetscErrorCode    ierr;
6531   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dctx;
6532   const PetscScalar *yy;
6533   Vec               v;
6534 
6535   PetscFunctionBegin;
6536   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
6537   if (!step) {
6538     PetscDrawAxis axis;
6539     PetscInt      dim;
6540     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
6541     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
6542     if (!ctx->names) {
6543       PetscBool flg;
6544       /* user provides names of variables to plot but no names has been set so assume names are integer values */
6545       ierr = PetscOptionsHasName(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",&flg);CHKERRQ(ierr);
6546       if (flg) {
6547         PetscInt i,n;
6548         char     **names;
6549         ierr = VecGetSize(u,&n);CHKERRQ(ierr);
6550         ierr = PetscMalloc1(n+1,&names);CHKERRQ(ierr);
6551         for (i=0; i<n; i++) {
6552           ierr = PetscMalloc1(5,&names[i]);CHKERRQ(ierr);
6553           ierr = PetscSNPrintf(names[i],5,"%D",i);CHKERRQ(ierr);
6554         }
6555         names[n] = NULL;
6556         ctx->names = names;
6557       }
6558     }
6559     if (ctx->names && !ctx->displaynames) {
6560       char      **displaynames;
6561       PetscBool flg;
6562       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6563       ierr = PetscMalloc1(dim+1,&displaynames);CHKERRQ(ierr);
6564       ierr = PetscMemzero(displaynames,(dim+1)*sizeof(char*));CHKERRQ(ierr);
6565       ierr = PetscOptionsGetStringArray(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",displaynames,&dim,&flg);CHKERRQ(ierr);
6566       if (flg) {
6567         ierr = TSMonitorLGCtxSetDisplayVariables(ctx,(const char *const *)displaynames);CHKERRQ(ierr);
6568       }
6569       ierr = PetscStrArrayDestroy(&displaynames);CHKERRQ(ierr);
6570     }
6571     if (ctx->displaynames) {
6572       ierr = PetscDrawLGSetDimension(ctx->lg,ctx->ndisplayvariables);CHKERRQ(ierr);
6573       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->displaynames);CHKERRQ(ierr);
6574     } else if (ctx->names) {
6575       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6576       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
6577       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->names);CHKERRQ(ierr);
6578     } else {
6579       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6580       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
6581     }
6582     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
6583   }
6584 
6585   if (!ctx->transform) v = u;
6586   else {ierr = (*ctx->transform)(ctx->transformctx,u,&v);CHKERRQ(ierr);}
6587   ierr = VecGetArrayRead(v,&yy);CHKERRQ(ierr);
6588   if (ctx->displaynames) {
6589     PetscInt i;
6590     for (i=0; i<ctx->ndisplayvariables; i++)
6591       ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
6592     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,ctx->displayvalues);CHKERRQ(ierr);
6593   } else {
6594 #if defined(PETSC_USE_COMPLEX)
6595     PetscInt  i,n;
6596     PetscReal *yreal;
6597     ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
6598     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
6599     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
6600     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
6601     ierr = PetscFree(yreal);CHKERRQ(ierr);
6602 #else
6603     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
6604 #endif
6605   }
6606   ierr = VecRestoreArrayRead(v,&yy);CHKERRQ(ierr);
6607   if (ctx->transform) {ierr = VecDestroy(&v);CHKERRQ(ierr);}
6608 
6609   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
6610     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
6611     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
6612   }
6613   PetscFunctionReturn(0);
6614 }
6615 
6616 /*@C
6617    TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
6618 
6619    Collective on TS
6620 
6621    Input Parameters:
6622 +  ts - the TS context
6623 -  names - the names of the components, final string must be NULL
6624 
6625    Level: intermediate
6626 
6627    Notes:
6628     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6629 
6630 .keywords: TS,  vector, monitor, view
6631 
6632 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetVariableNames()
6633 @*/
6634 PetscErrorCode  TSMonitorLGSetVariableNames(TS ts,const char * const *names)
6635 {
6636   PetscErrorCode    ierr;
6637   PetscInt          i;
6638 
6639   PetscFunctionBegin;
6640   for (i=0; i<ts->numbermonitors; i++) {
6641     if (ts->monitor[i] == TSMonitorLGSolution) {
6642       ierr = TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i],names);CHKERRQ(ierr);
6643       break;
6644     }
6645   }
6646   PetscFunctionReturn(0);
6647 }
6648 
6649 /*@C
6650    TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
6651 
6652    Collective on TS
6653 
6654    Input Parameters:
6655 +  ts - the TS context
6656 -  names - the names of the components, final string must be NULL
6657 
6658    Level: intermediate
6659 
6660 .keywords: TS,  vector, monitor, view
6661 
6662 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGSetVariableNames()
6663 @*/
6664 PetscErrorCode  TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx,const char * const *names)
6665 {
6666   PetscErrorCode    ierr;
6667 
6668   PetscFunctionBegin;
6669   ierr = PetscStrArrayDestroy(&ctx->names);CHKERRQ(ierr);
6670   ierr = PetscStrArrayallocpy(names,&ctx->names);CHKERRQ(ierr);
6671   PetscFunctionReturn(0);
6672 }
6673 
6674 /*@C
6675    TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
6676 
6677    Collective on TS
6678 
6679    Input Parameter:
6680 .  ts - the TS context
6681 
6682    Output Parameter:
6683 .  names - the names of the components, final string must be NULL
6684 
6685    Level: intermediate
6686 
6687    Notes:
6688     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6689 
6690 .keywords: TS,  vector, monitor, view
6691 
6692 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
6693 @*/
6694 PetscErrorCode  TSMonitorLGGetVariableNames(TS ts,const char *const **names)
6695 {
6696   PetscInt       i;
6697 
6698   PetscFunctionBegin;
6699   *names = NULL;
6700   for (i=0; i<ts->numbermonitors; i++) {
6701     if (ts->monitor[i] == TSMonitorLGSolution) {
6702       TSMonitorLGCtx  ctx = (TSMonitorLGCtx) ts->monitorcontext[i];
6703       *names = (const char *const *)ctx->names;
6704       break;
6705     }
6706   }
6707   PetscFunctionReturn(0);
6708 }
6709 
6710 /*@C
6711    TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
6712 
6713    Collective on TS
6714 
6715    Input Parameters:
6716 +  ctx - the TSMonitorLG context
6717 .  displaynames - the names of the components, final string must be NULL
6718 
6719    Level: intermediate
6720 
6721 .keywords: TS,  vector, monitor, view
6722 
6723 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
6724 @*/
6725 PetscErrorCode  TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx,const char * const *displaynames)
6726 {
6727   PetscInt          j = 0,k;
6728   PetscErrorCode    ierr;
6729 
6730   PetscFunctionBegin;
6731   if (!ctx->names) PetscFunctionReturn(0);
6732   ierr = PetscStrArrayDestroy(&ctx->displaynames);CHKERRQ(ierr);
6733   ierr = PetscStrArrayallocpy(displaynames,&ctx->displaynames);CHKERRQ(ierr);
6734   while (displaynames[j]) j++;
6735   ctx->ndisplayvariables = j;
6736   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvariables);CHKERRQ(ierr);
6737   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvalues);CHKERRQ(ierr);
6738   j = 0;
6739   while (displaynames[j]) {
6740     k = 0;
6741     while (ctx->names[k]) {
6742       PetscBool flg;
6743       ierr = PetscStrcmp(displaynames[j],ctx->names[k],&flg);CHKERRQ(ierr);
6744       if (flg) {
6745         ctx->displayvariables[j] = k;
6746         break;
6747       }
6748       k++;
6749     }
6750     j++;
6751   }
6752   PetscFunctionReturn(0);
6753 }
6754 
6755 /*@C
6756    TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
6757 
6758    Collective on TS
6759 
6760    Input Parameters:
6761 +  ts - the TS context
6762 .  displaynames - the names of the components, final string must be NULL
6763 
6764    Notes:
6765     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6766 
6767    Level: intermediate
6768 
6769 .keywords: TS,  vector, monitor, view
6770 
6771 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
6772 @*/
6773 PetscErrorCode  TSMonitorLGSetDisplayVariables(TS ts,const char * const *displaynames)
6774 {
6775   PetscInt          i;
6776   PetscErrorCode    ierr;
6777 
6778   PetscFunctionBegin;
6779   for (i=0; i<ts->numbermonitors; i++) {
6780     if (ts->monitor[i] == TSMonitorLGSolution) {
6781       ierr = TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i],displaynames);CHKERRQ(ierr);
6782       break;
6783     }
6784   }
6785   PetscFunctionReturn(0);
6786 }
6787 
6788 /*@C
6789    TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
6790 
6791    Collective on TS
6792 
6793    Input Parameters:
6794 +  ts - the TS context
6795 .  transform - the transform function
6796 .  destroy - function to destroy the optional context
6797 -  ctx - optional context used by transform function
6798 
6799    Notes:
6800     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6801 
6802    Level: intermediate
6803 
6804 .keywords: TS,  vector, monitor, view
6805 
6806 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGCtxSetTransform()
6807 @*/
6808 PetscErrorCode  TSMonitorLGSetTransform(TS ts,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
6809 {
6810   PetscInt          i;
6811   PetscErrorCode    ierr;
6812 
6813   PetscFunctionBegin;
6814   for (i=0; i<ts->numbermonitors; i++) {
6815     if (ts->monitor[i] == TSMonitorLGSolution) {
6816       ierr = TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i],transform,destroy,tctx);CHKERRQ(ierr);
6817     }
6818   }
6819   PetscFunctionReturn(0);
6820 }
6821 
6822 /*@C
6823    TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
6824 
6825    Collective on TSLGCtx
6826 
6827    Input Parameters:
6828 +  ts - the TS context
6829 .  transform - the transform function
6830 .  destroy - function to destroy the optional context
6831 -  ctx - optional context used by transform function
6832 
6833    Level: intermediate
6834 
6835 .keywords: TS,  vector, monitor, view
6836 
6837 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGSetTransform()
6838 @*/
6839 PetscErrorCode  TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
6840 {
6841   PetscFunctionBegin;
6842   ctx->transform    = transform;
6843   ctx->transformdestroy = destroy;
6844   ctx->transformctx = tctx;
6845   PetscFunctionReturn(0);
6846 }
6847 
6848 /*@C
6849    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the error
6850        in a time based line graph
6851 
6852    Collective on TS
6853 
6854    Input Parameters:
6855 +  ts - the TS context
6856 .  step - current time-step
6857 .  ptime - current time
6858 .  u - current solution
6859 -  dctx - TSMonitorLGCtx object created with TSMonitorLGCtxCreate()
6860 
6861    Level: intermediate
6862 
6863    Notes:
6864     Each process in a parallel run displays its component errors in a separate window
6865 
6866    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
6867 
6868    Options Database Keys:
6869 .  -ts_monitor_lg_error - create a graphical monitor of error history
6870 
6871 .keywords: TS,  vector, monitor, view
6872 
6873 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
6874 @*/
6875 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
6876 {
6877   PetscErrorCode    ierr;
6878   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
6879   const PetscScalar *yy;
6880   Vec               y;
6881 
6882   PetscFunctionBegin;
6883   if (!step) {
6884     PetscDrawAxis axis;
6885     PetscInt      dim;
6886     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
6887     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Error");CHKERRQ(ierr);
6888     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6889     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
6890     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
6891   }
6892   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
6893   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
6894   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
6895   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
6896 #if defined(PETSC_USE_COMPLEX)
6897   {
6898     PetscReal *yreal;
6899     PetscInt  i,n;
6900     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
6901     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
6902     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
6903     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
6904     ierr = PetscFree(yreal);CHKERRQ(ierr);
6905   }
6906 #else
6907   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
6908 #endif
6909   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
6910   ierr = VecDestroy(&y);CHKERRQ(ierr);
6911   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
6912     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
6913     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
6914   }
6915   PetscFunctionReturn(0);
6916 }
6917 
6918 /*@C
6919    TSMonitorError - Monitors progress of the TS solvers by printing the 2 norm of the error at each timestep
6920 
6921    Collective on TS
6922 
6923    Input Parameters:
6924 +  ts - the TS context
6925 .  step - current time-step
6926 .  ptime - current time
6927 .  u - current solution
6928 -  dctx - unused context
6929 
6930    Level: intermediate
6931 
6932    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
6933 
6934    Options Database Keys:
6935 .  -ts_monitor_error - create a graphical monitor of error history
6936 
6937 .keywords: TS,  vector, monitor, view
6938 
6939 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
6940 @*/
6941 PetscErrorCode  TSMonitorError(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
6942 {
6943   PetscErrorCode    ierr;
6944   Vec               y;
6945   PetscReal         nrm;
6946   PetscBool         flg;
6947 
6948   PetscFunctionBegin;
6949   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
6950   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
6951   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
6952   ierr = PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERASCII,&flg);CHKERRQ(ierr);
6953   if (flg) {
6954     ierr = VecNorm(y,NORM_2,&nrm);CHKERRQ(ierr);
6955     ierr = PetscViewerASCIIPrintf(vf->viewer,"2-norm of error %g\n",(double)nrm);CHKERRQ(ierr);
6956   }
6957   ierr = PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERDRAW,&flg);CHKERRQ(ierr);
6958   if (flg) {
6959     ierr = VecView(y,vf->viewer);CHKERRQ(ierr);
6960   }
6961   ierr = VecDestroy(&y);CHKERRQ(ierr);
6962   PetscFunctionReturn(0);
6963 }
6964 
6965 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
6966 {
6967   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
6968   PetscReal      x   = ptime,y;
6969   PetscErrorCode ierr;
6970   PetscInt       its;
6971 
6972   PetscFunctionBegin;
6973   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
6974   if (!n) {
6975     PetscDrawAxis axis;
6976     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
6977     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
6978     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
6979     ctx->snes_its = 0;
6980   }
6981   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
6982   y    = its - ctx->snes_its;
6983   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
6984   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
6985     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
6986     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
6987   }
6988   ctx->snes_its = its;
6989   PetscFunctionReturn(0);
6990 }
6991 
6992 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
6993 {
6994   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
6995   PetscReal      x   = ptime,y;
6996   PetscErrorCode ierr;
6997   PetscInt       its;
6998 
6999   PetscFunctionBegin;
7000   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7001   if (!n) {
7002     PetscDrawAxis axis;
7003     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7004     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
7005     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7006     ctx->ksp_its = 0;
7007   }
7008   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
7009   y    = its - ctx->ksp_its;
7010   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7011   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7012     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7013     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7014   }
7015   ctx->ksp_its = its;
7016   PetscFunctionReturn(0);
7017 }
7018 
7019 /*@
7020    TSComputeLinearStability - computes the linear stability function at a point
7021 
7022    Collective on TS and Vec
7023 
7024    Input Parameters:
7025 +  ts - the TS context
7026 -  xr,xi - real and imaginary part of input arguments
7027 
7028    Output Parameters:
7029 .  yr,yi - real and imaginary part of function value
7030 
7031    Level: developer
7032 
7033 .keywords: TS, compute
7034 
7035 .seealso: TSSetRHSFunction(), TSComputeIFunction()
7036 @*/
7037 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
7038 {
7039   PetscErrorCode ierr;
7040 
7041   PetscFunctionBegin;
7042   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7043   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
7044   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
7045   PetscFunctionReturn(0);
7046 }
7047 
7048 /* ------------------------------------------------------------------------*/
7049 /*@C
7050    TSMonitorEnvelopeCtxCreate - Creates a context for use with TSMonitorEnvelope()
7051 
7052    Collective on TS
7053 
7054    Input Parameters:
7055 .  ts  - the ODE solver object
7056 
7057    Output Parameter:
7058 .  ctx - the context
7059 
7060    Level: intermediate
7061 
7062 .keywords: TS, monitor, line graph, residual, seealso
7063 
7064 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
7065 
7066 @*/
7067 PetscErrorCode  TSMonitorEnvelopeCtxCreate(TS ts,TSMonitorEnvelopeCtx *ctx)
7068 {
7069   PetscErrorCode ierr;
7070 
7071   PetscFunctionBegin;
7072   ierr = PetscNew(ctx);CHKERRQ(ierr);
7073   PetscFunctionReturn(0);
7074 }
7075 
7076 /*@C
7077    TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
7078 
7079    Collective on TS
7080 
7081    Input Parameters:
7082 +  ts - the TS context
7083 .  step - current time-step
7084 .  ptime - current time
7085 .  u  - current solution
7086 -  dctx - the envelope context
7087 
7088    Options Database:
7089 .  -ts_monitor_envelope
7090 
7091    Level: intermediate
7092 
7093    Notes:
7094     after a solve you can use TSMonitorEnvelopeGetBounds() to access the envelope
7095 
7096 .keywords: TS,  vector, monitor, view
7097 
7098 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxCreate()
7099 @*/
7100 PetscErrorCode  TSMonitorEnvelope(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
7101 {
7102   PetscErrorCode       ierr;
7103   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
7104 
7105   PetscFunctionBegin;
7106   if (!ctx->max) {
7107     ierr = VecDuplicate(u,&ctx->max);CHKERRQ(ierr);
7108     ierr = VecDuplicate(u,&ctx->min);CHKERRQ(ierr);
7109     ierr = VecCopy(u,ctx->max);CHKERRQ(ierr);
7110     ierr = VecCopy(u,ctx->min);CHKERRQ(ierr);
7111   } else {
7112     ierr = VecPointwiseMax(ctx->max,u,ctx->max);CHKERRQ(ierr);
7113     ierr = VecPointwiseMin(ctx->min,u,ctx->min);CHKERRQ(ierr);
7114   }
7115   PetscFunctionReturn(0);
7116 }
7117 
7118 /*@C
7119    TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
7120 
7121    Collective on TS
7122 
7123    Input Parameter:
7124 .  ts - the TS context
7125 
7126    Output Parameter:
7127 +  max - the maximum values
7128 -  min - the minimum values
7129 
7130    Notes:
7131     If the TS does not have a TSMonitorEnvelopeCtx associated with it then this function is ignored
7132 
7133    Level: intermediate
7134 
7135 .keywords: TS,  vector, monitor, view
7136 
7137 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
7138 @*/
7139 PetscErrorCode  TSMonitorEnvelopeGetBounds(TS ts,Vec *max,Vec *min)
7140 {
7141   PetscInt i;
7142 
7143   PetscFunctionBegin;
7144   if (max) *max = NULL;
7145   if (min) *min = NULL;
7146   for (i=0; i<ts->numbermonitors; i++) {
7147     if (ts->monitor[i] == TSMonitorEnvelope) {
7148       TSMonitorEnvelopeCtx  ctx = (TSMonitorEnvelopeCtx) ts->monitorcontext[i];
7149       if (max) *max = ctx->max;
7150       if (min) *min = ctx->min;
7151       break;
7152     }
7153   }
7154   PetscFunctionReturn(0);
7155 }
7156 
7157 /*@C
7158    TSMonitorEnvelopeCtxDestroy - Destroys a context that was created  with TSMonitorEnvelopeCtxCreate().
7159 
7160    Collective on TSMonitorEnvelopeCtx
7161 
7162    Input Parameter:
7163 .  ctx - the monitor context
7164 
7165    Level: intermediate
7166 
7167 .keywords: TS, monitor, line graph, destroy
7168 
7169 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep()
7170 @*/
7171 PetscErrorCode  TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
7172 {
7173   PetscErrorCode ierr;
7174 
7175   PetscFunctionBegin;
7176   ierr = VecDestroy(&(*ctx)->min);CHKERRQ(ierr);
7177   ierr = VecDestroy(&(*ctx)->max);CHKERRQ(ierr);
7178   ierr = PetscFree(*ctx);CHKERRQ(ierr);
7179   PetscFunctionReturn(0);
7180 }
7181 
7182 /*@
7183    TSRestartStep - Flags the solver to restart the next step
7184 
7185    Collective on TS
7186 
7187    Input Parameter:
7188 .  ts - the TS context obtained from TSCreate()
7189 
7190    Level: advanced
7191 
7192    Notes:
7193    Multistep methods like BDF or Runge-Kutta methods with FSAL property require restarting the solver in the event of
7194    discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
7195    vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
7196    the sake of correctness and maximum safety, users are expected to call TSRestart() whenever they introduce
7197    discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
7198    discontinuous source terms).
7199 
7200 .keywords: TS, timestep, restart
7201 
7202 .seealso: TSSolve(), TSSetPreStep(), TSSetPostStep()
7203 @*/
7204 PetscErrorCode TSRestartStep(TS ts)
7205 {
7206   PetscFunctionBegin;
7207   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7208   ts->steprestart = PETSC_TRUE;
7209   PetscFunctionReturn(0);
7210 }
7211 
7212 /*@
7213    TSRollBack - Rolls back one time step
7214 
7215    Collective on TS
7216 
7217    Input Parameter:
7218 .  ts - the TS context obtained from TSCreate()
7219 
7220    Level: advanced
7221 
7222 .keywords: TS, timestep, rollback
7223 
7224 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
7225 @*/
7226 PetscErrorCode  TSRollBack(TS ts)
7227 {
7228   PetscErrorCode ierr;
7229 
7230   PetscFunctionBegin;
7231   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7232   if (ts->steprollback) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"TSRollBack already called");
7233   if (!ts->ops->rollback) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
7234   ierr = (*ts->ops->rollback)(ts);CHKERRQ(ierr);
7235   ts->time_step = ts->ptime - ts->ptime_prev;
7236   ts->ptime = ts->ptime_prev;
7237   ts->ptime_prev = ts->ptime_prev_rollback;
7238   ts->steps--;
7239   ts->steprollback = PETSC_TRUE;
7240   PetscFunctionReturn(0);
7241 }
7242 
7243 /*@
7244    TSGetStages - Get the number of stages and stage values
7245 
7246    Input Parameter:
7247 .  ts - the TS context obtained from TSCreate()
7248 
7249    Output Parameters:
7250 +  ns - the number of stages
7251 -  Y - the current stage vectors
7252 
7253    Level: advanced
7254 
7255    Notes: Both ns and Y can be NULL.
7256 
7257 .keywords: TS, getstages
7258 
7259 .seealso: TSCreate()
7260 @*/
7261 PetscErrorCode  TSGetStages(TS ts,PetscInt *ns,Vec **Y)
7262 {
7263   PetscErrorCode ierr;
7264 
7265   PetscFunctionBegin;
7266   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7267   if (ns) PetscValidPointer(ns,2);
7268   if (Y) PetscValidPointer(Y,3);
7269   if (!ts->ops->getstages) {
7270     if (ns) *ns = 0;
7271     if (Y) *Y = NULL;
7272   } else {
7273     ierr = (*ts->ops->getstages)(ts,ns,Y);CHKERRQ(ierr);
7274   }
7275   PetscFunctionReturn(0);
7276 }
7277 
7278 /*@C
7279   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
7280 
7281   Collective on SNES
7282 
7283   Input Parameters:
7284 + ts - the TS context
7285 . t - current timestep
7286 . U - state vector
7287 . Udot - time derivative of state vector
7288 . shift - shift to apply, see note below
7289 - ctx - an optional user context
7290 
7291   Output Parameters:
7292 + J - Jacobian matrix (not altered in this routine)
7293 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
7294 
7295   Level: intermediate
7296 
7297   Notes:
7298   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
7299 
7300   dF/dU + shift*dF/dUdot
7301 
7302   Most users should not need to explicitly call this routine, as it
7303   is used internally within the nonlinear solvers.
7304 
7305   This will first try to get the coloring from the DM.  If the DM type has no coloring
7306   routine, then it will try to get the coloring from the matrix.  This requires that the
7307   matrix have nonzero entries precomputed.
7308 
7309 .keywords: TS, finite differences, Jacobian, coloring, sparse
7310 .seealso: TSSetIJacobian(), MatFDColoringCreate(), MatFDColoringSetFunction()
7311 @*/
7312 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat J,Mat B,void *ctx)
7313 {
7314   SNES           snes;
7315   MatFDColoring  color;
7316   PetscBool      hascolor, matcolor = PETSC_FALSE;
7317   PetscErrorCode ierr;
7318 
7319   PetscFunctionBegin;
7320   ierr = PetscOptionsGetBool(((PetscObject)ts)->options,((PetscObject) ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL);CHKERRQ(ierr);
7321   ierr = PetscObjectQuery((PetscObject) B, "TSMatFDColoring", (PetscObject *) &color);CHKERRQ(ierr);
7322   if (!color) {
7323     DM         dm;
7324     ISColoring iscoloring;
7325 
7326     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
7327     ierr = DMHasColoring(dm, &hascolor);CHKERRQ(ierr);
7328     if (hascolor && !matcolor) {
7329       ierr = DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring);CHKERRQ(ierr);
7330       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7331       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7332       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7333       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7334       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7335     } else {
7336       MatColoring mc;
7337 
7338       ierr = MatColoringCreate(B, &mc);CHKERRQ(ierr);
7339       ierr = MatColoringSetDistance(mc, 2);CHKERRQ(ierr);
7340       ierr = MatColoringSetType(mc, MATCOLORINGSL);CHKERRQ(ierr);
7341       ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr);
7342       ierr = MatColoringApply(mc, &iscoloring);CHKERRQ(ierr);
7343       ierr = MatColoringDestroy(&mc);CHKERRQ(ierr);
7344       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7345       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7346       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7347       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7348       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7349     }
7350     ierr = PetscObjectCompose((PetscObject) B, "TSMatFDColoring", (PetscObject) color);CHKERRQ(ierr);
7351     ierr = PetscObjectDereference((PetscObject) color);CHKERRQ(ierr);
7352   }
7353   ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
7354   ierr = MatFDColoringApply(B, color, U, snes);CHKERRQ(ierr);
7355   if (J != B) {
7356     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7357     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7358   }
7359   PetscFunctionReturn(0);
7360 }
7361 
7362 /*@
7363     TSSetFunctionDomainError - Set the function testing if the current state vector is valid
7364 
7365     Input Parameters:
7366     ts - the TS context
7367     func - function called within TSFunctionDomainError
7368 
7369     Level: intermediate
7370 
7371 .keywords: TS, state, domain
7372 .seealso: TSAdaptCheckStage(), TSFunctionDomainError()
7373 @*/
7374 
7375 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS,PetscReal,Vec,PetscBool*))
7376 {
7377   PetscFunctionBegin;
7378   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7379   ts->functiondomainerror = func;
7380   PetscFunctionReturn(0);
7381 }
7382 
7383 /*@
7384     TSFunctionDomainError - Check if the current state is valid
7385 
7386     Input Parameters:
7387     ts - the TS context
7388     stagetime - time of the simulation
7389     Y - state vector to check.
7390 
7391     Output Parameter:
7392     accept - Set to PETSC_FALSE if the current state vector is valid.
7393 
7394     Note:
7395     This function should be used to ensure the state is in a valid part of the space.
7396     For example, one can ensure here all values are positive.
7397 
7398     Level: advanced
7399 @*/
7400 PetscErrorCode TSFunctionDomainError(TS ts,PetscReal stagetime,Vec Y,PetscBool* accept)
7401 {
7402   PetscFunctionBegin;
7403   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7404   *accept = PETSC_TRUE;
7405   if (ts->functiondomainerror) {
7406     PetscStackCallStandard((*ts->functiondomainerror),(ts,stagetime,Y,accept));
7407   }
7408   PetscFunctionReturn(0);
7409 }
7410 
7411 /*@C
7412   TSClone - This function clones a time step object.
7413 
7414   Collective on MPI_Comm
7415 
7416   Input Parameter:
7417 . tsin    - The input TS
7418 
7419   Output Parameter:
7420 . tsout   - The output TS (cloned)
7421 
7422   Notes:
7423   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.
7424 
7425   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);
7426 
7427   Level: developer
7428 
7429 .keywords: TS, clone
7430 .seealso: TSCreate(), TSSetType(), TSSetUp(), TSDestroy(), TSSetProblemType()
7431 @*/
7432 PetscErrorCode  TSClone(TS tsin, TS *tsout)
7433 {
7434   TS             t;
7435   PetscErrorCode ierr;
7436   SNES           snes_start;
7437   DM             dm;
7438   TSType         type;
7439 
7440   PetscFunctionBegin;
7441   PetscValidPointer(tsin,1);
7442   *tsout = NULL;
7443 
7444   ierr = PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView);CHKERRQ(ierr);
7445 
7446   /* General TS description */
7447   t->numbermonitors    = 0;
7448   t->setupcalled       = 0;
7449   t->ksp_its           = 0;
7450   t->snes_its          = 0;
7451   t->nwork             = 0;
7452   t->rhsjacobian.time  = -1e20;
7453   t->rhsjacobian.scale = 1.;
7454   t->ijacobian.shift   = 1.;
7455 
7456   ierr = TSGetSNES(tsin,&snes_start);CHKERRQ(ierr);
7457   ierr = TSSetSNES(t,snes_start);CHKERRQ(ierr);
7458 
7459   ierr = TSGetDM(tsin,&dm);CHKERRQ(ierr);
7460   ierr = TSSetDM(t,dm);CHKERRQ(ierr);
7461 
7462   t->adapt = tsin->adapt;
7463   ierr = PetscObjectReference((PetscObject)t->adapt);CHKERRQ(ierr);
7464 
7465   t->trajectory = tsin->trajectory;
7466   ierr = PetscObjectReference((PetscObject)t->trajectory);CHKERRQ(ierr);
7467 
7468   t->event = tsin->event;
7469   if (t->event) t->event->refct++;
7470 
7471   t->problem_type      = tsin->problem_type;
7472   t->ptime             = tsin->ptime;
7473   t->ptime_prev        = tsin->ptime_prev;
7474   t->time_step         = tsin->time_step;
7475   t->max_time          = tsin->max_time;
7476   t->steps             = tsin->steps;
7477   t->max_steps         = tsin->max_steps;
7478   t->equation_type     = tsin->equation_type;
7479   t->atol              = tsin->atol;
7480   t->rtol              = tsin->rtol;
7481   t->max_snes_failures = tsin->max_snes_failures;
7482   t->max_reject        = tsin->max_reject;
7483   t->errorifstepfailed = tsin->errorifstepfailed;
7484 
7485   ierr = TSGetType(tsin,&type);CHKERRQ(ierr);
7486   ierr = TSSetType(t,type);CHKERRQ(ierr);
7487 
7488   t->vec_sol           = NULL;
7489 
7490   t->cfltime          = tsin->cfltime;
7491   t->cfltime_local    = tsin->cfltime_local;
7492   t->exact_final_time = tsin->exact_final_time;
7493 
7494   ierr = PetscMemcpy(t->ops,tsin->ops,sizeof(struct _TSOps));CHKERRQ(ierr);
7495 
7496   if (((PetscObject)tsin)->fortran_func_pointers) {
7497     PetscInt i;
7498     ierr = PetscMalloc((10)*sizeof(void(*)(void)),&((PetscObject)t)->fortran_func_pointers);CHKERRQ(ierr);
7499     for (i=0; i<10; i++) {
7500       ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
7501     }
7502   }
7503   *tsout = t;
7504   PetscFunctionReturn(0);
7505 }
7506 
7507 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void* ctx,Vec x,Vec y)
7508 {
7509   PetscErrorCode ierr;
7510   TS             ts = (TS) ctx;
7511 
7512   PetscFunctionBegin;
7513   ierr = TSComputeRHSFunction(ts,0,x,y);CHKERRQ(ierr);
7514   PetscFunctionReturn(0);
7515 }
7516 
7517 /*@
7518     TSRHSJacobianTest - Compares the multiply routine provided to the MATSHELL with differencing on the TS given RHS function.
7519 
7520    Logically Collective on TS and Mat
7521 
7522     Input Parameters:
7523     TS - the time stepping routine
7524 
7525    Output Parameter:
7526 .   flg - PETSC_TRUE if the multiply is likely correct
7527 
7528    Options Database:
7529  .   -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
7530 
7531    Level: advanced
7532 
7533    Notes:
7534     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
7535 
7536 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellTestMultTranspose(), TSRHSJacobianTestTranspose()
7537 @*/
7538 PetscErrorCode  TSRHSJacobianTest(TS ts,PetscBool *flg)
7539 {
7540   Mat            J,B;
7541   PetscErrorCode ierr;
7542   TSRHSJacobian  func;
7543   void*          ctx;
7544 
7545   PetscFunctionBegin;
7546   ierr = TSGetRHSJacobian(ts,&J,&B,&func,&ctx);CHKERRQ(ierr);
7547   ierr = (*func)(ts,0.0,ts->vec_sol,J,B,ctx);CHKERRQ(ierr);
7548   ierr = MatShellTestMult(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg);CHKERRQ(ierr);
7549   PetscFunctionReturn(0);
7550 }
7551 
7552 /*@C
7553     TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the MATSHELL with differencing on the TS given RHS function.
7554 
7555    Logically Collective on TS and Mat
7556 
7557     Input Parameters:
7558     TS - the time stepping routine
7559 
7560    Output Parameter:
7561 .   flg - PETSC_TRUE if the multiply is likely correct
7562 
7563    Options Database:
7564 .   -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
7565 
7566    Notes:
7567     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
7568 
7569    Level: advanced
7570 
7571 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellTestMultTranspose(), TSRHSJacobianTest()
7572 @*/
7573 PetscErrorCode  TSRHSJacobianTestTranspose(TS ts,PetscBool *flg)
7574 {
7575   Mat            J,B;
7576   PetscErrorCode ierr;
7577   void           *ctx;
7578   TSRHSJacobian  func;
7579 
7580   PetscFunctionBegin;
7581   ierr = TSGetRHSJacobian(ts,&J,&B,&func,&ctx);CHKERRQ(ierr);
7582   ierr = (*func)(ts,0.0,ts->vec_sol,J,B,ctx);CHKERRQ(ierr);
7583   ierr = MatShellTestMultTranspose(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg);CHKERRQ(ierr);
7584   PetscFunctionReturn(0);
7585 }
7586