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