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