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