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