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