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