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