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