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