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