xref: /petsc/src/ts/interface/ts.c (revision 50c5671dffa46513473c2503d649ca60c7ec5643)
1 #include <petsc/private/tsimpl.h>        /*I "petscts.h"  I*/
2 #include <petscdmshell.h>
3 #include <petscdmda.h>
4 #include <petscviewer.h>
5 #include <petscdraw.h>
6 #include <petscconvest.h>
7 
8 #define SkipSmallValue(a,b,tol) if(PetscAbsScalar(a)< tol || PetscAbsScalar(b)< tol) continue;
9 
10 /* Logging support */
11 PetscClassId  TS_CLASSID, DMTS_CLASSID;
12 PetscLogEvent TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;
13 
14 const char *const TSExactFinalTimeOptions[] = {"UNSPECIFIED","STEPOVER","INTERPOLATE","MATCHSTEP","TSExactFinalTimeOption","TS_EXACTFINALTIME_",0};
15 
16 
17 /*@C
18    TSMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
19 
20    Collective on TS
21 
22    Input Parameters:
23 +  ts - TS object you wish to monitor
24 .  name - the monitor type one is seeking
25 .  help - message indicating what monitoring is done
26 .  manual - manual page for the monitor
27 .  monitor - the monitor function
28 -  monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the TS or PetscViewer objects
29 
30    Level: developer
31 
32 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
33           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
34           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
35           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
36           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
37           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
38           PetscOptionsFList(), PetscOptionsEList()
39 @*/
40 PetscErrorCode  TSMonitorSetFromOptions(TS ts,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(TS,PetscViewerAndFormat*))
41 {
42   PetscErrorCode    ierr;
43   PetscViewer       viewer;
44   PetscViewerFormat format;
45   PetscBool         flg;
46 
47   PetscFunctionBegin;
48   ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts),((PetscObject) ts)->options,((PetscObject)ts)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr);
49   if (flg) {
50     PetscViewerAndFormat *vf;
51     ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr);
52     ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr);
53     if (monitorsetup) {
54       ierr = (*monitorsetup)(ts,vf);CHKERRQ(ierr);
55     }
56     ierr = TSMonitorSet(ts,(PetscErrorCode (*)(TS,PetscInt,PetscReal,Vec,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr);
57   }
58   PetscFunctionReturn(0);
59 }
60 
61 static PetscErrorCode TSAdaptSetDefaultType(TSAdapt adapt,TSAdaptType default_type)
62 {
63   PetscErrorCode ierr;
64 
65   PetscFunctionBegin;
66   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
67   PetscValidCharPointer(default_type,2);
68   if (!((PetscObject)adapt)->type_name) {
69     ierr = TSAdaptSetType(adapt,default_type);CHKERRQ(ierr);
70   }
71   PetscFunctionReturn(0);
72 }
73 
74 /*@
75    TSSetFromOptions - Sets various TS parameters from user options.
76 
77    Collective on TS
78 
79    Input Parameter:
80 .  ts - the TS context obtained from TSCreate()
81 
82    Options Database Keys:
83 +  -ts_type <type> - TSEULER, TSBEULER, TSSUNDIALS, TSPSEUDO, TSCN, TSRK, TSTHETA, TSALPHA, TSGLLE, TSSSP, TSGLEE, TSBSYMP
84 .  -ts_save_trajectory - checkpoint the solution at each time-step
85 .  -ts_max_time <time> - maximum time to compute to
86 .  -ts_max_steps <steps> - maximum number of time-steps to take
87 .  -ts_init_time <time> - initial time to start computation
88 .  -ts_final_time <time> - final time to compute to (deprecated: use -ts_max_time)
89 .  -ts_dt <dt> - initial time step
90 .  -ts_exact_final_time <stepover,interpolate,matchstep> - whether to stop at the exact given final time and how to compute the solution at that ti,e
91 .  -ts_max_snes_failures <maxfailures> - Maximum number of nonlinear solve failures allowed
92 .  -ts_max_reject <maxrejects> - Maximum number of step rejections before step fails
93 .  -ts_error_if_step_fails <true,false> - Error if no step succeeds
94 .  -ts_rtol <rtol> - relative tolerance for local truncation error
95 .  -ts_atol <atol> Absolute tolerance for local truncation error
96 .  -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - test the Jacobian at each iteration against finite difference with RHS function
97 .  -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - test the Jacobian at each iteration against finite difference with RHS function
98 .  -ts_adjoint_solve <yes,no> After solving the ODE/DAE solve the adjoint problem (requires -ts_save_trajectory)
99 .  -ts_fd_color - Use finite differences with coloring to compute IJacobian
100 .  -ts_monitor - print information at each timestep
101 .  -ts_monitor_lg_solution - Monitor solution graphically
102 .  -ts_monitor_lg_error - Monitor error graphically
103 .  -ts_monitor_error - Monitors norm of error
104 .  -ts_monitor_lg_timestep - Monitor timestep size graphically
105 .  -ts_monitor_lg_timestep_log - Monitor log timestep size graphically
106 .  -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically
107 .  -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically
108 .  -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically
109 .  -ts_monitor_draw_solution - Monitor solution graphically
110 .  -ts_monitor_draw_solution_phase  <xleft,yleft,xright,yright> - Monitor solution graphically with phase diagram, requires problem with exactly 2 degrees of freedom
111 .  -ts_monitor_draw_error - Monitor error graphically, requires use to have provided TSSetSolutionFunction()
112 .  -ts_monitor_solution [ascii binary draw][:filename][:viewerformat] - monitors the solution at each timestep
113 .  -ts_monitor_solution_vtk <filename.vts,filename.vtu> - Save each time step to a binary file, use filename-%%03D.vts (filename-%%03D.vtu)
114 -  -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
115 
116    Developer Note:
117    We should unify all the -ts_monitor options in the way that -xxx_view has been unified
118 
119    Level: beginner
120 
121 .seealso: TSGetType()
122 @*/
123 PetscErrorCode  TSSetFromOptions(TS ts)
124 {
125   PetscBool              opt,flg,tflg;
126   PetscErrorCode         ierr;
127   char                   monfilename[PETSC_MAX_PATH_LEN];
128   PetscReal              time_step;
129   TSExactFinalTimeOption eftopt;
130   char                   dir[16];
131   TSIFunction            ifun;
132   const char             *defaultType;
133   char                   typeName[256];
134 
135   PetscFunctionBegin;
136   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
137 
138   ierr = TSRegisterAll();CHKERRQ(ierr);
139   ierr = TSGetIFunction(ts,NULL,&ifun,NULL);CHKERRQ(ierr);
140 
141   ierr = PetscObjectOptionsBegin((PetscObject)ts);CHKERRQ(ierr);
142   if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name;
143   else defaultType = ifun ? TSBEULER : TSEULER;
144   ierr = PetscOptionsFList("-ts_type","TS method","TSSetType",TSList,defaultType,typeName,256,&opt);CHKERRQ(ierr);
145   if (opt) {
146     ierr = TSSetType(ts,typeName);CHKERRQ(ierr);
147   } else {
148     ierr = TSSetType(ts,defaultType);CHKERRQ(ierr);
149   }
150 
151   /* Handle generic TS options */
152   ierr = PetscOptionsDeprecated("-ts_final_time","-ts_max_time","3.10",NULL);CHKERRQ(ierr);
153   ierr = PetscOptionsReal("-ts_max_time","Maximum time to run to","TSSetMaxTime",ts->max_time,&ts->max_time,NULL);CHKERRQ(ierr);
154   ierr = PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetMaxSteps",ts->max_steps,&ts->max_steps,NULL);CHKERRQ(ierr);
155   ierr = PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,NULL);CHKERRQ(ierr);
156   ierr = PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&time_step,&flg);CHKERRQ(ierr);
157   if (flg) {ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr);}
158   ierr = PetscOptionsEnum("-ts_exact_final_time","Option for handling of final time step","TSSetExactFinalTime",TSExactFinalTimeOptions,(PetscEnum)ts->exact_final_time,(PetscEnum*)&eftopt,&flg);CHKERRQ(ierr);
159   if (flg) {ierr = TSSetExactFinalTime(ts,eftopt);CHKERRQ(ierr);}
160   ierr = PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","TSSetMaxSNESFailures",ts->max_snes_failures,&ts->max_snes_failures,NULL);CHKERRQ(ierr);
161   ierr = PetscOptionsInt("-ts_max_reject","Maximum number of step rejections before step fails","TSSetMaxStepRejections",ts->max_reject,&ts->max_reject,NULL);CHKERRQ(ierr);
162   ierr = PetscOptionsBool("-ts_error_if_step_fails","Error if no step succeeds","TSSetErrorIfStepFails",ts->errorifstepfailed,&ts->errorifstepfailed,NULL);CHKERRQ(ierr);
163   ierr = PetscOptionsReal("-ts_rtol","Relative tolerance for local truncation error","TSSetTolerances",ts->rtol,&ts->rtol,NULL);CHKERRQ(ierr);
164   ierr = PetscOptionsReal("-ts_atol","Absolute tolerance for local truncation error","TSSetTolerances",ts->atol,&ts->atol,NULL);CHKERRQ(ierr);
165 
166   ierr = PetscOptionsBool("-ts_rhs_jacobian_test_mult","Test the RHS Jacobian for consistency with RHS at each solve ","None",ts->testjacobian,&ts->testjacobian,NULL);CHKERRQ(ierr);
167   ierr = PetscOptionsBool("-ts_rhs_jacobian_test_mult_transpose","Test the RHS Jacobian transpose for consistency with RHS at each solve ","None",ts->testjacobiantranspose,&ts->testjacobiantranspose,NULL);CHKERRQ(ierr);
168   ierr = PetscOptionsBool("-ts_use_splitrhsfunction","Use the split RHS function for multirate solvers ","TSSetUseSplitRHSFunction",ts->use_splitrhsfunction,&ts->use_splitrhsfunction,NULL);CHKERRQ(ierr);
169 #if defined(PETSC_HAVE_SAWS)
170   {
171     PetscBool set;
172     flg  = PETSC_FALSE;
173     ierr = PetscOptionsBool("-ts_saws_block","Block for SAWs memory snooper at end of TSSolve","PetscObjectSAWsBlock",((PetscObject)ts)->amspublishblock,&flg,&set);CHKERRQ(ierr);
174     if (set) {
175       ierr = PetscObjectSAWsSetBlock((PetscObject)ts,flg);CHKERRQ(ierr);
176     }
177   }
178 #endif
179 
180   /* Monitor options */
181   ierr = TSMonitorSetFromOptions(ts,"-ts_monitor","Monitor time and timestep size","TSMonitorDefault",TSMonitorDefault,NULL);CHKERRQ(ierr);
182   ierr = TSMonitorSetFromOptions(ts,"-ts_monitor_extreme","Monitor extreme values of the solution","TSMonitorExtreme",TSMonitorExtreme,NULL);CHKERRQ(ierr);
183   ierr = TSMonitorSetFromOptions(ts,"-ts_monitor_solution","View the solution at each timestep","TSMonitorSolution",TSMonitorSolution,NULL);CHKERRQ(ierr);
184 
185   ierr = PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
186   if (flg) {ierr = PetscPythonMonitorSet((PetscObject)ts,monfilename);CHKERRQ(ierr);}
187 
188   ierr = PetscOptionsName("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",&opt);CHKERRQ(ierr);
189   if (opt) {
190     TSMonitorLGCtx ctx;
191     PetscInt       howoften = 1;
192 
193     ierr = PetscOptionsInt("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",howoften,&howoften,NULL);CHKERRQ(ierr);
194     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
195     ierr = TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
196   }
197 
198   ierr = PetscOptionsName("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",&opt);CHKERRQ(ierr);
199   if (opt) {
200     TSMonitorLGCtx ctx;
201     PetscInt       howoften = 1;
202 
203     ierr = PetscOptionsInt("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",howoften,&howoften,NULL);CHKERRQ(ierr);
204     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
205     ierr = TSMonitorSet(ts,TSMonitorLGError,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
206   }
207   ierr = TSMonitorSetFromOptions(ts,"-ts_monitor_error","View the error at each timestep","TSMonitorError",TSMonitorError,NULL);CHKERRQ(ierr);
208 
209   ierr = PetscOptionsName("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",&opt);CHKERRQ(ierr);
210   if (opt) {
211     TSMonitorLGCtx ctx;
212     PetscInt       howoften = 1;
213 
214     ierr = PetscOptionsInt("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL);CHKERRQ(ierr);
215     ierr = TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
216     ierr = TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
217   }
218   ierr = PetscOptionsName("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",&opt);CHKERRQ(ierr);
219   if (opt) {
220     TSMonitorLGCtx ctx;
221     PetscInt       howoften = 1;
222 
223     ierr = PetscOptionsInt("-ts_monitor_lg_timestep_log","Monitor log timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL);CHKERRQ(ierr);
224     ierr = TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
225     ierr = TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
226     ctx->semilogy = PETSC_TRUE;
227   }
228 
229   ierr = PetscOptionsName("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",&opt);CHKERRQ(ierr);
230   if (opt) {
231     TSMonitorLGCtx ctx;
232     PetscInt       howoften = 1;
233 
234     ierr = PetscOptionsInt("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",howoften,&howoften,NULL);CHKERRQ(ierr);
235     ierr = TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
236     ierr = TSMonitorSet(ts,TSMonitorLGSNESIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
237   }
238   ierr = PetscOptionsName("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",&opt);CHKERRQ(ierr);
239   if (opt) {
240     TSMonitorLGCtx ctx;
241     PetscInt       howoften = 1;
242 
243     ierr = PetscOptionsInt("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",howoften,&howoften,NULL);CHKERRQ(ierr);
244     ierr = TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,howoften,&ctx);CHKERRQ(ierr);
245     ierr = TSMonitorSet(ts,TSMonitorLGKSPIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
246   }
247   ierr = PetscOptionsName("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",&opt);CHKERRQ(ierr);
248   if (opt) {
249     TSMonitorSPEigCtx ctx;
250     PetscInt          howoften = 1;
251 
252     ierr = PetscOptionsInt("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",howoften,&howoften,NULL);CHKERRQ(ierr);
253     ierr = TSMonitorSPEigCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
254     ierr = TSMonitorSet(ts,TSMonitorSPEig,ctx,(PetscErrorCode (*)(void**))TSMonitorSPEigCtxDestroy);CHKERRQ(ierr);
255   }
256   ierr = PetscOptionsName("-ts_monitor_sp_swarm","Display particle phase from the DMSwarm","TSMonitorSPSwarm",&opt);CHKERRQ(ierr);
257   if (opt) {
258     TSMonitorSPCtx  ctx;
259     PetscInt        howoften = 1;
260     ierr = PetscOptionsInt("-ts_monitor_sp_swarm","Display particles phase from the DMSwarm","TSMonitorSPSwarm",howoften,&howoften,NULL);CHKERRQ(ierr);
261     ierr = TSMonitorSPCtxCreate(PETSC_COMM_SELF, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, howoften, &ctx);CHKERRQ(ierr);
262     ierr = TSMonitorSet(ts, TSMonitorSPSwarmSolution, ctx, (PetscErrorCode (*)(void**))TSMonitorSPCtxDestroy);CHKERRQ(ierr);
263   }
264   opt  = PETSC_FALSE;
265   ierr = PetscOptionsName("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",&opt);CHKERRQ(ierr);
266   if (opt) {
267     TSMonitorDrawCtx ctx;
268     PetscInt         howoften = 1;
269 
270     ierr = PetscOptionsInt("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",howoften,&howoften,NULL);CHKERRQ(ierr);
271     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,"Computed Solution",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
272     ierr = TSMonitorSet(ts,TSMonitorDrawSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
273   }
274   opt  = PETSC_FALSE;
275   ierr = PetscOptionsName("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",&opt);CHKERRQ(ierr);
276   if (opt) {
277     TSMonitorDrawCtx ctx;
278     PetscReal        bounds[4];
279     PetscInt         n = 4;
280     PetscDraw        draw;
281     PetscDrawAxis    axis;
282 
283     ierr = PetscOptionsRealArray("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",bounds,&n,NULL);CHKERRQ(ierr);
284     if (n != 4) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Must provide bounding box of phase field");
285     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,1,&ctx);CHKERRQ(ierr);
286     ierr = PetscViewerDrawGetDraw(ctx->viewer,0,&draw);CHKERRQ(ierr);
287     ierr = PetscViewerDrawGetDrawAxis(ctx->viewer,0,&axis);CHKERRQ(ierr);
288     ierr = PetscDrawAxisSetLimits(axis,bounds[0],bounds[2],bounds[1],bounds[3]);CHKERRQ(ierr);
289     ierr = PetscDrawAxisSetLabels(axis,"Phase Diagram","Variable 1","Variable 2");CHKERRQ(ierr);
290     ierr = TSMonitorSet(ts,TSMonitorDrawSolutionPhase,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
291   }
292   opt  = PETSC_FALSE;
293   ierr = PetscOptionsName("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",&opt);CHKERRQ(ierr);
294   if (opt) {
295     TSMonitorDrawCtx ctx;
296     PetscInt         howoften = 1;
297 
298     ierr = PetscOptionsInt("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",howoften,&howoften,NULL);CHKERRQ(ierr);
299     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,"Error",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
300     ierr = TSMonitorSet(ts,TSMonitorDrawError,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
301   }
302   opt  = PETSC_FALSE;
303   ierr = PetscOptionsName("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",&opt);CHKERRQ(ierr);
304   if (opt) {
305     TSMonitorDrawCtx ctx;
306     PetscInt         howoften = 1;
307 
308     ierr = PetscOptionsInt("-ts_monitor_draw_solution_function","Monitor solution provided by TSMonitorSetSolutionFunction() graphically","TSMonitorDrawSolutionFunction",howoften,&howoften,NULL);CHKERRQ(ierr);
309     ierr = TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,"Solution provided by user function",PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
310     ierr = TSMonitorSet(ts,TSMonitorDrawSolutionFunction,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
311   }
312 
313   opt  = PETSC_FALSE;
314   ierr = PetscOptionsString("-ts_monitor_solution_vtk","Save each time step to a binary file, use filename-%%03D.vts","TSMonitorSolutionVTK",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
315   if (flg) {
316     const char *ptr,*ptr2;
317     char       *filetemplate;
318     if (!monfilename[0]) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
319     /* Do some cursory validation of the input. */
320     ierr = PetscStrstr(monfilename,"%",(char**)&ptr);CHKERRQ(ierr);
321     if (!ptr) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
322     for (ptr++; ptr && *ptr; ptr++) {
323       ierr = PetscStrchr("DdiouxX",*ptr,(char**)&ptr2);CHKERRQ(ierr);
324       if (!ptr2 && (*ptr < '0' || '9' < *ptr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03D.vts");
325       if (ptr2) break;
326     }
327     ierr = PetscStrallocpy(monfilename,&filetemplate);CHKERRQ(ierr);
328     ierr = TSMonitorSet(ts,TSMonitorSolutionVTK,filetemplate,(PetscErrorCode (*)(void**))TSMonitorSolutionVTKDestroy);CHKERRQ(ierr);
329   }
330 
331   ierr = PetscOptionsString("-ts_monitor_dmda_ray","Display a ray of the solution","None","y=0",dir,16,&flg);CHKERRQ(ierr);
332   if (flg) {
333     TSMonitorDMDARayCtx *rayctx;
334     int                  ray = 0;
335     DMDirection          ddir;
336     DM                   da;
337     PetscMPIInt          rank;
338 
339     if (dir[1] != '=') SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
340     if (dir[0] == 'x') ddir = DM_X;
341     else if (dir[0] == 'y') ddir = DM_Y;
342     else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
343     sscanf(dir+2,"%d",&ray);
344 
345     ierr = PetscInfo2(((PetscObject)ts),"Displaying DMDA ray %c = %d\n",dir[0],ray);CHKERRQ(ierr);
346     ierr = PetscNew(&rayctx);CHKERRQ(ierr);
347     ierr = TSGetDM(ts,&da);CHKERRQ(ierr);
348     ierr = DMDAGetRay(da,ddir,ray,&rayctx->ray,&rayctx->scatter);CHKERRQ(ierr);
349     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)ts),&rank);CHKERRQ(ierr);
350     if (!rank) {
351       ierr = PetscViewerDrawOpen(PETSC_COMM_SELF,0,0,0,0,600,300,&rayctx->viewer);CHKERRQ(ierr);
352     }
353     rayctx->lgctx = NULL;
354     ierr = TSMonitorSet(ts,TSMonitorDMDARay,rayctx,TSMonitorDMDARayDestroy);CHKERRQ(ierr);
355   }
356   ierr = PetscOptionsString("-ts_monitor_lg_dmda_ray","Display a ray of the solution","None","x=0",dir,16,&flg);CHKERRQ(ierr);
357   if (flg) {
358     TSMonitorDMDARayCtx *rayctx;
359     int                 ray = 0;
360     DMDirection         ddir;
361     DM                  da;
362     PetscInt            howoften = 1;
363 
364     if (dir[1] != '=') SETERRQ1(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir);
365     if      (dir[0] == 'x') ddir = DM_X;
366     else if (dir[0] == 'y') ddir = DM_Y;
367     else SETERRQ1(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir);
368     sscanf(dir+2, "%d", &ray);
369 
370     ierr = PetscInfo2(((PetscObject) ts),"Displaying LG DMDA ray %c = %d\n", dir[0], ray);CHKERRQ(ierr);
371     ierr = PetscNew(&rayctx);CHKERRQ(ierr);
372     ierr = TSGetDM(ts, &da);CHKERRQ(ierr);
373     ierr = DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter);CHKERRQ(ierr);
374     ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&rayctx->lgctx);CHKERRQ(ierr);
375     ierr = TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy);CHKERRQ(ierr);
376   }
377 
378   ierr = PetscOptionsName("-ts_monitor_envelope","Monitor maximum and minimum value of each component of the solution","TSMonitorEnvelope",&opt);CHKERRQ(ierr);
379   if (opt) {
380     TSMonitorEnvelopeCtx ctx;
381 
382     ierr = TSMonitorEnvelopeCtxCreate(ts,&ctx);CHKERRQ(ierr);
383     ierr = TSMonitorSet(ts,TSMonitorEnvelope,ctx,(PetscErrorCode (*)(void**))TSMonitorEnvelopeCtxDestroy);CHKERRQ(ierr);
384   }
385 
386   flg  = PETSC_FALSE;
387   ierr = PetscOptionsBool("-ts_fd_color", "Use finite differences with coloring to compute IJacobian", "TSComputeJacobianDefaultColor", flg, &flg, NULL);CHKERRQ(ierr);
388   if (flg) {
389     DM   dm;
390     DMTS tdm;
391 
392     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
393     ierr = DMGetDMTS(dm, &tdm);CHKERRQ(ierr);
394     tdm->ijacobianctx = NULL;
395     ierr = TSSetIJacobian(ts, NULL, NULL, TSComputeIJacobianDefaultColor, 0);CHKERRQ(ierr);
396     ierr = PetscInfo(ts, "Setting default finite difference coloring Jacobian matrix\n");CHKERRQ(ierr);
397   }
398 
399   /* Handle specific TS options */
400   if (ts->ops->setfromoptions) {
401     ierr = (*ts->ops->setfromoptions)(PetscOptionsObject,ts);CHKERRQ(ierr);
402   }
403 
404   /* Handle TSAdapt options */
405   ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr);
406   ierr = TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type);CHKERRQ(ierr);
407   ierr = TSAdaptSetFromOptions(PetscOptionsObject,ts->adapt);CHKERRQ(ierr);
408 
409   /* TS trajectory must be set after TS, since it may use some TS options above */
410   tflg = ts->trajectory ? PETSC_TRUE : PETSC_FALSE;
411   ierr = PetscOptionsBool("-ts_save_trajectory","Save the solution at each timestep","TSSetSaveTrajectory",tflg,&tflg,NULL);CHKERRQ(ierr);
412   if (tflg) {
413     ierr = TSSetSaveTrajectory(ts);CHKERRQ(ierr);
414   }
415 
416   ierr = TSAdjointSetFromOptions(PetscOptionsObject,ts);CHKERRQ(ierr);
417 
418   /* process any options handlers added with PetscObjectAddOptionsHandler() */
419   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)ts);CHKERRQ(ierr);
420   ierr = PetscOptionsEnd();CHKERRQ(ierr);
421 
422   if (ts->trajectory) {
423     ierr = TSTrajectorySetFromOptions(ts->trajectory,ts);CHKERRQ(ierr);
424   }
425 
426   /* why do we have to do this here and not during TSSetUp? */
427   ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr);
428   if (ts->problem_type == TS_LINEAR) {
429     ierr = PetscObjectTypeCompareAny((PetscObject)ts->snes,&flg,SNESKSPONLY,SNESKSPTRANSPOSEONLY,"");CHKERRQ(ierr);
430     if (!flg) { ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr); }
431   }
432   ierr = SNESSetFromOptions(ts->snes);CHKERRQ(ierr);
433   PetscFunctionReturn(0);
434 }
435 
436 /*@
437    TSGetTrajectory - Gets the trajectory from a TS if it exists
438 
439    Collective on TS
440 
441    Input Parameters:
442 .  ts - the TS context obtained from TSCreate()
443 
444    Output Parameters:
445 .  tr - the TSTrajectory object, if it exists
446 
447    Note: This routine should be called after all TS options have been set
448 
449    Level: advanced
450 
451 .seealso: TSGetTrajectory(), TSAdjointSolve(), TSTrajectory, TSTrajectoryCreate()
452 
453 @*/
454 PetscErrorCode  TSGetTrajectory(TS ts,TSTrajectory *tr)
455 {
456   PetscFunctionBegin;
457   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
458   *tr = ts->trajectory;
459   PetscFunctionReturn(0);
460 }
461 
462 /*@
463    TSSetSaveTrajectory - Causes the TS to save its solutions as it iterates forward in time in a TSTrajectory object
464 
465    Collective on TS
466 
467    Input Parameters:
468 .  ts - the TS context obtained from TSCreate()
469 
470    Options Database:
471 +  -ts_save_trajectory - saves the trajectory to a file
472 -  -ts_trajectory_type type
473 
474 Note: This routine should be called after all TS options have been set
475 
476     The TSTRAJECTORYVISUALIZATION files can be loaded into Python with $PETSC_DIR/lib/petsc/bin/PetscBinaryIOTrajectory.py and
477    MATLAB with $PETSC_DIR/share/petsc/matlab/PetscReadBinaryTrajectory.m
478 
479    Level: intermediate
480 
481 .seealso: TSGetTrajectory(), TSAdjointSolve()
482 
483 @*/
484 PetscErrorCode  TSSetSaveTrajectory(TS ts)
485 {
486   PetscErrorCode ierr;
487 
488   PetscFunctionBegin;
489   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
490   if (!ts->trajectory) {
491     ierr = TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory);CHKERRQ(ierr);
492   }
493   PetscFunctionReturn(0);
494 }
495 
496 /*@
497    TSResetTrajectory - Destroys and recreates the internal TSTrajectory object
498 
499    Collective on TS
500 
501    Input Parameters:
502 .  ts - the TS context obtained from TSCreate()
503 
504    Level: intermediate
505 
506 .seealso: TSGetTrajectory(), TSAdjointSolve()
507 
508 @*/
509 PetscErrorCode  TSResetTrajectory(TS ts)
510 {
511   PetscErrorCode ierr;
512 
513   PetscFunctionBegin;
514   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
515   if (ts->trajectory) {
516     ierr = TSTrajectoryDestroy(&ts->trajectory);CHKERRQ(ierr);
517     ierr = TSTrajectoryCreate(PetscObjectComm((PetscObject)ts),&ts->trajectory);CHKERRQ(ierr);
518   }
519   PetscFunctionReturn(0);
520 }
521 
522 /*@
523    TSComputeRHSJacobian - Computes the Jacobian matrix that has been
524       set with TSSetRHSJacobian().
525 
526    Collective on TS
527 
528    Input Parameters:
529 +  ts - the TS context
530 .  t - current timestep
531 -  U - input vector
532 
533    Output Parameters:
534 +  A - Jacobian matrix
535 .  B - optional preconditioning matrix
536 -  flag - flag indicating matrix structure
537 
538    Notes:
539    Most users should not need to explicitly call this routine, as it
540    is used internally within the nonlinear solvers.
541 
542    See KSPSetOperators() for important information about setting the
543    flag parameter.
544 
545    Level: developer
546 
547 .seealso:  TSSetRHSJacobian(), KSPSetOperators()
548 @*/
549 PetscErrorCode  TSComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat B)
550 {
551   PetscErrorCode   ierr;
552   PetscObjectState Ustate;
553   PetscObjectId    Uid;
554   DM               dm;
555   DMTS             tsdm;
556   TSRHSJacobian    rhsjacobianfunc;
557   void             *ctx;
558   TSIJacobian      ijacobianfunc;
559   TSRHSFunction    rhsfunction;
560 
561   PetscFunctionBegin;
562   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
563   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
564   PetscCheckSameComm(ts,1,U,3);
565   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
566   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
567   ierr = DMTSGetRHSJacobian(dm,&rhsjacobianfunc,&ctx);CHKERRQ(ierr);
568   ierr = DMTSGetIJacobian(dm,&ijacobianfunc,NULL);CHKERRQ(ierr);
569   ierr = DMTSGetRHSFunction(dm,&rhsfunction,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 = 0; 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("@techreport{tspaper,\n"
3685                                 "  title       = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
3686                                 "  author      = {Shrirang Abhyankar and Jed Brown and Emil Constantinescu and Debojyoti Ghosh and Barry F. Smith},\n"
3687                                 "  type        = {Preprint},\n"
3688                                 "  number      = {ANL/MCS-P5061-0114},\n"
3689                                 "  institution = {Argonne National Laboratory},\n"
3690                                 "  year        = {2014}\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 
4069         incall = PETSC_TRUE;
4070         ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
4071         ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
4072         ierr = PetscCalloc1(PetscMax(Nf, 1), &alpha);CHKERRQ(ierr);
4073         ierr = PetscConvEstCreate(PetscObjectComm((PetscObject) ts), &conv);CHKERRQ(ierr);
4074         ierr = PetscConvEstUseTS(conv);CHKERRQ(ierr);
4075         ierr = PetscConvEstSetSolver(conv, (PetscObject) ts);CHKERRQ(ierr);
4076         ierr = PetscConvEstSetFromOptions(conv);CHKERRQ(ierr);
4077         ierr = PetscConvEstSetUp(conv);CHKERRQ(ierr);
4078         ierr = PetscConvEstGetConvRate(conv, alpha);CHKERRQ(ierr);
4079         ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr);
4080         ierr = PetscConvEstRateView(conv, alpha, viewer);CHKERRQ(ierr);
4081         ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
4082         ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4083         ierr = PetscConvEstDestroy(&conv);CHKERRQ(ierr);
4084         ierr = PetscFree(alpha);CHKERRQ(ierr);
4085         incall = PETSC_FALSE;
4086       }
4087     }
4088   }
4089 
4090   ierr = TSViewFromOptions(ts,NULL,"-ts_view_pre");CHKERRQ(ierr);
4091 
4092   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
4093     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
4094     if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
4095     ts->solvetime = ts->ptime;
4096     solution = ts->vec_sol;
4097   } else { /* Step the requested number of timesteps. */
4098     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4099     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4100 
4101     if (!ts->steps) {
4102       ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4103       ierr = TSEventInitialize(ts->event,ts,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4104     }
4105 
4106     while (!ts->reason) {
4107       ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4108       if (!ts->steprollback) {
4109         ierr = TSPreStep(ts);CHKERRQ(ierr);
4110       }
4111       ierr = TSStep(ts);CHKERRQ(ierr);
4112       if (ts->testjacobian) {
4113         ierr = TSRHSJacobianTest(ts,NULL);CHKERRQ(ierr);
4114       }
4115       if (ts->testjacobiantranspose) {
4116         ierr = TSRHSJacobianTestTranspose(ts,NULL);CHKERRQ(ierr);
4117       }
4118       if (ts->quadraturets && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
4119         if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
4120         ierr = TSForwardCostIntegral(ts);CHKERRQ(ierr);
4121         if (ts->reason >= 0) ts->steps++;
4122       }
4123       if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
4124         if (ts->reason >= 0) ts->steps--; /* Revert the step number changed by TSStep() */
4125         ierr = TSForwardStep(ts);CHKERRQ(ierr);
4126         if (ts->reason >= 0) ts->steps++;
4127       }
4128       ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
4129       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. */
4130       if (ts->steprollback) {
4131         ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
4132       }
4133       if (!ts->steprollback) {
4134         ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4135         ierr = TSPostStep(ts);CHKERRQ(ierr);
4136       }
4137     }
4138     ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4139 
4140     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
4141       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
4142       ts->solvetime = ts->max_time;
4143       solution = u;
4144       ierr = TSMonitor(ts,-1,ts->solvetime,solution);CHKERRQ(ierr);
4145     } else {
4146       if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
4147       ts->solvetime = ts->ptime;
4148       solution = ts->vec_sol;
4149     }
4150   }
4151 
4152   ierr = TSViewFromOptions(ts,NULL,"-ts_view");CHKERRQ(ierr);
4153   ierr = VecViewFromOptions(solution,NULL,"-ts_view_solution");CHKERRQ(ierr);
4154   ierr = PetscObjectSAWsBlock((PetscObject)ts);CHKERRQ(ierr);
4155   if (ts->adjoint_solve) {
4156     ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
4157   }
4158   PetscFunctionReturn(0);
4159 }
4160 
4161 /*@C
4162    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
4163 
4164    Collective on TS
4165 
4166    Input Parameters:
4167 +  ts - time stepping context obtained from TSCreate()
4168 .  step - step number that has just completed
4169 .  ptime - model time of the state
4170 -  u - state at the current model time
4171 
4172    Notes:
4173    TSMonitor() is typically used automatically within the time stepping implementations.
4174    Users would almost never call this routine directly.
4175 
4176    A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
4177 
4178    Level: developer
4179 
4180 @*/
4181 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
4182 {
4183   DM             dm;
4184   PetscInt       i,n = ts->numbermonitors;
4185   PetscErrorCode ierr;
4186 
4187   PetscFunctionBegin;
4188   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4189   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4190 
4191   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4192   ierr = DMSetOutputSequenceNumber(dm,step,ptime);CHKERRQ(ierr);
4193 
4194   ierr = VecLockReadPush(u);CHKERRQ(ierr);
4195   for (i=0; i<n; i++) {
4196     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
4197   }
4198   ierr = VecLockReadPop(u);CHKERRQ(ierr);
4199   PetscFunctionReturn(0);
4200 }
4201 
4202 /* ------------------------------------------------------------------------*/
4203 /*@C
4204    TSMonitorLGCtxCreate - Creates a TSMonitorLGCtx context for use with
4205    TS to monitor the solution process graphically in various ways
4206 
4207    Collective on TS
4208 
4209    Input Parameters:
4210 +  host - the X display to open, or null for the local machine
4211 .  label - the title to put in the title bar
4212 .  x, y - the screen coordinates of the upper left coordinate of the window
4213 .  m, n - the screen width and height in pixels
4214 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
4215 
4216    Output Parameter:
4217 .  ctx - the context
4218 
4219    Options Database Key:
4220 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
4221 +  -ts_monitor_lg_timestep_log - automatically sets line graph monitor
4222 .  -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling TSMonitorLGSetDisplayVariables() or TSMonitorLGCtxSetDisplayVariables())
4223 .  -ts_monitor_lg_error -  monitor the error
4224 .  -ts_monitor_lg_ksp_iterations - monitor the number of KSP iterations needed for each timestep
4225 .  -ts_monitor_lg_snes_iterations - monitor the number of SNES iterations needed for each timestep
4226 -  -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
4227 
4228    Notes:
4229    Use TSMonitorLGCtxDestroy() to destroy.
4230 
4231    One can provide a function that transforms the solution before plotting it with TSMonitorLGCtxSetTransform() or TSMonitorLGSetTransform()
4232 
4233    Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a TS object as the
4234    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
4235    as the first argument.
4236 
4237    One can control the names displayed for each solution or error variable with TSMonitorLGCtxSetVariableNames() or TSMonitorLGSetVariableNames()
4238 
4239    Level: intermediate
4240 
4241 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError(), TSMonitorDefault(), VecView(),
4242            TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
4243            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
4244            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
4245            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
4246 
4247 @*/
4248 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
4249 {
4250   PetscDraw      draw;
4251   PetscErrorCode ierr;
4252 
4253   PetscFunctionBegin;
4254   ierr = PetscNew(ctx);CHKERRQ(ierr);
4255   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&draw);CHKERRQ(ierr);
4256   ierr = PetscDrawSetFromOptions(draw);CHKERRQ(ierr);
4257   ierr = PetscDrawLGCreate(draw,1,&(*ctx)->lg);CHKERRQ(ierr);
4258   ierr = PetscDrawLGSetFromOptions((*ctx)->lg);CHKERRQ(ierr);
4259   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
4260   (*ctx)->howoften = howoften;
4261   PetscFunctionReturn(0);
4262 }
4263 
4264 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
4265 {
4266   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4267   PetscReal      x   = ptime,y;
4268   PetscErrorCode ierr;
4269 
4270   PetscFunctionBegin;
4271   if (step < 0) PetscFunctionReturn(0); /* -1 indicates an interpolated solution */
4272   if (!step) {
4273     PetscDrawAxis axis;
4274     const char *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
4275     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4276     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time",ylabel);CHKERRQ(ierr);
4277     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4278   }
4279   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
4280   if (ctx->semilogy) y = PetscLog10Real(y);
4281   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4282   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4283     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4284     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
4285   }
4286   PetscFunctionReturn(0);
4287 }
4288 
4289 /*@C
4290    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
4291    with TSMonitorLGCtxCreate().
4292 
4293    Collective on TSMonitorLGCtx
4294 
4295    Input Parameter:
4296 .  ctx - the monitor context
4297 
4298    Level: intermediate
4299 
4300 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
4301 @*/
4302 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
4303 {
4304   PetscErrorCode ierr;
4305 
4306   PetscFunctionBegin;
4307   if ((*ctx)->transformdestroy) {
4308     ierr = ((*ctx)->transformdestroy)((*ctx)->transformctx);CHKERRQ(ierr);
4309   }
4310   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
4311   ierr = PetscStrArrayDestroy(&(*ctx)->names);CHKERRQ(ierr);
4312   ierr = PetscStrArrayDestroy(&(*ctx)->displaynames);CHKERRQ(ierr);
4313   ierr = PetscFree((*ctx)->displayvariables);CHKERRQ(ierr);
4314   ierr = PetscFree((*ctx)->displayvalues);CHKERRQ(ierr);
4315   ierr = PetscFree(*ctx);CHKERRQ(ierr);
4316   PetscFunctionReturn(0);
4317 }
4318 
4319 /*
4320 
4321   Creates a TS Monitor SPCtx for use with DM Swarm particle visualizations
4322 
4323 */
4324 PetscErrorCode TSMonitorSPCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorSPCtx *ctx)
4325 {
4326   PetscDraw      draw;
4327   PetscErrorCode ierr;
4328 
4329   PetscFunctionBegin;
4330   ierr = PetscNew(ctx);CHKERRQ(ierr);
4331   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&draw);CHKERRQ(ierr);
4332   ierr = PetscDrawSetFromOptions(draw);CHKERRQ(ierr);
4333   ierr = PetscDrawSPCreate(draw,1,&(*ctx)->sp);CHKERRQ(ierr);
4334   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
4335   (*ctx)->howoften = howoften;
4336   PetscFunctionReturn(0);
4337 
4338 }
4339 
4340 /*
4341   Destroys a TSMonitorSPCtx that was created with TSMonitorSPCtxCreate
4342 */
4343 PetscErrorCode TSMonitorSPCtxDestroy(TSMonitorSPCtx *ctx)
4344 {
4345   PetscErrorCode ierr;
4346 
4347   PetscFunctionBegin;
4348 
4349   ierr = PetscDrawSPDestroy(&(*ctx)->sp);CHKERRQ(ierr);
4350   ierr = PetscFree(*ctx);CHKERRQ(ierr);
4351 
4352   PetscFunctionReturn(0);
4353 
4354 }
4355 
4356 /*@
4357    TSGetTime - Gets the time of the most recently completed step.
4358 
4359    Not Collective
4360 
4361    Input Parameter:
4362 .  ts - the TS context obtained from TSCreate()
4363 
4364    Output Parameter:
4365 .  t  - the current time. This time may not corresponds to the final time set with TSSetMaxTime(), use TSGetSolveTime().
4366 
4367    Level: beginner
4368 
4369    Note:
4370    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
4371    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
4372 
4373 .seealso:  TSGetSolveTime(), TSSetTime(), TSGetTimeStep(), TSGetStepNumber()
4374 
4375 @*/
4376 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
4377 {
4378   PetscFunctionBegin;
4379   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4380   PetscValidRealPointer(t,2);
4381   *t = ts->ptime;
4382   PetscFunctionReturn(0);
4383 }
4384 
4385 /*@
4386    TSGetPrevTime - Gets the starting time of the previously completed step.
4387 
4388    Not Collective
4389 
4390    Input Parameter:
4391 .  ts - the TS context obtained from TSCreate()
4392 
4393    Output Parameter:
4394 .  t  - the previous time
4395 
4396    Level: beginner
4397 
4398 .seealso: TSGetTime(), TSGetSolveTime(), TSGetTimeStep()
4399 
4400 @*/
4401 PetscErrorCode  TSGetPrevTime(TS ts,PetscReal *t)
4402 {
4403   PetscFunctionBegin;
4404   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4405   PetscValidRealPointer(t,2);
4406   *t = ts->ptime_prev;
4407   PetscFunctionReturn(0);
4408 }
4409 
4410 /*@
4411    TSSetTime - Allows one to reset the time.
4412 
4413    Logically Collective on TS
4414 
4415    Input Parameters:
4416 +  ts - the TS context obtained from TSCreate()
4417 -  time - the time
4418 
4419    Level: intermediate
4420 
4421 .seealso: TSGetTime(), TSSetMaxSteps()
4422 
4423 @*/
4424 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
4425 {
4426   PetscFunctionBegin;
4427   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4428   PetscValidLogicalCollectiveReal(ts,t,2);
4429   ts->ptime = t;
4430   PetscFunctionReturn(0);
4431 }
4432 
4433 /*@C
4434    TSSetOptionsPrefix - Sets the prefix used for searching for all
4435    TS options in the database.
4436 
4437    Logically Collective on TS
4438 
4439    Input Parameter:
4440 +  ts     - The TS context
4441 -  prefix - The prefix to prepend to all option names
4442 
4443    Notes:
4444    A hyphen (-) must NOT be given at the beginning of the prefix name.
4445    The first character of all runtime options is AUTOMATICALLY the
4446    hyphen.
4447 
4448    Level: advanced
4449 
4450 .seealso: TSSetFromOptions()
4451 
4452 @*/
4453 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
4454 {
4455   PetscErrorCode ierr;
4456   SNES           snes;
4457 
4458   PetscFunctionBegin;
4459   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4460   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4461   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4462   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4463   PetscFunctionReturn(0);
4464 }
4465 
4466 /*@C
4467    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4468    TS options in the database.
4469 
4470    Logically Collective on TS
4471 
4472    Input Parameter:
4473 +  ts     - The TS context
4474 -  prefix - The prefix to prepend to all option names
4475 
4476    Notes:
4477    A hyphen (-) must NOT be given at the beginning of the prefix name.
4478    The first character of all runtime options is AUTOMATICALLY the
4479    hyphen.
4480 
4481    Level: advanced
4482 
4483 .seealso: TSGetOptionsPrefix()
4484 
4485 @*/
4486 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
4487 {
4488   PetscErrorCode ierr;
4489   SNES           snes;
4490 
4491   PetscFunctionBegin;
4492   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4493   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4494   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4495   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4496   PetscFunctionReturn(0);
4497 }
4498 
4499 /*@C
4500    TSGetOptionsPrefix - Sets the prefix used for searching for all
4501    TS options in the database.
4502 
4503    Not Collective
4504 
4505    Input Parameter:
4506 .  ts - The TS context
4507 
4508    Output Parameter:
4509 .  prefix - A pointer to the prefix string used
4510 
4511    Notes:
4512     On the fortran side, the user should pass in a string 'prifix' of
4513    sufficient length to hold the prefix.
4514 
4515    Level: intermediate
4516 
4517 .seealso: TSAppendOptionsPrefix()
4518 @*/
4519 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
4520 {
4521   PetscErrorCode ierr;
4522 
4523   PetscFunctionBegin;
4524   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4525   PetscValidPointer(prefix,2);
4526   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4527   PetscFunctionReturn(0);
4528 }
4529 
4530 /*@C
4531    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4532 
4533    Not Collective, but parallel objects are returned if TS is parallel
4534 
4535    Input Parameter:
4536 .  ts  - The TS context obtained from TSCreate()
4537 
4538    Output Parameters:
4539 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
4540 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
4541 .  func - Function to compute the Jacobian of the RHS  (or NULL)
4542 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
4543 
4544    Notes:
4545     You can pass in NULL for any return argument you do not need.
4546 
4547    Level: intermediate
4548 
4549 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4550 
4551 @*/
4552 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
4553 {
4554   PetscErrorCode ierr;
4555   DM             dm;
4556 
4557   PetscFunctionBegin;
4558   if (Amat || Pmat) {
4559     SNES snes;
4560     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4561     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4562     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4563   }
4564   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4565   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
4566   PetscFunctionReturn(0);
4567 }
4568 
4569 /*@C
4570    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4571 
4572    Not Collective, but parallel objects are returned if TS is parallel
4573 
4574    Input Parameter:
4575 .  ts  - The TS context obtained from TSCreate()
4576 
4577    Output Parameters:
4578 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
4579 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
4580 .  f   - The function to compute the matrices
4581 - ctx - User-defined context for Jacobian evaluation routine
4582 
4583    Notes:
4584     You can pass in NULL for any return argument you do not need.
4585 
4586    Level: advanced
4587 
4588 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4589 
4590 @*/
4591 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
4592 {
4593   PetscErrorCode ierr;
4594   DM             dm;
4595 
4596   PetscFunctionBegin;
4597   if (Amat || Pmat) {
4598     SNES snes;
4599     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4600     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4601     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4602   }
4603   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4604   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
4605   PetscFunctionReturn(0);
4606 }
4607 
4608 /*@C
4609    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
4610    VecView() for the solution at each timestep
4611 
4612    Collective on TS
4613 
4614    Input Parameters:
4615 +  ts - the TS context
4616 .  step - current time-step
4617 .  ptime - current time
4618 -  dummy - either a viewer or NULL
4619 
4620    Options Database:
4621 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
4622 
4623    Notes:
4624     the initial solution and current solution are not display with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
4625        will look bad
4626 
4627    Level: intermediate
4628 
4629 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4630 @*/
4631 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4632 {
4633   PetscErrorCode   ierr;
4634   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
4635   PetscDraw        draw;
4636 
4637   PetscFunctionBegin;
4638   if (!step && ictx->showinitial) {
4639     if (!ictx->initialsolution) {
4640       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
4641     }
4642     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
4643   }
4644   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4645 
4646   if (ictx->showinitial) {
4647     PetscReal pause;
4648     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
4649     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
4650     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
4651     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
4652     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
4653   }
4654   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
4655   if (ictx->showtimestepandtime) {
4656     PetscReal xl,yl,xr,yr,h;
4657     char      time[32];
4658 
4659     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4660     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4661     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4662     h    = yl + .95*(yr - yl);
4663     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4664     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4665   }
4666 
4667   if (ictx->showinitial) {
4668     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
4669   }
4670   PetscFunctionReturn(0);
4671 }
4672 
4673 /*@C
4674    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
4675 
4676    Collective on TS
4677 
4678    Input Parameters:
4679 +  ts - the TS context
4680 .  step - current time-step
4681 .  ptime - current time
4682 -  dummy - either a viewer or NULL
4683 
4684    Level: intermediate
4685 
4686 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4687 @*/
4688 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4689 {
4690   PetscErrorCode    ierr;
4691   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
4692   PetscDraw         draw;
4693   PetscDrawAxis     axis;
4694   PetscInt          n;
4695   PetscMPIInt       size;
4696   PetscReal         U0,U1,xl,yl,xr,yr,h;
4697   char              time[32];
4698   const PetscScalar *U;
4699 
4700   PetscFunctionBegin;
4701   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)ts),&size);CHKERRQ(ierr);
4702   if (size != 1) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only allowed for sequential runs");
4703   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
4704   if (n != 2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only for ODEs with two unknowns");
4705 
4706   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
4707   ierr = PetscViewerDrawGetDrawAxis(ictx->viewer,0,&axis);CHKERRQ(ierr);
4708   ierr = PetscDrawAxisGetLimits(axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
4709   if (!step) {
4710     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
4711     ierr = PetscDrawAxisDraw(axis);CHKERRQ(ierr);
4712   }
4713 
4714   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
4715   U0 = PetscRealPart(U[0]);
4716   U1 = PetscRealPart(U[1]);
4717   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
4718   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(0);
4719 
4720   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
4721   ierr = PetscDrawPoint(draw,U0,U1,PETSC_DRAW_BLACK);CHKERRQ(ierr);
4722   if (ictx->showtimestepandtime) {
4723     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
4724     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
4725     h    = yl + .95*(yr - yl);
4726     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
4727   }
4728   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
4729   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
4730   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
4731   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
4732   PetscFunctionReturn(0);
4733 }
4734 
4735 /*@C
4736    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
4737 
4738    Collective on TS
4739 
4740    Input Parameters:
4741 .    ctx - the monitor context
4742 
4743    Level: intermediate
4744 
4745 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
4746 @*/
4747 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
4748 {
4749   PetscErrorCode ierr;
4750 
4751   PetscFunctionBegin;
4752   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
4753   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
4754   ierr = PetscFree(*ictx);CHKERRQ(ierr);
4755   PetscFunctionReturn(0);
4756 }
4757 
4758 /*@C
4759    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
4760 
4761    Collective on TS
4762 
4763    Input Parameter:
4764 .    ts - time-step context
4765 
4766    Output Patameter:
4767 .    ctx - the monitor context
4768 
4769    Options Database:
4770 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
4771 
4772    Level: intermediate
4773 
4774 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
4775 @*/
4776 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
4777 {
4778   PetscErrorCode   ierr;
4779 
4780   PetscFunctionBegin;
4781   ierr = PetscNew(ctx);CHKERRQ(ierr);
4782   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
4783   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
4784 
4785   (*ctx)->howoften    = howoften;
4786   (*ctx)->showinitial = PETSC_FALSE;
4787   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
4788 
4789   (*ctx)->showtimestepandtime = PETSC_FALSE;
4790   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
4791   PetscFunctionReturn(0);
4792 }
4793 
4794 /*@C
4795    TSMonitorDrawSolutionFunction - Monitors progress of the TS solvers by calling
4796    VecView() for the solution provided by TSSetSolutionFunction() at each timestep
4797 
4798    Collective on TS
4799 
4800    Input Parameters:
4801 +  ts - the TS context
4802 .  step - current time-step
4803 .  ptime - current time
4804 -  dummy - either a viewer or NULL
4805 
4806    Options Database:
4807 .  -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
4808 
4809    Level: intermediate
4810 
4811 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4812 @*/
4813 PetscErrorCode  TSMonitorDrawSolutionFunction(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4814 {
4815   PetscErrorCode   ierr;
4816   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
4817   PetscViewer      viewer = ctx->viewer;
4818   Vec              work;
4819 
4820   PetscFunctionBegin;
4821   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4822   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
4823   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
4824   ierr = VecView(work,viewer);CHKERRQ(ierr);
4825   ierr = VecDestroy(&work);CHKERRQ(ierr);
4826   PetscFunctionReturn(0);
4827 }
4828 
4829 /*@C
4830    TSMonitorDrawError - Monitors progress of the TS solvers by calling
4831    VecView() for the error at each timestep
4832 
4833    Collective on TS
4834 
4835    Input Parameters:
4836 +  ts - the TS context
4837 .  step - current time-step
4838 .  ptime - current time
4839 -  dummy - either a viewer or NULL
4840 
4841    Options Database:
4842 .  -ts_monitor_draw_error - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
4843 
4844    Level: intermediate
4845 
4846 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4847 @*/
4848 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4849 {
4850   PetscErrorCode   ierr;
4851   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
4852   PetscViewer      viewer = ctx->viewer;
4853   Vec              work;
4854 
4855   PetscFunctionBegin;
4856   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
4857   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
4858   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
4859   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
4860   ierr = VecView(work,viewer);CHKERRQ(ierr);
4861   ierr = VecDestroy(&work);CHKERRQ(ierr);
4862   PetscFunctionReturn(0);
4863 }
4864 
4865 #include <petsc/private/dmimpl.h>
4866 /*@
4867    TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS
4868 
4869    Logically Collective on ts
4870 
4871    Input Parameters:
4872 +  ts - the ODE integrator object
4873 -  dm - the dm, cannot be NULL
4874 
4875    Notes:
4876    A DM can only be used for solving one problem at a time because information about the problem is stored on the DM,
4877    even when not using interfaces like DMTSSetIFunction().  Use DMClone() to get a distinct DM when solving
4878    different problems using the same function space.
4879 
4880    Level: intermediate
4881 
4882 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
4883 @*/
4884 PetscErrorCode  TSSetDM(TS ts,DM dm)
4885 {
4886   PetscErrorCode ierr;
4887   SNES           snes;
4888   DMTS           tsdm;
4889 
4890   PetscFunctionBegin;
4891   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4892   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
4893   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
4894   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
4895     if (ts->dm->dmts && !dm->dmts) {
4896       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
4897       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
4898       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
4899         tsdm->originaldm = dm;
4900       }
4901     }
4902     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
4903   }
4904   ts->dm = dm;
4905 
4906   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4907   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
4908   PetscFunctionReturn(0);
4909 }
4910 
4911 /*@
4912    TSGetDM - Gets the DM that may be used by some preconditioners
4913 
4914    Not Collective
4915 
4916    Input Parameter:
4917 . ts - the preconditioner context
4918 
4919    Output Parameter:
4920 .  dm - the dm
4921 
4922    Level: intermediate
4923 
4924 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
4925 @*/
4926 PetscErrorCode  TSGetDM(TS ts,DM *dm)
4927 {
4928   PetscErrorCode ierr;
4929 
4930   PetscFunctionBegin;
4931   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4932   if (!ts->dm) {
4933     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
4934     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
4935   }
4936   *dm = ts->dm;
4937   PetscFunctionReturn(0);
4938 }
4939 
4940 /*@
4941    SNESTSFormFunction - Function to evaluate nonlinear residual
4942 
4943    Logically Collective on SNES
4944 
4945    Input Parameter:
4946 + snes - nonlinear solver
4947 . U - the current state at which to evaluate the residual
4948 - ctx - user context, must be a TS
4949 
4950    Output Parameter:
4951 . F - the nonlinear residual
4952 
4953    Notes:
4954    This function is not normally called by users and is automatically registered with the SNES used by TS.
4955    It is most frequently passed to MatFDColoringSetFunction().
4956 
4957    Level: advanced
4958 
4959 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
4960 @*/
4961 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
4962 {
4963   TS             ts = (TS)ctx;
4964   PetscErrorCode ierr;
4965 
4966   PetscFunctionBegin;
4967   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4968   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
4969   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
4970   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
4971   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
4972   PetscFunctionReturn(0);
4973 }
4974 
4975 /*@
4976    SNESTSFormJacobian - Function to evaluate the Jacobian
4977 
4978    Collective on SNES
4979 
4980    Input Parameter:
4981 + snes - nonlinear solver
4982 . U - the current state at which to evaluate the residual
4983 - ctx - user context, must be a TS
4984 
4985    Output Parameter:
4986 + A - the Jacobian
4987 . B - the preconditioning matrix (may be the same as A)
4988 - flag - indicates any structure change in the matrix
4989 
4990    Notes:
4991    This function is not normally called by users and is automatically registered with the SNES used by TS.
4992 
4993    Level: developer
4994 
4995 .seealso: SNESSetJacobian()
4996 @*/
4997 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
4998 {
4999   TS             ts = (TS)ctx;
5000   PetscErrorCode ierr;
5001 
5002   PetscFunctionBegin;
5003   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
5004   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5005   PetscValidPointer(A,3);
5006   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
5007   PetscValidPointer(B,4);
5008   PetscValidHeaderSpecific(B,MAT_CLASSID,4);
5009   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
5010   ierr = (ts->ops->snesjacobian)(snes,U,A,B,ts);CHKERRQ(ierr);
5011   PetscFunctionReturn(0);
5012 }
5013 
5014 /*@C
5015    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only
5016 
5017    Collective on TS
5018 
5019    Input Arguments:
5020 +  ts - time stepping context
5021 .  t - time at which to evaluate
5022 .  U - state at which to evaluate
5023 -  ctx - context
5024 
5025    Output Arguments:
5026 .  F - right hand side
5027 
5028    Level: intermediate
5029 
5030    Notes:
5031    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
5032    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
5033 
5034 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
5035 @*/
5036 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
5037 {
5038   PetscErrorCode ierr;
5039   Mat            Arhs,Brhs;
5040 
5041   PetscFunctionBegin;
5042   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
5043   ierr = TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);CHKERRQ(ierr);
5044   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
5045   PetscFunctionReturn(0);
5046 }
5047 
5048 /*@C
5049    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
5050 
5051    Collective on TS
5052 
5053    Input Arguments:
5054 +  ts - time stepping context
5055 .  t - time at which to evaluate
5056 .  U - state at which to evaluate
5057 -  ctx - context
5058 
5059    Output Arguments:
5060 +  A - pointer to operator
5061 .  B - pointer to preconditioning matrix
5062 -  flg - matrix structure flag
5063 
5064    Level: intermediate
5065 
5066    Notes:
5067    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
5068 
5069 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
5070 @*/
5071 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
5072 {
5073   PetscFunctionBegin;
5074   PetscFunctionReturn(0);
5075 }
5076 
5077 /*@C
5078    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
5079 
5080    Collective on TS
5081 
5082    Input Arguments:
5083 +  ts - time stepping context
5084 .  t - time at which to evaluate
5085 .  U - state at which to evaluate
5086 .  Udot - time derivative of state vector
5087 -  ctx - context
5088 
5089    Output Arguments:
5090 .  F - left hand side
5091 
5092    Level: intermediate
5093 
5094    Notes:
5095    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
5096    user is required to write their own TSComputeIFunction.
5097    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
5098    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
5099 
5100    Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U
5101 
5102 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant(), TSComputeRHSFunctionLinear()
5103 @*/
5104 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
5105 {
5106   PetscErrorCode ierr;
5107   Mat            A,B;
5108 
5109   PetscFunctionBegin;
5110   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
5111   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE);CHKERRQ(ierr);
5112   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
5113   PetscFunctionReturn(0);
5114 }
5115 
5116 /*@C
5117    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
5118 
5119    Collective on TS
5120 
5121    Input Arguments:
5122 +  ts - time stepping context
5123 .  t - time at which to evaluate
5124 .  U - state at which to evaluate
5125 .  Udot - time derivative of state vector
5126 .  shift - shift to apply
5127 -  ctx - context
5128 
5129    Output Arguments:
5130 +  A - pointer to operator
5131 .  B - pointer to preconditioning matrix
5132 -  flg - matrix structure flag
5133 
5134    Level: advanced
5135 
5136    Notes:
5137    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
5138 
5139    It is only appropriate for problems of the form
5140 
5141 $     M Udot = F(U,t)
5142 
5143   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
5144   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
5145   an implicit operator of the form
5146 
5147 $    shift*M + J
5148 
5149   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
5150   a copy of M or reassemble it when requested.
5151 
5152 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
5153 @*/
5154 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
5155 {
5156   PetscErrorCode ierr;
5157 
5158   PetscFunctionBegin;
5159   ierr = MatScale(A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
5160   ts->ijacobian.shift = shift;
5161   PetscFunctionReturn(0);
5162 }
5163 
5164 /*@
5165    TSGetEquationType - Gets the type of the equation that TS is solving.
5166 
5167    Not Collective
5168 
5169    Input Parameter:
5170 .  ts - the TS context
5171 
5172    Output Parameter:
5173 .  equation_type - see TSEquationType
5174 
5175    Level: beginner
5176 
5177 .seealso: TSSetEquationType(), TSEquationType
5178 @*/
5179 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
5180 {
5181   PetscFunctionBegin;
5182   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5183   PetscValidPointer(equation_type,2);
5184   *equation_type = ts->equation_type;
5185   PetscFunctionReturn(0);
5186 }
5187 
5188 /*@
5189    TSSetEquationType - Sets the type of the equation that TS is solving.
5190 
5191    Not Collective
5192 
5193    Input Parameter:
5194 +  ts - the TS context
5195 -  equation_type - see TSEquationType
5196 
5197    Level: advanced
5198 
5199 .seealso: TSGetEquationType(), TSEquationType
5200 @*/
5201 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
5202 {
5203   PetscFunctionBegin;
5204   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5205   ts->equation_type = equation_type;
5206   PetscFunctionReturn(0);
5207 }
5208 
5209 /*@
5210    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
5211 
5212    Not Collective
5213 
5214    Input Parameter:
5215 .  ts - the TS context
5216 
5217    Output Parameter:
5218 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5219             manual pages for the individual convergence tests for complete lists
5220 
5221    Level: beginner
5222 
5223    Notes:
5224    Can only be called after the call to TSSolve() is complete.
5225 
5226 .seealso: TSSetConvergenceTest(), TSConvergedReason
5227 @*/
5228 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
5229 {
5230   PetscFunctionBegin;
5231   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5232   PetscValidPointer(reason,2);
5233   *reason = ts->reason;
5234   PetscFunctionReturn(0);
5235 }
5236 
5237 /*@
5238    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
5239 
5240    Logically Collective; reason must contain common value
5241 
5242    Input Parameters:
5243 +  ts - the TS context
5244 -  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5245             manual pages for the individual convergence tests for complete lists
5246 
5247    Level: advanced
5248 
5249    Notes:
5250    Can only be called while TSSolve() is active.
5251 
5252 .seealso: TSConvergedReason
5253 @*/
5254 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
5255 {
5256   PetscFunctionBegin;
5257   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5258   ts->reason = reason;
5259   PetscFunctionReturn(0);
5260 }
5261 
5262 /*@
5263    TSGetSolveTime - Gets the time after a call to TSSolve()
5264 
5265    Not Collective
5266 
5267    Input Parameter:
5268 .  ts - the TS context
5269 
5270    Output Parameter:
5271 .  ftime - the final time. This time corresponds to the final time set with TSSetMaxTime()
5272 
5273    Level: beginner
5274 
5275    Notes:
5276    Can only be called after the call to TSSolve() is complete.
5277 
5278 .seealso: TSSetConvergenceTest(), TSConvergedReason
5279 @*/
5280 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
5281 {
5282   PetscFunctionBegin;
5283   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5284   PetscValidPointer(ftime,2);
5285   *ftime = ts->solvetime;
5286   PetscFunctionReturn(0);
5287 }
5288 
5289 /*@
5290    TSGetSNESIterations - Gets the total number of nonlinear iterations
5291    used by the time integrator.
5292 
5293    Not Collective
5294 
5295    Input Parameter:
5296 .  ts - TS context
5297 
5298    Output Parameter:
5299 .  nits - number of nonlinear iterations
5300 
5301    Notes:
5302    This counter is reset to zero for each successive call to TSSolve().
5303 
5304    Level: intermediate
5305 
5306 .seealso:  TSGetKSPIterations()
5307 @*/
5308 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
5309 {
5310   PetscFunctionBegin;
5311   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5312   PetscValidIntPointer(nits,2);
5313   *nits = ts->snes_its;
5314   PetscFunctionReturn(0);
5315 }
5316 
5317 /*@
5318    TSGetKSPIterations - Gets the total number of linear iterations
5319    used by the time integrator.
5320 
5321    Not Collective
5322 
5323    Input Parameter:
5324 .  ts - TS context
5325 
5326    Output Parameter:
5327 .  lits - number of linear iterations
5328 
5329    Notes:
5330    This counter is reset to zero for each successive call to TSSolve().
5331 
5332    Level: intermediate
5333 
5334 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
5335 @*/
5336 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
5337 {
5338   PetscFunctionBegin;
5339   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5340   PetscValidIntPointer(lits,2);
5341   *lits = ts->ksp_its;
5342   PetscFunctionReturn(0);
5343 }
5344 
5345 /*@
5346    TSGetStepRejections - Gets the total number of rejected steps.
5347 
5348    Not Collective
5349 
5350    Input Parameter:
5351 .  ts - TS context
5352 
5353    Output Parameter:
5354 .  rejects - number of steps rejected
5355 
5356    Notes:
5357    This counter is reset to zero for each successive call to TSSolve().
5358 
5359    Level: intermediate
5360 
5361 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
5362 @*/
5363 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
5364 {
5365   PetscFunctionBegin;
5366   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5367   PetscValidIntPointer(rejects,2);
5368   *rejects = ts->reject;
5369   PetscFunctionReturn(0);
5370 }
5371 
5372 /*@
5373    TSGetSNESFailures - Gets the total number of failed SNES solves
5374 
5375    Not Collective
5376 
5377    Input Parameter:
5378 .  ts - TS context
5379 
5380    Output Parameter:
5381 .  fails - number of failed nonlinear solves
5382 
5383    Notes:
5384    This counter is reset to zero for each successive call to TSSolve().
5385 
5386    Level: intermediate
5387 
5388 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
5389 @*/
5390 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
5391 {
5392   PetscFunctionBegin;
5393   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5394   PetscValidIntPointer(fails,2);
5395   *fails = ts->num_snes_failures;
5396   PetscFunctionReturn(0);
5397 }
5398 
5399 /*@
5400    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
5401 
5402    Not Collective
5403 
5404    Input Parameter:
5405 +  ts - TS context
5406 -  rejects - maximum number of rejected steps, pass -1 for unlimited
5407 
5408    Notes:
5409    The counter is reset to zero for each step
5410 
5411    Options Database Key:
5412  .  -ts_max_reject - Maximum number of step rejections before a step fails
5413 
5414    Level: intermediate
5415 
5416 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5417 @*/
5418 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
5419 {
5420   PetscFunctionBegin;
5421   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5422   ts->max_reject = rejects;
5423   PetscFunctionReturn(0);
5424 }
5425 
5426 /*@
5427    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
5428 
5429    Not Collective
5430 
5431    Input Parameter:
5432 +  ts - TS context
5433 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
5434 
5435    Notes:
5436    The counter is reset to zero for each successive call to TSSolve().
5437 
5438    Options Database Key:
5439  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
5440 
5441    Level: intermediate
5442 
5443 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
5444 @*/
5445 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
5446 {
5447   PetscFunctionBegin;
5448   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5449   ts->max_snes_failures = fails;
5450   PetscFunctionReturn(0);
5451 }
5452 
5453 /*@
5454    TSSetErrorIfStepFails - Error if no step succeeds
5455 
5456    Not Collective
5457 
5458    Input Parameter:
5459 +  ts - TS context
5460 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
5461 
5462    Options Database Key:
5463  .  -ts_error_if_step_fails - Error if no step succeeds
5464 
5465    Level: intermediate
5466 
5467 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5468 @*/
5469 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
5470 {
5471   PetscFunctionBegin;
5472   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5473   ts->errorifstepfailed = err;
5474   PetscFunctionReturn(0);
5475 }
5476 
5477 /*@C
5478    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
5479 
5480    Collective on TS
5481 
5482    Input Parameters:
5483 +  ts - the TS context
5484 .  step - current time-step
5485 .  ptime - current time
5486 .  u - current state
5487 -  vf - viewer and its format
5488 
5489    Level: intermediate
5490 
5491 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5492 @*/
5493 PetscErrorCode  TSMonitorSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
5494 {
5495   PetscErrorCode ierr;
5496 
5497   PetscFunctionBegin;
5498   ierr = PetscViewerPushFormat(vf->viewer,vf->format);CHKERRQ(ierr);
5499   ierr = VecView(u,vf->viewer);CHKERRQ(ierr);
5500   ierr = PetscViewerPopFormat(vf->viewer);CHKERRQ(ierr);
5501   PetscFunctionReturn(0);
5502 }
5503 
5504 /*@C
5505    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
5506 
5507    Collective on TS
5508 
5509    Input Parameters:
5510 +  ts - the TS context
5511 .  step - current time-step
5512 .  ptime - current time
5513 .  u - current state
5514 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5515 
5516    Level: intermediate
5517 
5518    Notes:
5519    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.
5520    These are named according to the file name template.
5521 
5522    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
5523 
5524 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5525 @*/
5526 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
5527 {
5528   PetscErrorCode ierr;
5529   char           filename[PETSC_MAX_PATH_LEN];
5530   PetscViewer    viewer;
5531 
5532   PetscFunctionBegin;
5533   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
5534   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
5535   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
5536   ierr = VecView(u,viewer);CHKERRQ(ierr);
5537   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5538   PetscFunctionReturn(0);
5539 }
5540 
5541 /*@C
5542    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
5543 
5544    Collective on TS
5545 
5546    Input Parameters:
5547 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5548 
5549    Level: intermediate
5550 
5551    Note:
5552    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
5553 
5554 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
5555 @*/
5556 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
5557 {
5558   PetscErrorCode ierr;
5559 
5560   PetscFunctionBegin;
5561   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
5562   PetscFunctionReturn(0);
5563 }
5564 
5565 /*@
5566    TSGetAdapt - Get the adaptive controller context for the current method
5567 
5568    Collective on TS if controller has not been created yet
5569 
5570    Input Arguments:
5571 .  ts - time stepping context
5572 
5573    Output Arguments:
5574 .  adapt - adaptive controller
5575 
5576    Level: intermediate
5577 
5578 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
5579 @*/
5580 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
5581 {
5582   PetscErrorCode ierr;
5583 
5584   PetscFunctionBegin;
5585   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5586   PetscValidPointer(adapt,2);
5587   if (!ts->adapt) {
5588     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
5589     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt);CHKERRQ(ierr);
5590     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
5591   }
5592   *adapt = ts->adapt;
5593   PetscFunctionReturn(0);
5594 }
5595 
5596 /*@
5597    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
5598 
5599    Logically Collective
5600 
5601    Input Arguments:
5602 +  ts - time integration context
5603 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
5604 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
5605 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
5606 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
5607 
5608    Options Database keys:
5609 +  -ts_rtol <rtol> - relative tolerance for local truncation error
5610 -  -ts_atol <atol> Absolute tolerance for local truncation error
5611 
5612    Notes:
5613    With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
5614    (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
5615    computed only for the differential or the algebraic part then this can be done using the vector of
5616    tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
5617    differential part and infinity for the algebraic part, the LTE calculation will include only the
5618    differential variables.
5619 
5620    Level: beginner
5621 
5622 .seealso: TS, TSAdapt, TSErrorWeightedNorm(), TSGetTolerances()
5623 @*/
5624 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
5625 {
5626   PetscErrorCode ierr;
5627 
5628   PetscFunctionBegin;
5629   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
5630   if (vatol) {
5631     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
5632     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
5633     ts->vatol = vatol;
5634   }
5635   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
5636   if (vrtol) {
5637     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
5638     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
5639     ts->vrtol = vrtol;
5640   }
5641   PetscFunctionReturn(0);
5642 }
5643 
5644 /*@
5645    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
5646 
5647    Logically Collective
5648 
5649    Input Arguments:
5650 .  ts - time integration context
5651 
5652    Output Arguments:
5653 +  atol - scalar absolute tolerances, NULL to ignore
5654 .  vatol - vector of absolute tolerances, NULL to ignore
5655 .  rtol - scalar relative tolerances, NULL to ignore
5656 -  vrtol - vector of relative tolerances, NULL to ignore
5657 
5658    Level: beginner
5659 
5660 .seealso: TS, TSAdapt, TSErrorWeightedNorm(), TSSetTolerances()
5661 @*/
5662 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
5663 {
5664   PetscFunctionBegin;
5665   if (atol)  *atol  = ts->atol;
5666   if (vatol) *vatol = ts->vatol;
5667   if (rtol)  *rtol  = ts->rtol;
5668   if (vrtol) *vrtol = ts->vrtol;
5669   PetscFunctionReturn(0);
5670 }
5671 
5672 /*@
5673    TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors
5674 
5675    Collective on TS
5676 
5677    Input Arguments:
5678 +  ts - time stepping context
5679 .  U - state vector, usually ts->vec_sol
5680 -  Y - state vector to be compared to U
5681 
5682    Output Arguments:
5683 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5684 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5685 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5686 
5687    Level: developer
5688 
5689 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNormInfinity()
5690 @*/
5691 PetscErrorCode TSErrorWeightedNorm2(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5692 {
5693   PetscErrorCode    ierr;
5694   PetscInt          i,n,N,rstart;
5695   PetscInt          n_loc,na_loc,nr_loc;
5696   PetscReal         n_glb,na_glb,nr_glb;
5697   const PetscScalar *u,*y;
5698   PetscReal         sum,suma,sumr,gsum,gsuma,gsumr,diff;
5699   PetscReal         tol,tola,tolr;
5700   PetscReal         err_loc[6],err_glb[6];
5701 
5702   PetscFunctionBegin;
5703   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5704   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5705   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
5706   PetscValidType(U,2);
5707   PetscValidType(Y,3);
5708   PetscCheckSameComm(U,2,Y,3);
5709   PetscValidPointer(norm,4);
5710   PetscValidPointer(norma,5);
5711   PetscValidPointer(normr,6);
5712   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
5713 
5714   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
5715   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
5716   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
5717   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5718   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5719   sum  = 0.; n_loc  = 0;
5720   suma = 0.; na_loc = 0;
5721   sumr = 0.; nr_loc = 0;
5722   if (ts->vatol && ts->vrtol) {
5723     const PetscScalar *atol,*rtol;
5724     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5725     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5726     for (i=0; i<n; i++) {
5727       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5728       diff = PetscAbsScalar(y[i] - u[i]);
5729       tola = PetscRealPart(atol[i]);
5730       if(tola>0.){
5731         suma  += PetscSqr(diff/tola);
5732         na_loc++;
5733       }
5734       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5735       if(tolr>0.){
5736         sumr  += PetscSqr(diff/tolr);
5737         nr_loc++;
5738       }
5739       tol=tola+tolr;
5740       if(tol>0.){
5741         sum  += PetscSqr(diff/tol);
5742         n_loc++;
5743       }
5744     }
5745     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5746     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5747   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5748     const PetscScalar *atol;
5749     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5750     for (i=0; i<n; i++) {
5751       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5752       diff = PetscAbsScalar(y[i] - u[i]);
5753       tola = PetscRealPart(atol[i]);
5754       if(tola>0.){
5755         suma  += PetscSqr(diff/tola);
5756         na_loc++;
5757       }
5758       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5759       if(tolr>0.){
5760         sumr  += PetscSqr(diff/tolr);
5761         nr_loc++;
5762       }
5763       tol=tola+tolr;
5764       if(tol>0.){
5765         sum  += PetscSqr(diff/tol);
5766         n_loc++;
5767       }
5768     }
5769     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5770   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5771     const PetscScalar *rtol;
5772     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5773     for (i=0; i<n; i++) {
5774       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5775       diff = PetscAbsScalar(y[i] - u[i]);
5776       tola = ts->atol;
5777       if(tola>0.){
5778         suma  += PetscSqr(diff/tola);
5779         na_loc++;
5780       }
5781       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5782       if(tolr>0.){
5783         sumr  += PetscSqr(diff/tolr);
5784         nr_loc++;
5785       }
5786       tol=tola+tolr;
5787       if(tol>0.){
5788         sum  += PetscSqr(diff/tol);
5789         n_loc++;
5790       }
5791     }
5792     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5793   } else {                      /* scalar atol, scalar rtol */
5794     for (i=0; i<n; i++) {
5795       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5796       diff = PetscAbsScalar(y[i] - u[i]);
5797       tola = ts->atol;
5798       if(tola>0.){
5799         suma  += PetscSqr(diff/tola);
5800         na_loc++;
5801       }
5802       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5803       if(tolr>0.){
5804         sumr  += PetscSqr(diff/tolr);
5805         nr_loc++;
5806       }
5807       tol=tola+tolr;
5808       if(tol>0.){
5809         sum  += PetscSqr(diff/tol);
5810         n_loc++;
5811       }
5812     }
5813   }
5814   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5815   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5816 
5817   err_loc[0] = sum;
5818   err_loc[1] = suma;
5819   err_loc[2] = sumr;
5820   err_loc[3] = (PetscReal)n_loc;
5821   err_loc[4] = (PetscReal)na_loc;
5822   err_loc[5] = (PetscReal)nr_loc;
5823 
5824   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5825 
5826   gsum   = err_glb[0];
5827   gsuma  = err_glb[1];
5828   gsumr  = err_glb[2];
5829   n_glb  = err_glb[3];
5830   na_glb = err_glb[4];
5831   nr_glb = err_glb[5];
5832 
5833   *norm  = 0.;
5834   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
5835   *norma = 0.;
5836   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
5837   *normr = 0.;
5838   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
5839 
5840   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5841   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5842   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5843   PetscFunctionReturn(0);
5844 }
5845 
5846 /*@
5847    TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors
5848 
5849    Collective on TS
5850 
5851    Input Arguments:
5852 +  ts - time stepping context
5853 .  U - state vector, usually ts->vec_sol
5854 -  Y - state vector to be compared to U
5855 
5856    Output Arguments:
5857 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
5858 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
5859 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
5860 
5861    Level: developer
5862 
5863 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNorm2()
5864 @*/
5865 PetscErrorCode TSErrorWeightedNormInfinity(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
5866 {
5867   PetscErrorCode    ierr;
5868   PetscInt          i,n,N,rstart;
5869   const PetscScalar *u,*y;
5870   PetscReal         max,gmax,maxa,gmaxa,maxr,gmaxr;
5871   PetscReal         tol,tola,tolr,diff;
5872   PetscReal         err_loc[3],err_glb[3];
5873 
5874   PetscFunctionBegin;
5875   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5876   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5877   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
5878   PetscValidType(U,2);
5879   PetscValidType(Y,3);
5880   PetscCheckSameComm(U,2,Y,3);
5881   PetscValidPointer(norm,4);
5882   PetscValidPointer(norma,5);
5883   PetscValidPointer(normr,6);
5884   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
5885 
5886   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
5887   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
5888   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
5889   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
5890   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
5891 
5892   max=0.;
5893   maxa=0.;
5894   maxr=0.;
5895 
5896   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
5897     const PetscScalar *atol,*rtol;
5898     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5899     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5900 
5901     for (i=0; i<n; i++) {
5902       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5903       diff = PetscAbsScalar(y[i] - u[i]);
5904       tola = PetscRealPart(atol[i]);
5905       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5906       tol  = tola+tolr;
5907       if(tola>0.){
5908         maxa = PetscMax(maxa,diff / tola);
5909       }
5910       if(tolr>0.){
5911         maxr = PetscMax(maxr,diff / tolr);
5912       }
5913       if(tol>0.){
5914         max = PetscMax(max,diff / tol);
5915       }
5916     }
5917     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5918     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5919   } else if (ts->vatol) {       /* vector atol, scalar rtol */
5920     const PetscScalar *atol;
5921     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5922     for (i=0; i<n; i++) {
5923       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5924       diff = PetscAbsScalar(y[i] - u[i]);
5925       tola = PetscRealPart(atol[i]);
5926       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5927       tol  = tola+tolr;
5928       if(tola>0.){
5929         maxa = PetscMax(maxa,diff / tola);
5930       }
5931       if(tolr>0.){
5932         maxr = PetscMax(maxr,diff / tolr);
5933       }
5934       if(tol>0.){
5935         max = PetscMax(max,diff / tol);
5936       }
5937     }
5938     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
5939   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
5940     const PetscScalar *rtol;
5941     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5942 
5943     for (i=0; i<n; i++) {
5944       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5945       diff = PetscAbsScalar(y[i] - u[i]);
5946       tola = ts->atol;
5947       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5948       tol  = tola+tolr;
5949       if(tola>0.){
5950         maxa = PetscMax(maxa,diff / tola);
5951       }
5952       if(tolr>0.){
5953         maxr = PetscMax(maxr,diff / tolr);
5954       }
5955       if(tol>0.){
5956         max = PetscMax(max,diff / tol);
5957       }
5958     }
5959     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
5960   } else {                      /* scalar atol, scalar rtol */
5961 
5962     for (i=0; i<n; i++) {
5963       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
5964       diff = PetscAbsScalar(y[i] - u[i]);
5965       tola = ts->atol;
5966       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
5967       tol  = tola+tolr;
5968       if(tola>0.){
5969         maxa = PetscMax(maxa,diff / tola);
5970       }
5971       if(tolr>0.){
5972         maxr = PetscMax(maxr,diff / tolr);
5973       }
5974       if(tol>0.){
5975         max = PetscMax(max,diff / tol);
5976       }
5977     }
5978   }
5979   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
5980   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
5981   err_loc[0] = max;
5982   err_loc[1] = maxa;
5983   err_loc[2] = maxr;
5984   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
5985   gmax   = err_glb[0];
5986   gmaxa  = err_glb[1];
5987   gmaxr  = err_glb[2];
5988 
5989   *norm = gmax;
5990   *norma = gmaxa;
5991   *normr = gmaxr;
5992   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
5993     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
5994     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
5995   PetscFunctionReturn(0);
5996 }
5997 
5998 /*@
5999    TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
6000 
6001    Collective on TS
6002 
6003    Input Arguments:
6004 +  ts - time stepping context
6005 .  U - state vector, usually ts->vec_sol
6006 .  Y - state vector to be compared to U
6007 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6008 
6009    Output Arguments:
6010 +  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6011 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6012 -  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6013 
6014    Options Database Keys:
6015 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6016 
6017    Level: developer
6018 
6019 .seealso: TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2(), TSErrorWeightedENorm
6020 @*/
6021 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6022 {
6023   PetscErrorCode ierr;
6024 
6025   PetscFunctionBegin;
6026   if (wnormtype == NORM_2) {
6027     ierr = TSErrorWeightedNorm2(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
6028   } else if(wnormtype == NORM_INFINITY) {
6029     ierr = TSErrorWeightedNormInfinity(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
6030   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6031   PetscFunctionReturn(0);
6032 }
6033 
6034 
6035 /*@
6036    TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances
6037 
6038    Collective on TS
6039 
6040    Input Arguments:
6041 +  ts - time stepping context
6042 .  E - error vector
6043 .  U - state vector, usually ts->vec_sol
6044 -  Y - state vector, previous time step
6045 
6046    Output Arguments:
6047 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6048 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6049 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6050 
6051    Level: developer
6052 
6053 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENormInfinity()
6054 @*/
6055 PetscErrorCode TSErrorWeightedENorm2(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6056 {
6057   PetscErrorCode    ierr;
6058   PetscInt          i,n,N,rstart;
6059   PetscInt          n_loc,na_loc,nr_loc;
6060   PetscReal         n_glb,na_glb,nr_glb;
6061   const PetscScalar *e,*u,*y;
6062   PetscReal         err,sum,suma,sumr,gsum,gsuma,gsumr;
6063   PetscReal         tol,tola,tolr;
6064   PetscReal         err_loc[6],err_glb[6];
6065 
6066   PetscFunctionBegin;
6067   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6068   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
6069   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
6070   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
6071   PetscValidType(E,2);
6072   PetscValidType(U,3);
6073   PetscValidType(Y,4);
6074   PetscCheckSameComm(E,2,U,3);
6075   PetscCheckSameComm(U,2,Y,3);
6076   PetscValidPointer(norm,5);
6077   PetscValidPointer(norma,6);
6078   PetscValidPointer(normr,7);
6079 
6080   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
6081   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
6082   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
6083   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
6084   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6085   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6086   sum  = 0.; n_loc  = 0;
6087   suma = 0.; na_loc = 0;
6088   sumr = 0.; nr_loc = 0;
6089   if (ts->vatol && ts->vrtol) {
6090     const PetscScalar *atol,*rtol;
6091     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6092     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6093     for (i=0; i<n; i++) {
6094       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
6095       err = PetscAbsScalar(e[i]);
6096       tola = PetscRealPart(atol[i]);
6097       if(tola>0.){
6098         suma  += PetscSqr(err/tola);
6099         na_loc++;
6100       }
6101       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6102       if(tolr>0.){
6103         sumr  += PetscSqr(err/tolr);
6104         nr_loc++;
6105       }
6106       tol=tola+tolr;
6107       if(tol>0.){
6108         sum  += PetscSqr(err/tol);
6109         n_loc++;
6110       }
6111     }
6112     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6113     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6114   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6115     const PetscScalar *atol;
6116     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6117     for (i=0; i<n; i++) {
6118       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
6119       err = PetscAbsScalar(e[i]);
6120       tola = PetscRealPart(atol[i]);
6121       if(tola>0.){
6122         suma  += PetscSqr(err/tola);
6123         na_loc++;
6124       }
6125       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6126       if(tolr>0.){
6127         sumr  += PetscSqr(err/tolr);
6128         nr_loc++;
6129       }
6130       tol=tola+tolr;
6131       if(tol>0.){
6132         sum  += PetscSqr(err/tol);
6133         n_loc++;
6134       }
6135     }
6136     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6137   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6138     const PetscScalar *rtol;
6139     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6140     for (i=0; i<n; i++) {
6141       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
6142       err = PetscAbsScalar(e[i]);
6143       tola = ts->atol;
6144       if(tola>0.){
6145         suma  += PetscSqr(err/tola);
6146         na_loc++;
6147       }
6148       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6149       if(tolr>0.){
6150         sumr  += PetscSqr(err/tolr);
6151         nr_loc++;
6152       }
6153       tol=tola+tolr;
6154       if(tol>0.){
6155         sum  += PetscSqr(err/tol);
6156         n_loc++;
6157       }
6158     }
6159     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6160   } else {                      /* scalar atol, scalar rtol */
6161     for (i=0; i<n; i++) {
6162       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
6163       err = PetscAbsScalar(e[i]);
6164       tola = ts->atol;
6165       if(tola>0.){
6166         suma  += PetscSqr(err/tola);
6167         na_loc++;
6168       }
6169       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6170       if(tolr>0.){
6171         sumr  += PetscSqr(err/tolr);
6172         nr_loc++;
6173       }
6174       tol=tola+tolr;
6175       if(tol>0.){
6176         sum  += PetscSqr(err/tol);
6177         n_loc++;
6178       }
6179     }
6180   }
6181   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6182   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6183   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6184 
6185   err_loc[0] = sum;
6186   err_loc[1] = suma;
6187   err_loc[2] = sumr;
6188   err_loc[3] = (PetscReal)n_loc;
6189   err_loc[4] = (PetscReal)na_loc;
6190   err_loc[5] = (PetscReal)nr_loc;
6191 
6192   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6193 
6194   gsum   = err_glb[0];
6195   gsuma  = err_glb[1];
6196   gsumr  = err_glb[2];
6197   n_glb  = err_glb[3];
6198   na_glb = err_glb[4];
6199   nr_glb = err_glb[5];
6200 
6201   *norm  = 0.;
6202   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
6203   *norma = 0.;
6204   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
6205   *normr = 0.;
6206   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
6207 
6208   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6209   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6210   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6211   PetscFunctionReturn(0);
6212 }
6213 
6214 /*@
6215    TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances
6216    Collective on TS
6217 
6218    Input Arguments:
6219 +  ts - time stepping context
6220 .  E - error vector
6221 .  U - state vector, usually ts->vec_sol
6222 -  Y - state vector, previous time step
6223 
6224    Output Arguments:
6225 +  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6226 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6227 -  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6228 
6229    Level: developer
6230 
6231 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENorm2()
6232 @*/
6233 PetscErrorCode TSErrorWeightedENormInfinity(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6234 {
6235   PetscErrorCode    ierr;
6236   PetscInt          i,n,N,rstart;
6237   const PetscScalar *e,*u,*y;
6238   PetscReal         err,max,gmax,maxa,gmaxa,maxr,gmaxr;
6239   PetscReal         tol,tola,tolr;
6240   PetscReal         err_loc[3],err_glb[3];
6241 
6242   PetscFunctionBegin;
6243   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6244   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
6245   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
6246   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
6247   PetscValidType(E,2);
6248   PetscValidType(U,3);
6249   PetscValidType(Y,4);
6250   PetscCheckSameComm(E,2,U,3);
6251   PetscCheckSameComm(U,2,Y,3);
6252   PetscValidPointer(norm,5);
6253   PetscValidPointer(norma,6);
6254   PetscValidPointer(normr,7);
6255 
6256   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
6257   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
6258   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
6259   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
6260   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6261   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6262 
6263   max=0.;
6264   maxa=0.;
6265   maxr=0.;
6266 
6267   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
6268     const PetscScalar *atol,*rtol;
6269     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6270     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6271 
6272     for (i=0; i<n; i++) {
6273       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
6274       err = PetscAbsScalar(e[i]);
6275       tola = PetscRealPart(atol[i]);
6276       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6277       tol  = tola+tolr;
6278       if(tola>0.){
6279         maxa = PetscMax(maxa,err / tola);
6280       }
6281       if(tolr>0.){
6282         maxr = PetscMax(maxr,err / tolr);
6283       }
6284       if(tol>0.){
6285         max = PetscMax(max,err / tol);
6286       }
6287     }
6288     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6289     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6290   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6291     const PetscScalar *atol;
6292     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6293     for (i=0; i<n; i++) {
6294       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
6295       err = PetscAbsScalar(e[i]);
6296       tola = PetscRealPart(atol[i]);
6297       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6298       tol  = tola+tolr;
6299       if(tola>0.){
6300         maxa = PetscMax(maxa,err / tola);
6301       }
6302       if(tolr>0.){
6303         maxr = PetscMax(maxr,err / tolr);
6304       }
6305       if(tol>0.){
6306         max = PetscMax(max,err / tol);
6307       }
6308     }
6309     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6310   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6311     const PetscScalar *rtol;
6312     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6313 
6314     for (i=0; i<n; i++) {
6315       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
6316       err = PetscAbsScalar(e[i]);
6317       tola = ts->atol;
6318       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6319       tol  = tola+tolr;
6320       if(tola>0.){
6321         maxa = PetscMax(maxa,err / tola);
6322       }
6323       if(tolr>0.){
6324         maxr = PetscMax(maxr,err / tolr);
6325       }
6326       if(tol>0.){
6327         max = PetscMax(max,err / tol);
6328       }
6329     }
6330     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6331   } else {                      /* scalar atol, scalar rtol */
6332 
6333     for (i=0; i<n; i++) {
6334       SkipSmallValue(y[i],u[i],ts->adapt->ignore_max);
6335       err = PetscAbsScalar(e[i]);
6336       tola = ts->atol;
6337       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6338       tol  = tola+tolr;
6339       if(tola>0.){
6340         maxa = PetscMax(maxa,err / tola);
6341       }
6342       if(tolr>0.){
6343         maxr = PetscMax(maxr,err / tolr);
6344       }
6345       if(tol>0.){
6346         max = PetscMax(max,err / tol);
6347       }
6348     }
6349   }
6350   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6351   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6352   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6353   err_loc[0] = max;
6354   err_loc[1] = maxa;
6355   err_loc[2] = maxr;
6356   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6357   gmax   = err_glb[0];
6358   gmaxa  = err_glb[1];
6359   gmaxr  = err_glb[2];
6360 
6361   *norm = gmax;
6362   *norma = gmaxa;
6363   *normr = gmaxr;
6364   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6365     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6366     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6367   PetscFunctionReturn(0);
6368 }
6369 
6370 /*@
6371    TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
6372 
6373    Collective on TS
6374 
6375    Input Arguments:
6376 +  ts - time stepping context
6377 .  E - error vector
6378 .  U - state vector, usually ts->vec_sol
6379 .  Y - state vector, previous time step
6380 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6381 
6382    Output Arguments:
6383 +  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6384 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6385 -  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6386 
6387    Options Database Keys:
6388 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6389 
6390    Level: developer
6391 
6392 .seealso: TSErrorWeightedENormInfinity(), TSErrorWeightedENorm2(), TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2()
6393 @*/
6394 PetscErrorCode TSErrorWeightedENorm(TS ts,Vec E,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6395 {
6396   PetscErrorCode ierr;
6397 
6398   PetscFunctionBegin;
6399   if (wnormtype == NORM_2) {
6400     ierr = TSErrorWeightedENorm2(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6401   } else if(wnormtype == NORM_INFINITY) {
6402     ierr = TSErrorWeightedENormInfinity(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6403   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6404   PetscFunctionReturn(0);
6405 }
6406 
6407 
6408 /*@
6409    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
6410 
6411    Logically Collective on TS
6412 
6413    Input Arguments:
6414 +  ts - time stepping context
6415 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
6416 
6417    Note:
6418    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
6419 
6420    Level: intermediate
6421 
6422 .seealso: TSGetCFLTime(), TSADAPTCFL
6423 @*/
6424 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
6425 {
6426   PetscFunctionBegin;
6427   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6428   ts->cfltime_local = cfltime;
6429   ts->cfltime       = -1.;
6430   PetscFunctionReturn(0);
6431 }
6432 
6433 /*@
6434    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
6435 
6436    Collective on TS
6437 
6438    Input Arguments:
6439 .  ts - time stepping context
6440 
6441    Output Arguments:
6442 .  cfltime - maximum stable time step for forward Euler
6443 
6444    Level: advanced
6445 
6446 .seealso: TSSetCFLTimeLocal()
6447 @*/
6448 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
6449 {
6450   PetscErrorCode ierr;
6451 
6452   PetscFunctionBegin;
6453   if (ts->cfltime < 0) {
6454     ierr = MPIU_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6455   }
6456   *cfltime = ts->cfltime;
6457   PetscFunctionReturn(0);
6458 }
6459 
6460 /*@
6461    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
6462 
6463    Input Parameters:
6464 +  ts   - the TS context.
6465 .  xl   - lower bound.
6466 -  xu   - upper bound.
6467 
6468    Notes:
6469    If this routine is not called then the lower and upper bounds are set to
6470    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
6471 
6472    Level: advanced
6473 
6474 @*/
6475 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
6476 {
6477   PetscErrorCode ierr;
6478   SNES           snes;
6479 
6480   PetscFunctionBegin;
6481   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
6482   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
6483   PetscFunctionReturn(0);
6484 }
6485 
6486 /*@C
6487    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
6488        in a time based line graph
6489 
6490    Collective on TS
6491 
6492    Input Parameters:
6493 +  ts - the TS context
6494 .  step - current time-step
6495 .  ptime - current time
6496 .  u - current solution
6497 -  dctx - the TSMonitorLGCtx object that contains all the options for the monitoring, this is created with TSMonitorLGCtxCreate()
6498 
6499    Options Database:
6500 .   -ts_monitor_lg_solution_variables
6501 
6502    Level: intermediate
6503 
6504    Notes:
6505     Each process in a parallel run displays its component solutions in a separate window
6506 
6507 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
6508            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
6509            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
6510            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
6511 @*/
6512 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
6513 {
6514   PetscErrorCode    ierr;
6515   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dctx;
6516   const PetscScalar *yy;
6517   Vec               v;
6518 
6519   PetscFunctionBegin;
6520   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
6521   if (!step) {
6522     PetscDrawAxis axis;
6523     PetscInt      dim;
6524     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
6525     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
6526     if (!ctx->names) {
6527       PetscBool flg;
6528       /* user provides names of variables to plot but no names has been set so assume names are integer values */
6529       ierr = PetscOptionsHasName(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",&flg);CHKERRQ(ierr);
6530       if (flg) {
6531         PetscInt i,n;
6532         char     **names;
6533         ierr = VecGetSize(u,&n);CHKERRQ(ierr);
6534         ierr = PetscMalloc1(n+1,&names);CHKERRQ(ierr);
6535         for (i=0; i<n; i++) {
6536           ierr = PetscMalloc1(5,&names[i]);CHKERRQ(ierr);
6537           ierr = PetscSNPrintf(names[i],5,"%D",i);CHKERRQ(ierr);
6538         }
6539         names[n] = NULL;
6540         ctx->names = names;
6541       }
6542     }
6543     if (ctx->names && !ctx->displaynames) {
6544       char      **displaynames;
6545       PetscBool flg;
6546       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6547       ierr = PetscCalloc1(dim+1,&displaynames);CHKERRQ(ierr);
6548       ierr = PetscOptionsGetStringArray(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",displaynames,&dim,&flg);CHKERRQ(ierr);
6549       if (flg) {
6550         ierr = TSMonitorLGCtxSetDisplayVariables(ctx,(const char *const *)displaynames);CHKERRQ(ierr);
6551       }
6552       ierr = PetscStrArrayDestroy(&displaynames);CHKERRQ(ierr);
6553     }
6554     if (ctx->displaynames) {
6555       ierr = PetscDrawLGSetDimension(ctx->lg,ctx->ndisplayvariables);CHKERRQ(ierr);
6556       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->displaynames);CHKERRQ(ierr);
6557     } else if (ctx->names) {
6558       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6559       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
6560       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->names);CHKERRQ(ierr);
6561     } else {
6562       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6563       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
6564     }
6565     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
6566   }
6567 
6568   if (!ctx->transform) v = u;
6569   else {ierr = (*ctx->transform)(ctx->transformctx,u,&v);CHKERRQ(ierr);}
6570   ierr = VecGetArrayRead(v,&yy);CHKERRQ(ierr);
6571   if (ctx->displaynames) {
6572     PetscInt i;
6573     for (i=0; i<ctx->ndisplayvariables; i++)
6574       ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
6575     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,ctx->displayvalues);CHKERRQ(ierr);
6576   } else {
6577 #if defined(PETSC_USE_COMPLEX)
6578     PetscInt  i,n;
6579     PetscReal *yreal;
6580     ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
6581     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
6582     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
6583     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
6584     ierr = PetscFree(yreal);CHKERRQ(ierr);
6585 #else
6586     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
6587 #endif
6588   }
6589   ierr = VecRestoreArrayRead(v,&yy);CHKERRQ(ierr);
6590   if (ctx->transform) {ierr = VecDestroy(&v);CHKERRQ(ierr);}
6591 
6592   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
6593     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
6594     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
6595   }
6596   PetscFunctionReturn(0);
6597 }
6598 
6599 /*@C
6600    TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
6601 
6602    Collective on TS
6603 
6604    Input Parameters:
6605 +  ts - the TS context
6606 -  names - the names of the components, final string must be NULL
6607 
6608    Level: intermediate
6609 
6610    Notes:
6611     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6612 
6613 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetVariableNames()
6614 @*/
6615 PetscErrorCode  TSMonitorLGSetVariableNames(TS ts,const char * const *names)
6616 {
6617   PetscErrorCode    ierr;
6618   PetscInt          i;
6619 
6620   PetscFunctionBegin;
6621   for (i=0; i<ts->numbermonitors; i++) {
6622     if (ts->monitor[i] == TSMonitorLGSolution) {
6623       ierr = TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i],names);CHKERRQ(ierr);
6624       break;
6625     }
6626   }
6627   PetscFunctionReturn(0);
6628 }
6629 
6630 /*@C
6631    TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
6632 
6633    Collective on TS
6634 
6635    Input Parameters:
6636 +  ts - the TS context
6637 -  names - the names of the components, final string must be NULL
6638 
6639    Level: intermediate
6640 
6641 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGSetVariableNames()
6642 @*/
6643 PetscErrorCode  TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx,const char * const *names)
6644 {
6645   PetscErrorCode    ierr;
6646 
6647   PetscFunctionBegin;
6648   ierr = PetscStrArrayDestroy(&ctx->names);CHKERRQ(ierr);
6649   ierr = PetscStrArrayallocpy(names,&ctx->names);CHKERRQ(ierr);
6650   PetscFunctionReturn(0);
6651 }
6652 
6653 /*@C
6654    TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
6655 
6656    Collective on TS
6657 
6658    Input Parameter:
6659 .  ts - the TS context
6660 
6661    Output Parameter:
6662 .  names - the names of the components, final string must be NULL
6663 
6664    Level: intermediate
6665 
6666    Notes:
6667     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6668 
6669 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
6670 @*/
6671 PetscErrorCode  TSMonitorLGGetVariableNames(TS ts,const char *const **names)
6672 {
6673   PetscInt       i;
6674 
6675   PetscFunctionBegin;
6676   *names = NULL;
6677   for (i=0; i<ts->numbermonitors; i++) {
6678     if (ts->monitor[i] == TSMonitorLGSolution) {
6679       TSMonitorLGCtx  ctx = (TSMonitorLGCtx) ts->monitorcontext[i];
6680       *names = (const char *const *)ctx->names;
6681       break;
6682     }
6683   }
6684   PetscFunctionReturn(0);
6685 }
6686 
6687 /*@C
6688    TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
6689 
6690    Collective on TS
6691 
6692    Input Parameters:
6693 +  ctx - the TSMonitorLG context
6694 -  displaynames - the names of the components, final string must be NULL
6695 
6696    Level: intermediate
6697 
6698 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
6699 @*/
6700 PetscErrorCode  TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx,const char * const *displaynames)
6701 {
6702   PetscInt          j = 0,k;
6703   PetscErrorCode    ierr;
6704 
6705   PetscFunctionBegin;
6706   if (!ctx->names) PetscFunctionReturn(0);
6707   ierr = PetscStrArrayDestroy(&ctx->displaynames);CHKERRQ(ierr);
6708   ierr = PetscStrArrayallocpy(displaynames,&ctx->displaynames);CHKERRQ(ierr);
6709   while (displaynames[j]) j++;
6710   ctx->ndisplayvariables = j;
6711   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvariables);CHKERRQ(ierr);
6712   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvalues);CHKERRQ(ierr);
6713   j = 0;
6714   while (displaynames[j]) {
6715     k = 0;
6716     while (ctx->names[k]) {
6717       PetscBool flg;
6718       ierr = PetscStrcmp(displaynames[j],ctx->names[k],&flg);CHKERRQ(ierr);
6719       if (flg) {
6720         ctx->displayvariables[j] = k;
6721         break;
6722       }
6723       k++;
6724     }
6725     j++;
6726   }
6727   PetscFunctionReturn(0);
6728 }
6729 
6730 /*@C
6731    TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
6732 
6733    Collective on TS
6734 
6735    Input Parameters:
6736 +  ts - the TS context
6737 -  displaynames - the names of the components, final string must be NULL
6738 
6739    Notes:
6740     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6741 
6742    Level: intermediate
6743 
6744 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
6745 @*/
6746 PetscErrorCode  TSMonitorLGSetDisplayVariables(TS ts,const char * const *displaynames)
6747 {
6748   PetscInt          i;
6749   PetscErrorCode    ierr;
6750 
6751   PetscFunctionBegin;
6752   for (i=0; i<ts->numbermonitors; i++) {
6753     if (ts->monitor[i] == TSMonitorLGSolution) {
6754       ierr = TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i],displaynames);CHKERRQ(ierr);
6755       break;
6756     }
6757   }
6758   PetscFunctionReturn(0);
6759 }
6760 
6761 /*@C
6762    TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
6763 
6764    Collective on TS
6765 
6766    Input Parameters:
6767 +  ts - the TS context
6768 .  transform - the transform function
6769 .  destroy - function to destroy the optional context
6770 -  ctx - optional context used by transform function
6771 
6772    Notes:
6773     If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
6774 
6775    Level: intermediate
6776 
6777 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGCtxSetTransform()
6778 @*/
6779 PetscErrorCode  TSMonitorLGSetTransform(TS ts,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
6780 {
6781   PetscInt          i;
6782   PetscErrorCode    ierr;
6783 
6784   PetscFunctionBegin;
6785   for (i=0; i<ts->numbermonitors; i++) {
6786     if (ts->monitor[i] == TSMonitorLGSolution) {
6787       ierr = TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i],transform,destroy,tctx);CHKERRQ(ierr);
6788     }
6789   }
6790   PetscFunctionReturn(0);
6791 }
6792 
6793 /*@C
6794    TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
6795 
6796    Collective on TSLGCtx
6797 
6798    Input Parameters:
6799 +  ts - the TS context
6800 .  transform - the transform function
6801 .  destroy - function to destroy the optional context
6802 -  ctx - optional context used by transform function
6803 
6804    Level: intermediate
6805 
6806 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGSetTransform()
6807 @*/
6808 PetscErrorCode  TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
6809 {
6810   PetscFunctionBegin;
6811   ctx->transform    = transform;
6812   ctx->transformdestroy = destroy;
6813   ctx->transformctx = tctx;
6814   PetscFunctionReturn(0);
6815 }
6816 
6817 /*@C
6818    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the error
6819        in a time based line graph
6820 
6821    Collective on TS
6822 
6823    Input Parameters:
6824 +  ts - the TS context
6825 .  step - current time-step
6826 .  ptime - current time
6827 .  u - current solution
6828 -  dctx - TSMonitorLGCtx object created with TSMonitorLGCtxCreate()
6829 
6830    Level: intermediate
6831 
6832    Notes:
6833     Each process in a parallel run displays its component errors in a separate window
6834 
6835    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
6836 
6837    Options Database Keys:
6838 .  -ts_monitor_lg_error - create a graphical monitor of error history
6839 
6840 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
6841 @*/
6842 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
6843 {
6844   PetscErrorCode    ierr;
6845   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
6846   const PetscScalar *yy;
6847   Vec               y;
6848 
6849   PetscFunctionBegin;
6850   if (!step) {
6851     PetscDrawAxis axis;
6852     PetscInt      dim;
6853     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
6854     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Error");CHKERRQ(ierr);
6855     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
6856     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
6857     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
6858   }
6859   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
6860   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
6861   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
6862   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
6863 #if defined(PETSC_USE_COMPLEX)
6864   {
6865     PetscReal *yreal;
6866     PetscInt  i,n;
6867     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
6868     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
6869     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
6870     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
6871     ierr = PetscFree(yreal);CHKERRQ(ierr);
6872   }
6873 #else
6874   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
6875 #endif
6876   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
6877   ierr = VecDestroy(&y);CHKERRQ(ierr);
6878   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
6879     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
6880     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
6881   }
6882   PetscFunctionReturn(0);
6883 }
6884 
6885 /*@C
6886    TSMonitorSPSwarmSolution - Graphically displays phase plots of DMSwarm particles on a scatter plot
6887 
6888    Input Parameters:
6889 +  ts - the TS context
6890 .  step - current time-step
6891 .  ptime - current time
6892 .  u - current solution
6893 -  dctx - the TSMonitorSPCtx object that contains all the options for the monitoring, this is created with TSMonitorSPCtxCreate()
6894 
6895    Options Database:
6896 .   -ts_monitor_sp_swarm
6897 
6898    Level: intermediate
6899 
6900 @*/
6901 PetscErrorCode TSMonitorSPSwarmSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
6902 {
6903   PetscErrorCode    ierr;
6904   TSMonitorSPCtx    ctx = (TSMonitorSPCtx)dctx;
6905   const PetscScalar *yy;
6906   PetscReal       *y,*x;
6907   PetscInt          Np, p, dim=2;
6908   DM                dm;
6909 
6910   PetscFunctionBegin;
6911 
6912   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
6913   if (!step) {
6914     PetscDrawAxis axis;
6915     ierr = PetscDrawSPGetAxis(ctx->sp,&axis);CHKERRQ(ierr);
6916     ierr = PetscDrawAxisSetLabels(axis,"Particles","X","Y");CHKERRQ(ierr);
6917     ierr = PetscDrawAxisSetLimits(axis, -5, 5, -5, 5);CHKERRQ(ierr);
6918     ierr = PetscDrawAxisSetHoldLimits(axis, PETSC_TRUE);CHKERRQ(ierr);
6919     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
6920     ierr = DMGetDimension(dm, &dim);
6921     if(dim!=2) SETERRQ(PETSC_COMM_SELF, ierr, "Dimensions improper for monitor arguments! Current support: two dimensions.");CHKERRQ(ierr);
6922     ierr = VecGetLocalSize(u, &Np);CHKERRQ(ierr);
6923     Np /= 2*dim;
6924     ierr = PetscDrawSPSetDimension(ctx->sp, Np);CHKERRQ(ierr);
6925     ierr = PetscDrawSPReset(ctx->sp);CHKERRQ(ierr);
6926   }
6927 
6928   ierr = VecGetLocalSize(u, &Np);CHKERRQ(ierr);
6929   Np /= 2*dim;
6930   ierr = VecGetArrayRead(u,&yy);CHKERRQ(ierr);
6931   ierr = PetscMalloc2(Np, &x, Np, &y);CHKERRQ(ierr);
6932   /* get points from solution vector */
6933   for (p=0; p<Np; ++p){
6934     x[p] = PetscRealPart(yy[2*dim*p]);
6935     y[p] = PetscRealPart(yy[2*dim*p+1]);
6936   }
6937   ierr = VecRestoreArrayRead(u,&yy);CHKERRQ(ierr);
6938 
6939   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
6940     ierr = PetscDrawSPAddPoint(ctx->sp,x,y);CHKERRQ(ierr);
6941     ierr = PetscDrawSPDraw(ctx->sp,PETSC_FALSE);CHKERRQ(ierr);
6942     ierr = PetscDrawSPSave(ctx->sp);CHKERRQ(ierr);
6943   }
6944 
6945   ierr = PetscFree2(x, y);CHKERRQ(ierr);
6946 
6947   PetscFunctionReturn(0);
6948 }
6949 
6950 
6951 
6952 /*@C
6953    TSMonitorError - Monitors progress of the TS solvers by printing the 2 norm of the error at each timestep
6954 
6955    Collective on TS
6956 
6957    Input Parameters:
6958 +  ts - the TS context
6959 .  step - current time-step
6960 .  ptime - current time
6961 .  u - current solution
6962 -  dctx - unused context
6963 
6964    Level: intermediate
6965 
6966    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
6967 
6968    Options Database Keys:
6969 .  -ts_monitor_error - create a graphical monitor of error history
6970 
6971 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
6972 @*/
6973 PetscErrorCode  TSMonitorError(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
6974 {
6975   PetscErrorCode    ierr;
6976   Vec               y;
6977   PetscReal         nrm;
6978   PetscBool         flg;
6979 
6980   PetscFunctionBegin;
6981   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
6982   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
6983   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
6984   ierr = PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERASCII,&flg);CHKERRQ(ierr);
6985   if (flg) {
6986     ierr = VecNorm(y,NORM_2,&nrm);CHKERRQ(ierr);
6987     ierr = PetscViewerASCIIPrintf(vf->viewer,"2-norm of error %g\n",(double)nrm);CHKERRQ(ierr);
6988   }
6989   ierr = PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERDRAW,&flg);CHKERRQ(ierr);
6990   if (flg) {
6991     ierr = VecView(y,vf->viewer);CHKERRQ(ierr);
6992   }
6993   ierr = VecDestroy(&y);CHKERRQ(ierr);
6994   PetscFunctionReturn(0);
6995 }
6996 
6997 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
6998 {
6999   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7000   PetscReal      x   = ptime,y;
7001   PetscErrorCode ierr;
7002   PetscInt       its;
7003 
7004   PetscFunctionBegin;
7005   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7006   if (!n) {
7007     PetscDrawAxis axis;
7008     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7009     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
7010     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7011     ctx->snes_its = 0;
7012   }
7013   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
7014   y    = its - ctx->snes_its;
7015   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7016   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7017     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7018     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7019   }
7020   ctx->snes_its = its;
7021   PetscFunctionReturn(0);
7022 }
7023 
7024 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
7025 {
7026   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7027   PetscReal      x   = ptime,y;
7028   PetscErrorCode ierr;
7029   PetscInt       its;
7030 
7031   PetscFunctionBegin;
7032   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7033   if (!n) {
7034     PetscDrawAxis axis;
7035     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7036     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
7037     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7038     ctx->ksp_its = 0;
7039   }
7040   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
7041   y    = its - ctx->ksp_its;
7042   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7043   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7044     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7045     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7046   }
7047   ctx->ksp_its = its;
7048   PetscFunctionReturn(0);
7049 }
7050 
7051 /*@
7052    TSComputeLinearStability - computes the linear stability function at a point
7053 
7054    Collective on TS
7055 
7056    Input Parameters:
7057 +  ts - the TS context
7058 -  xr,xi - real and imaginary part of input arguments
7059 
7060    Output Parameters:
7061 .  yr,yi - real and imaginary part of function value
7062 
7063    Level: developer
7064 
7065 .seealso: TSSetRHSFunction(), TSComputeIFunction()
7066 @*/
7067 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
7068 {
7069   PetscErrorCode ierr;
7070 
7071   PetscFunctionBegin;
7072   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7073   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
7074   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
7075   PetscFunctionReturn(0);
7076 }
7077 
7078 /* ------------------------------------------------------------------------*/
7079 /*@C
7080    TSMonitorEnvelopeCtxCreate - Creates a context for use with TSMonitorEnvelope()
7081 
7082    Collective on TS
7083 
7084    Input Parameters:
7085 .  ts  - the ODE solver object
7086 
7087    Output Parameter:
7088 .  ctx - the context
7089 
7090    Level: intermediate
7091 
7092 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
7093 
7094 @*/
7095 PetscErrorCode  TSMonitorEnvelopeCtxCreate(TS ts,TSMonitorEnvelopeCtx *ctx)
7096 {
7097   PetscErrorCode ierr;
7098 
7099   PetscFunctionBegin;
7100   ierr = PetscNew(ctx);CHKERRQ(ierr);
7101   PetscFunctionReturn(0);
7102 }
7103 
7104 /*@C
7105    TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
7106 
7107    Collective on TS
7108 
7109    Input Parameters:
7110 +  ts - the TS context
7111 .  step - current time-step
7112 .  ptime - current time
7113 .  u  - current solution
7114 -  dctx - the envelope context
7115 
7116    Options Database:
7117 .  -ts_monitor_envelope
7118 
7119    Level: intermediate
7120 
7121    Notes:
7122     after a solve you can use TSMonitorEnvelopeGetBounds() to access the envelope
7123 
7124 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxCreate()
7125 @*/
7126 PetscErrorCode  TSMonitorEnvelope(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
7127 {
7128   PetscErrorCode       ierr;
7129   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
7130 
7131   PetscFunctionBegin;
7132   if (!ctx->max) {
7133     ierr = VecDuplicate(u,&ctx->max);CHKERRQ(ierr);
7134     ierr = VecDuplicate(u,&ctx->min);CHKERRQ(ierr);
7135     ierr = VecCopy(u,ctx->max);CHKERRQ(ierr);
7136     ierr = VecCopy(u,ctx->min);CHKERRQ(ierr);
7137   } else {
7138     ierr = VecPointwiseMax(ctx->max,u,ctx->max);CHKERRQ(ierr);
7139     ierr = VecPointwiseMin(ctx->min,u,ctx->min);CHKERRQ(ierr);
7140   }
7141   PetscFunctionReturn(0);
7142 }
7143 
7144 /*@C
7145    TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
7146 
7147    Collective on TS
7148 
7149    Input Parameter:
7150 .  ts - the TS context
7151 
7152    Output Parameter:
7153 +  max - the maximum values
7154 -  min - the minimum values
7155 
7156    Notes:
7157     If the TS does not have a TSMonitorEnvelopeCtx associated with it then this function is ignored
7158 
7159    Level: intermediate
7160 
7161 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
7162 @*/
7163 PetscErrorCode  TSMonitorEnvelopeGetBounds(TS ts,Vec *max,Vec *min)
7164 {
7165   PetscInt i;
7166 
7167   PetscFunctionBegin;
7168   if (max) *max = NULL;
7169   if (min) *min = NULL;
7170   for (i=0; i<ts->numbermonitors; i++) {
7171     if (ts->monitor[i] == TSMonitorEnvelope) {
7172       TSMonitorEnvelopeCtx  ctx = (TSMonitorEnvelopeCtx) ts->monitorcontext[i];
7173       if (max) *max = ctx->max;
7174       if (min) *min = ctx->min;
7175       break;
7176     }
7177   }
7178   PetscFunctionReturn(0);
7179 }
7180 
7181 /*@C
7182    TSMonitorEnvelopeCtxDestroy - Destroys a context that was created  with TSMonitorEnvelopeCtxCreate().
7183 
7184    Collective on TSMonitorEnvelopeCtx
7185 
7186    Input Parameter:
7187 .  ctx - the monitor context
7188 
7189    Level: intermediate
7190 
7191 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep()
7192 @*/
7193 PetscErrorCode  TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
7194 {
7195   PetscErrorCode ierr;
7196 
7197   PetscFunctionBegin;
7198   ierr = VecDestroy(&(*ctx)->min);CHKERRQ(ierr);
7199   ierr = VecDestroy(&(*ctx)->max);CHKERRQ(ierr);
7200   ierr = PetscFree(*ctx);CHKERRQ(ierr);
7201   PetscFunctionReturn(0);
7202 }
7203 
7204 /*@
7205    TSRestartStep - Flags the solver to restart the next step
7206 
7207    Collective on TS
7208 
7209    Input Parameter:
7210 .  ts - the TS context obtained from TSCreate()
7211 
7212    Level: advanced
7213 
7214    Notes:
7215    Multistep methods like BDF or Runge-Kutta methods with FSAL property require restarting the solver in the event of
7216    discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
7217    vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
7218    the sake of correctness and maximum safety, users are expected to call TSRestart() whenever they introduce
7219    discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
7220    discontinuous source terms).
7221 
7222 .seealso: TSSolve(), TSSetPreStep(), TSSetPostStep()
7223 @*/
7224 PetscErrorCode TSRestartStep(TS ts)
7225 {
7226   PetscFunctionBegin;
7227   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7228   ts->steprestart = PETSC_TRUE;
7229   PetscFunctionReturn(0);
7230 }
7231 
7232 /*@
7233    TSRollBack - Rolls back one time step
7234 
7235    Collective on TS
7236 
7237    Input Parameter:
7238 .  ts - the TS context obtained from TSCreate()
7239 
7240    Level: advanced
7241 
7242 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
7243 @*/
7244 PetscErrorCode  TSRollBack(TS ts)
7245 {
7246   PetscErrorCode ierr;
7247 
7248   PetscFunctionBegin;
7249   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7250   if (ts->steprollback) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"TSRollBack already called");
7251   if (!ts->ops->rollback) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
7252   ierr = (*ts->ops->rollback)(ts);CHKERRQ(ierr);
7253   ts->time_step = ts->ptime - ts->ptime_prev;
7254   ts->ptime = ts->ptime_prev;
7255   ts->ptime_prev = ts->ptime_prev_rollback;
7256   ts->steps--;
7257   ts->steprollback = PETSC_TRUE;
7258   PetscFunctionReturn(0);
7259 }
7260 
7261 /*@
7262    TSGetStages - Get the number of stages and stage values
7263 
7264    Input Parameter:
7265 .  ts - the TS context obtained from TSCreate()
7266 
7267    Output Parameters:
7268 +  ns - the number of stages
7269 -  Y - the current stage vectors
7270 
7271    Level: advanced
7272 
7273    Notes: Both ns and Y can be NULL.
7274 
7275 .seealso: TSCreate()
7276 @*/
7277 PetscErrorCode  TSGetStages(TS ts,PetscInt *ns,Vec **Y)
7278 {
7279   PetscErrorCode ierr;
7280 
7281   PetscFunctionBegin;
7282   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7283   if (ns) PetscValidPointer(ns,2);
7284   if (Y) PetscValidPointer(Y,3);
7285   if (!ts->ops->getstages) {
7286     if (ns) *ns = 0;
7287     if (Y) *Y = NULL;
7288   } else {
7289     ierr = (*ts->ops->getstages)(ts,ns,Y);CHKERRQ(ierr);
7290   }
7291   PetscFunctionReturn(0);
7292 }
7293 
7294 /*@C
7295   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
7296 
7297   Collective on SNES
7298 
7299   Input Parameters:
7300 + ts - the TS context
7301 . t - current timestep
7302 . U - state vector
7303 . Udot - time derivative of state vector
7304 . shift - shift to apply, see note below
7305 - ctx - an optional user context
7306 
7307   Output Parameters:
7308 + J - Jacobian matrix (not altered in this routine)
7309 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
7310 
7311   Level: intermediate
7312 
7313   Notes:
7314   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
7315 
7316   dF/dU + shift*dF/dUdot
7317 
7318   Most users should not need to explicitly call this routine, as it
7319   is used internally within the nonlinear solvers.
7320 
7321   This will first try to get the coloring from the DM.  If the DM type has no coloring
7322   routine, then it will try to get the coloring from the matrix.  This requires that the
7323   matrix have nonzero entries precomputed.
7324 
7325 .seealso: TSSetIJacobian(), MatFDColoringCreate(), MatFDColoringSetFunction()
7326 @*/
7327 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat J,Mat B,void *ctx)
7328 {
7329   SNES           snes;
7330   MatFDColoring  color;
7331   PetscBool      hascolor, matcolor = PETSC_FALSE;
7332   PetscErrorCode ierr;
7333 
7334   PetscFunctionBegin;
7335   ierr = PetscOptionsGetBool(((PetscObject)ts)->options,((PetscObject) ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL);CHKERRQ(ierr);
7336   ierr = PetscObjectQuery((PetscObject) B, "TSMatFDColoring", (PetscObject *) &color);CHKERRQ(ierr);
7337   if (!color) {
7338     DM         dm;
7339     ISColoring iscoloring;
7340 
7341     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
7342     ierr = DMHasColoring(dm, &hascolor);CHKERRQ(ierr);
7343     if (hascolor && !matcolor) {
7344       ierr = DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring);CHKERRQ(ierr);
7345       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7346       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7347       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7348       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7349       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7350     } else {
7351       MatColoring mc;
7352 
7353       ierr = MatColoringCreate(B, &mc);CHKERRQ(ierr);
7354       ierr = MatColoringSetDistance(mc, 2);CHKERRQ(ierr);
7355       ierr = MatColoringSetType(mc, MATCOLORINGSL);CHKERRQ(ierr);
7356       ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr);
7357       ierr = MatColoringApply(mc, &iscoloring);CHKERRQ(ierr);
7358       ierr = MatColoringDestroy(&mc);CHKERRQ(ierr);
7359       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
7360       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
7361       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
7362       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
7363       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
7364     }
7365     ierr = PetscObjectCompose((PetscObject) B, "TSMatFDColoring", (PetscObject) color);CHKERRQ(ierr);
7366     ierr = PetscObjectDereference((PetscObject) color);CHKERRQ(ierr);
7367   }
7368   ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
7369   ierr = MatFDColoringApply(B, color, U, snes);CHKERRQ(ierr);
7370   if (J != B) {
7371     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7372     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7373   }
7374   PetscFunctionReturn(0);
7375 }
7376 
7377 /*@
7378     TSSetFunctionDomainError - Set a function that tests if the current state vector is valid
7379 
7380     Input Parameters:
7381 +    ts - the TS context
7382 -    func - function called within TSFunctionDomainError
7383 
7384     Calling sequence of func:
7385 $     PetscErrorCode func(TS ts,PetscReal time,Vec state,PetscBool reject)
7386 
7387 +   ts - the TS context
7388 .   time - the current time (of the stage)
7389 .   state - the state to check if it is valid
7390 -   reject - (output parameter) PETSC_FALSE if the state is acceptable, PETSC_TRUE if not acceptable
7391 
7392     Level: intermediate
7393 
7394     Notes:
7395       If an implicit ODE solver is being used then, in addition to providing this routine, the
7396       user's code should call SNESSetFunctionDomainError() when domain errors occur during
7397       function evaluations where the functions are provided by TSSetIFunction() or TSSetRHSFunction().
7398       Use TSGetSNES() to obtain the SNES object
7399 
7400     Developer Notes:
7401       The naming of this function is inconsistent with the SNESSetFunctionDomainError()
7402       since one takes a function pointer and the other does not.
7403 
7404 .seealso: TSAdaptCheckStage(), TSFunctionDomainError(), SNESSetFunctionDomainError(), TSGetSNES()
7405 @*/
7406 
7407 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS,PetscReal,Vec,PetscBool*))
7408 {
7409   PetscFunctionBegin;
7410   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7411   ts->functiondomainerror = func;
7412   PetscFunctionReturn(0);
7413 }
7414 
7415 /*@
7416     TSFunctionDomainError - Checks if the current state is valid
7417 
7418     Input Parameters:
7419 +    ts - the TS context
7420 .    stagetime - time of the simulation
7421 -    Y - state vector to check.
7422 
7423     Output Parameter:
7424 .    accept - Set to PETSC_FALSE if the current state vector is valid.
7425 
7426     Note:
7427     This function is called by the TS integration routines and calls the user provided function (set with TSSetFunctionDomainError())
7428     to check if the current state is valid.
7429 
7430     Level: developer
7431 
7432 .seealso: TSSetFunctionDomainError()
7433 @*/
7434 PetscErrorCode TSFunctionDomainError(TS ts,PetscReal stagetime,Vec Y,PetscBool* accept)
7435 {
7436   PetscFunctionBegin;
7437   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7438   *accept = PETSC_TRUE;
7439   if (ts->functiondomainerror) {
7440     PetscStackCallStandard((*ts->functiondomainerror),(ts,stagetime,Y,accept));
7441   }
7442   PetscFunctionReturn(0);
7443 }
7444 
7445 /*@C
7446   TSClone - This function clones a time step object.
7447 
7448   Collective
7449 
7450   Input Parameter:
7451 . tsin    - The input TS
7452 
7453   Output Parameter:
7454 . tsout   - The output TS (cloned)
7455 
7456   Notes:
7457   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.
7458 
7459   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);
7460 
7461   Level: developer
7462 
7463 .seealso: TSCreate(), TSSetType(), TSSetUp(), TSDestroy(), TSSetProblemType()
7464 @*/
7465 PetscErrorCode  TSClone(TS tsin, TS *tsout)
7466 {
7467   TS             t;
7468   PetscErrorCode ierr;
7469   SNES           snes_start;
7470   DM             dm;
7471   TSType         type;
7472 
7473   PetscFunctionBegin;
7474   PetscValidPointer(tsin,1);
7475   *tsout = NULL;
7476 
7477   ierr = PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView);CHKERRQ(ierr);
7478 
7479   /* General TS description */
7480   t->numbermonitors    = 0;
7481   t->setupcalled       = 0;
7482   t->ksp_its           = 0;
7483   t->snes_its          = 0;
7484   t->nwork             = 0;
7485   t->rhsjacobian.time  = PETSC_MIN_REAL;
7486   t->rhsjacobian.scale = 1.;
7487   t->ijacobian.shift   = 1.;
7488 
7489   ierr = TSGetSNES(tsin,&snes_start);CHKERRQ(ierr);
7490   ierr = TSSetSNES(t,snes_start);CHKERRQ(ierr);
7491 
7492   ierr = TSGetDM(tsin,&dm);CHKERRQ(ierr);
7493   ierr = TSSetDM(t,dm);CHKERRQ(ierr);
7494 
7495   t->adapt = tsin->adapt;
7496   ierr = PetscObjectReference((PetscObject)t->adapt);CHKERRQ(ierr);
7497 
7498   t->trajectory = tsin->trajectory;
7499   ierr = PetscObjectReference((PetscObject)t->trajectory);CHKERRQ(ierr);
7500 
7501   t->event = tsin->event;
7502   if (t->event) t->event->refct++;
7503 
7504   t->problem_type      = tsin->problem_type;
7505   t->ptime             = tsin->ptime;
7506   t->ptime_prev        = tsin->ptime_prev;
7507   t->time_step         = tsin->time_step;
7508   t->max_time          = tsin->max_time;
7509   t->steps             = tsin->steps;
7510   t->max_steps         = tsin->max_steps;
7511   t->equation_type     = tsin->equation_type;
7512   t->atol              = tsin->atol;
7513   t->rtol              = tsin->rtol;
7514   t->max_snes_failures = tsin->max_snes_failures;
7515   t->max_reject        = tsin->max_reject;
7516   t->errorifstepfailed = tsin->errorifstepfailed;
7517 
7518   ierr = TSGetType(tsin,&type);CHKERRQ(ierr);
7519   ierr = TSSetType(t,type);CHKERRQ(ierr);
7520 
7521   t->vec_sol           = NULL;
7522 
7523   t->cfltime          = tsin->cfltime;
7524   t->cfltime_local    = tsin->cfltime_local;
7525   t->exact_final_time = tsin->exact_final_time;
7526 
7527   ierr = PetscMemcpy(t->ops,tsin->ops,sizeof(struct _TSOps));CHKERRQ(ierr);
7528 
7529   if (((PetscObject)tsin)->fortran_func_pointers) {
7530     PetscInt i;
7531     ierr = PetscMalloc((10)*sizeof(void(*)(void)),&((PetscObject)t)->fortran_func_pointers);CHKERRQ(ierr);
7532     for (i=0; i<10; i++) {
7533       ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
7534     }
7535   }
7536   *tsout = t;
7537   PetscFunctionReturn(0);
7538 }
7539 
7540 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void* ctx,Vec x,Vec y)
7541 {
7542   PetscErrorCode ierr;
7543   TS             ts = (TS) ctx;
7544 
7545   PetscFunctionBegin;
7546   ierr = TSComputeRHSFunction(ts,0,x,y);CHKERRQ(ierr);
7547   PetscFunctionReturn(0);
7548 }
7549 
7550 /*@
7551     TSRHSJacobianTest - Compares the multiply routine provided to the MATSHELL with differencing on the TS given RHS function.
7552 
7553    Logically Collective on TS
7554 
7555     Input Parameters:
7556     TS - the time stepping routine
7557 
7558    Output Parameter:
7559 .   flg - PETSC_TRUE if the multiply is likely correct
7560 
7561    Options Database:
7562  .   -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
7563 
7564    Level: advanced
7565 
7566    Notes:
7567     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
7568 
7569 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellTestMultTranspose(), TSRHSJacobianTestTranspose()
7570 @*/
7571 PetscErrorCode  TSRHSJacobianTest(TS ts,PetscBool *flg)
7572 {
7573   Mat            J,B;
7574   PetscErrorCode ierr;
7575   TSRHSJacobian  func;
7576   void*          ctx;
7577 
7578   PetscFunctionBegin;
7579   ierr = TSGetRHSJacobian(ts,&J,&B,&func,&ctx);CHKERRQ(ierr);
7580   ierr = (*func)(ts,0.0,ts->vec_sol,J,B,ctx);CHKERRQ(ierr);
7581   ierr = MatShellTestMult(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg);CHKERRQ(ierr);
7582   PetscFunctionReturn(0);
7583 }
7584 
7585 /*@C
7586     TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the MATSHELL with differencing on the TS given RHS function.
7587 
7588    Logically Collective on TS
7589 
7590     Input Parameters:
7591     TS - the time stepping routine
7592 
7593    Output Parameter:
7594 .   flg - PETSC_TRUE if the multiply is likely correct
7595 
7596    Options Database:
7597 .   -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
7598 
7599    Notes:
7600     This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
7601 
7602    Level: advanced
7603 
7604 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellTestMultTranspose(), TSRHSJacobianTest()
7605 @*/
7606 PetscErrorCode  TSRHSJacobianTestTranspose(TS ts,PetscBool *flg)
7607 {
7608   Mat            J,B;
7609   PetscErrorCode ierr;
7610   void           *ctx;
7611   TSRHSJacobian  func;
7612 
7613   PetscFunctionBegin;
7614   ierr = TSGetRHSJacobian(ts,&J,&B,&func,&ctx);CHKERRQ(ierr);
7615   ierr = (*func)(ts,0.0,ts->vec_sol,J,B,ctx);CHKERRQ(ierr);
7616   ierr = MatShellTestMultTranspose(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg);CHKERRQ(ierr);
7617   PetscFunctionReturn(0);
7618 }
7619 
7620 /*@
7621   TSSetUseSplitRHSFunction - Use the split RHSFunction when a multirate method is used.
7622 
7623   Logically collective
7624 
7625   Input Parameter:
7626 +  ts - timestepping context
7627 -  use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used
7628 
7629   Options Database:
7630 .   -ts_use_splitrhsfunction - <true,false>
7631 
7632   Notes:
7633     This is only useful for multirate methods
7634 
7635   Level: intermediate
7636 
7637 .seealso: TSGetUseSplitRHSFunction()
7638 @*/
7639 PetscErrorCode TSSetUseSplitRHSFunction(TS ts, PetscBool use_splitrhsfunction)
7640 {
7641   PetscFunctionBegin;
7642   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7643   ts->use_splitrhsfunction = use_splitrhsfunction;
7644   PetscFunctionReturn(0);
7645 }
7646 
7647 /*@
7648   TSGetUseSplitRHSFunction - Gets whether to use the split RHSFunction when a multirate method is used.
7649 
7650   Not collective
7651 
7652   Input Parameter:
7653 .  ts - timestepping context
7654 
7655   Output Parameter:
7656 .  use_splitrhsfunction - PETSC_TRUE indicates that the split RHSFunction will be used
7657 
7658   Level: intermediate
7659 
7660 .seealso: TSSetUseSplitRHSFunction()
7661 @*/
7662 PetscErrorCode TSGetUseSplitRHSFunction(TS ts, PetscBool *use_splitrhsfunction)
7663 {
7664   PetscFunctionBegin;
7665   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7666   *use_splitrhsfunction = ts->use_splitrhsfunction;
7667   PetscFunctionReturn(0);
7668 }
7669