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