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