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