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