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