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