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