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