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