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