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