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