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