xref: /petsc/src/ts/interface/ts.c (revision 80153354bc763d7777ef13196fd03cfc4d2e02f9)
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 = PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer);CHKERRQ(ierr);
1995     if (ts->ops->view) {
1996       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1997       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
1998       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1999     }
2000     if (ts->max_steps < PETSC_MAX_INT) {
2001       ierr = PetscViewerASCIIPrintf(viewer,"  maximum steps=%D\n",ts->max_steps);CHKERRQ(ierr);
2002     }
2003     if (ts->max_time < PETSC_MAX_REAL) {
2004       ierr = PetscViewerASCIIPrintf(viewer,"  maximum time=%g\n",(double)ts->max_time);CHKERRQ(ierr);
2005     }
2006     if (ts->usessnes) {
2007       PetscBool lin;
2008       if (ts->problem_type == TS_NONLINEAR) {
2009         ierr = PetscViewerASCIIPrintf(viewer,"  total number of nonlinear solver iterations=%D\n",ts->snes_its);CHKERRQ(ierr);
2010       }
2011       ierr = PetscViewerASCIIPrintf(viewer,"  total number of linear solver iterations=%D\n",ts->ksp_its);CHKERRQ(ierr);
2012       ierr = PetscObjectTypeCompare((PetscObject)ts->snes,SNESKSPONLY,&lin);CHKERRQ(ierr);
2013       ierr = PetscViewerASCIIPrintf(viewer,"  total number of %slinear solve failures=%D\n",lin ? "" : "non",ts->num_snes_failures);CHKERRQ(ierr);
2014     }
2015     ierr = PetscViewerASCIIPrintf(viewer,"  total number of rejected steps=%D\n",ts->reject);CHKERRQ(ierr);
2016     if (ts->vrtol) {
2017       ierr = PetscViewerASCIIPrintf(viewer,"  using vector of relative error tolerances, ");CHKERRQ(ierr);
2018     } else {
2019       ierr = PetscViewerASCIIPrintf(viewer,"  using relative error tolerance of %g, ",(double)ts->rtol);CHKERRQ(ierr);
2020     }
2021     if (ts->vatol) {
2022       ierr = PetscViewerASCIIPrintf(viewer,"  using vector of absolute error tolerances\n");CHKERRQ(ierr);
2023     } else {
2024       ierr = PetscViewerASCIIPrintf(viewer,"  using absolute error tolerance of %g\n",(double)ts->atol);CHKERRQ(ierr);
2025     }
2026     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2027     ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);
2028     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2029     if (ts->snes && ts->usessnes)  {
2030       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2031       ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);
2032       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2033     }
2034     ierr = DMGetDMTS(ts->dm,&sdm);CHKERRQ(ierr);
2035     ierr = DMTSView(sdm,viewer);CHKERRQ(ierr);
2036   } else if (isstring) {
2037     ierr = TSGetType(ts,&type);CHKERRQ(ierr);
2038     ierr = PetscViewerStringSPrintf(viewer," %-7.7s",type);CHKERRQ(ierr);
2039   } else if (isbinary) {
2040     PetscInt    classid = TS_FILE_CLASSID;
2041     MPI_Comm    comm;
2042     PetscMPIInt rank;
2043     char        type[256];
2044 
2045     ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
2046     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
2047     if (!rank) {
2048       ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
2049       ierr = PetscStrncpy(type,((PetscObject)ts)->type_name,256);CHKERRQ(ierr);
2050       ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
2051     }
2052     if (ts->ops->view) {
2053       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
2054     }
2055     if (ts->adapt) {ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);}
2056     ierr = DMView(ts->dm,viewer);CHKERRQ(ierr);
2057     ierr = VecView(ts->vec_sol,viewer);CHKERRQ(ierr);
2058     ierr = DMGetDMTS(ts->dm,&sdm);CHKERRQ(ierr);
2059     ierr = DMTSView(sdm,viewer);CHKERRQ(ierr);
2060   } else if (isdraw) {
2061     PetscDraw draw;
2062     char      str[36];
2063     PetscReal x,y,bottom,h;
2064 
2065     ierr   = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
2066     ierr   = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
2067     ierr   = PetscStrcpy(str,"TS: ");CHKERRQ(ierr);
2068     ierr   = PetscStrcat(str,((PetscObject)ts)->type_name);CHKERRQ(ierr);
2069     ierr   = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_BLACK,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
2070     bottom = y - h;
2071     ierr   = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr);
2072     if (ts->ops->view) {
2073       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
2074     }
2075     if (ts->adapt) {ierr = TSAdaptView(ts->adapt,viewer);CHKERRQ(ierr);}
2076     if (ts->snes)  {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);}
2077     ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr);
2078 #if defined(PETSC_HAVE_SAWS)
2079   } else if (issaws) {
2080     PetscMPIInt rank;
2081     const char  *name;
2082 
2083     ierr = PetscObjectGetName((PetscObject)ts,&name);CHKERRQ(ierr);
2084     ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
2085     if (!((PetscObject)ts)->amsmem && !rank) {
2086       char       dir[1024];
2087 
2088       ierr = PetscObjectViewSAWs((PetscObject)ts,viewer);CHKERRQ(ierr);
2089       ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time_step",name);CHKERRQ(ierr);
2090       PetscStackCallSAWs(SAWs_Register,(dir,&ts->steps,1,SAWs_READ,SAWs_INT));
2091       ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time",name);CHKERRQ(ierr);
2092       PetscStackCallSAWs(SAWs_Register,(dir,&ts->ptime,1,SAWs_READ,SAWs_DOUBLE));
2093     }
2094     if (ts->ops->view) {
2095       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
2096     }
2097 #endif
2098   }
2099 
2100   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
2101   ierr = PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials);CHKERRQ(ierr);
2102   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
2103   PetscFunctionReturn(0);
2104 }
2105 
2106 /*@
2107    TSSetApplicationContext - Sets an optional user-defined context for
2108    the timesteppers.
2109 
2110    Logically Collective on TS
2111 
2112    Input Parameters:
2113 +  ts - the TS context obtained from TSCreate()
2114 -  usrP - optional user context
2115 
2116    Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
2117     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2118 
2119    Level: intermediate
2120 
2121 .keywords: TS, timestep, set, application, context
2122 
2123 .seealso: TSGetApplicationContext()
2124 @*/
2125 PetscErrorCode  TSSetApplicationContext(TS ts,void *usrP)
2126 {
2127   PetscFunctionBegin;
2128   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2129   ts->user = usrP;
2130   PetscFunctionReturn(0);
2131 }
2132 
2133 /*@
2134     TSGetApplicationContext - Gets the user-defined context for the
2135     timestepper.
2136 
2137     Not Collective
2138 
2139     Input Parameter:
2140 .   ts - the TS context obtained from TSCreate()
2141 
2142     Output Parameter:
2143 .   usrP - user context
2144 
2145    Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
2146     function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
2147 
2148     Level: intermediate
2149 
2150 .keywords: TS, timestep, get, application, context
2151 
2152 .seealso: TSSetApplicationContext()
2153 @*/
2154 PetscErrorCode  TSGetApplicationContext(TS ts,void *usrP)
2155 {
2156   PetscFunctionBegin;
2157   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2158   *(void**)usrP = ts->user;
2159   PetscFunctionReturn(0);
2160 }
2161 
2162 /*@
2163    TSGetStepNumber - Gets the number of steps completed.
2164 
2165    Not Collective
2166 
2167    Input Parameter:
2168 .  ts - the TS context obtained from TSCreate()
2169 
2170    Output Parameter:
2171 .  steps - number of steps completed so far
2172 
2173    Level: intermediate
2174 
2175 .keywords: TS, timestep, get, iteration, number
2176 .seealso: TSGetTime(), TSGetTimeStep(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSSetPostStep()
2177 @*/
2178 PetscErrorCode TSGetStepNumber(TS ts,PetscInt *steps)
2179 {
2180   PetscFunctionBegin;
2181   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2182   PetscValidIntPointer(steps,2);
2183   *steps = ts->steps;
2184   PetscFunctionReturn(0);
2185 }
2186 
2187 /*@
2188    TSSetStepNumber - Sets the number of steps completed.
2189 
2190    Logically Collective on TS
2191 
2192    Input Parameters:
2193 +  ts - the TS context
2194 -  steps - number of steps completed so far
2195 
2196    Notes:
2197    For most uses of the TS solvers the user need not explicitly call
2198    TSSetStepNumber(), as the step counter is appropriately updated in
2199    TSSolve()/TSStep()/TSRollBack(). Power users may call this routine to
2200    reinitialize timestepping by setting the step counter to zero (and time
2201    to the initial time) to solve a similar problem with different initial
2202    conditions or parameters. Other possible use case is to continue
2203    timestepping from a previously interrupted run in such a way that TS
2204    monitors will be called with a initial nonzero step counter.
2205 
2206    Level: advanced
2207 
2208 .keywords: TS, timestep, set, iteration, number
2209 .seealso: TSGetStepNumber(), TSSetTime(), TSSetTimeStep(), TSSetSolution()
2210 @*/
2211 PetscErrorCode TSSetStepNumber(TS ts,PetscInt steps)
2212 {
2213   PetscFunctionBegin;
2214   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2215   PetscValidLogicalCollectiveInt(ts,steps,2);
2216   if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Step number must be non-negative");
2217   ts->steps = steps;
2218   PetscFunctionReturn(0);
2219 }
2220 
2221 /*@
2222    TSSetTimeStep - Allows one to reset the timestep at any time,
2223    useful for simple pseudo-timestepping codes.
2224 
2225    Logically Collective on TS
2226 
2227    Input Parameters:
2228 +  ts - the TS context obtained from TSCreate()
2229 -  time_step - the size of the timestep
2230 
2231    Level: intermediate
2232 
2233 .seealso: TSGetTimeStep(), TSSetTime()
2234 
2235 .keywords: TS, set, timestep
2236 @*/
2237 PetscErrorCode  TSSetTimeStep(TS ts,PetscReal time_step)
2238 {
2239   PetscFunctionBegin;
2240   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2241   PetscValidLogicalCollectiveReal(ts,time_step,2);
2242   ts->time_step = time_step;
2243   PetscFunctionReturn(0);
2244 }
2245 
2246 /*@
2247    TSSetExactFinalTime - Determines whether to adapt the final time step to
2248      match the exact final time, interpolate solution to the exact final time,
2249      or just return at the final time TS computed.
2250 
2251   Logically Collective on TS
2252 
2253    Input Parameter:
2254 +   ts - the time-step context
2255 -   eftopt - exact final time option
2256 
2257 $  TS_EXACTFINALTIME_STEPOVER    - Don't do anything if final time is exceeded
2258 $  TS_EXACTFINALTIME_INTERPOLATE - Interpolate back to final time
2259 $  TS_EXACTFINALTIME_MATCHSTEP - Adapt final time step to match the final time
2260 
2261    Options Database:
2262 .   -ts_exact_final_time <stepover,interpolate,matchstep> - select the final step at runtime
2263 
2264    Warning: If you use the option TS_EXACTFINALTIME_STEPOVER the solution may be at a very different time
2265     then the final time you selected.
2266 
2267    Level: beginner
2268 
2269 .seealso: TSExactFinalTimeOption, TSGetExactFinalTime()
2270 @*/
2271 PetscErrorCode TSSetExactFinalTime(TS ts,TSExactFinalTimeOption eftopt)
2272 {
2273   PetscFunctionBegin;
2274   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2275   PetscValidLogicalCollectiveEnum(ts,eftopt,2);
2276   ts->exact_final_time = eftopt;
2277   PetscFunctionReturn(0);
2278 }
2279 
2280 /*@
2281    TSGetExactFinalTime - Gets the exact final time option.
2282 
2283    Not Collective
2284 
2285    Input Parameter:
2286 .  ts - the TS context
2287 
2288    Output Parameter:
2289 .  eftopt - exact final time option
2290 
2291    Level: beginner
2292 
2293 .seealso: TSExactFinalTimeOption, TSSetExactFinalTime()
2294 @*/
2295 PetscErrorCode TSGetExactFinalTime(TS ts,TSExactFinalTimeOption *eftopt)
2296 {
2297   PetscFunctionBegin;
2298   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2299   PetscValidPointer(eftopt,2);
2300   *eftopt = ts->exact_final_time;
2301   PetscFunctionReturn(0);
2302 }
2303 
2304 /*@
2305    TSGetTimeStep - Gets the current timestep size.
2306 
2307    Not Collective
2308 
2309    Input Parameter:
2310 .  ts - the TS context obtained from TSCreate()
2311 
2312    Output Parameter:
2313 .  dt - the current timestep size
2314 
2315    Level: intermediate
2316 
2317 .seealso: TSSetTimeStep(), TSGetTime()
2318 
2319 .keywords: TS, get, timestep
2320 @*/
2321 PetscErrorCode  TSGetTimeStep(TS ts,PetscReal *dt)
2322 {
2323   PetscFunctionBegin;
2324   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2325   PetscValidRealPointer(dt,2);
2326   *dt = ts->time_step;
2327   PetscFunctionReturn(0);
2328 }
2329 
2330 /*@
2331    TSGetSolution - Returns the solution at the present timestep. It
2332    is valid to call this routine inside the function that you are evaluating
2333    in order to move to the new timestep. This vector not changed until
2334    the solution at the next timestep has been calculated.
2335 
2336    Not Collective, but Vec returned is parallel if TS is parallel
2337 
2338    Input Parameter:
2339 .  ts - the TS context obtained from TSCreate()
2340 
2341    Output Parameter:
2342 .  v - the vector containing the solution
2343 
2344    Note: If you used TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP); this does not return the solution at the requested
2345    final time. It returns the solution at the next timestep.
2346 
2347    Level: intermediate
2348 
2349 .seealso: TSGetTimeStep(), TSGetTime(), TSGetSolveTime(), TSGetSolutionComponents(), TSSetSolutionFunction()
2350 
2351 .keywords: TS, timestep, get, solution
2352 @*/
2353 PetscErrorCode  TSGetSolution(TS ts,Vec *v)
2354 {
2355   PetscFunctionBegin;
2356   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2357   PetscValidPointer(v,2);
2358   *v = ts->vec_sol;
2359   PetscFunctionReturn(0);
2360 }
2361 
2362 /*@
2363    TSGetSolutionComponents - Returns any solution components at the present
2364    timestep, if available for the time integration method being used.
2365    Solution components are quantities that share the same size and
2366    structure as the solution vector.
2367 
2368    Not Collective, but Vec returned is parallel if TS is parallel
2369 
2370    Parameters :
2371 .  ts - the TS context obtained from TSCreate() (input parameter).
2372 .  n - If v is PETSC_NULL, then the number of solution components is
2373        returned through n, else the n-th solution component is
2374        returned in v.
2375 .  v - the vector containing the n-th solution component
2376        (may be PETSC_NULL to use this function to find out
2377         the number of solutions components).
2378 
2379    Level: advanced
2380 
2381 .seealso: TSGetSolution()
2382 
2383 .keywords: TS, timestep, get, solution
2384 @*/
2385 PetscErrorCode  TSGetSolutionComponents(TS ts,PetscInt *n,Vec *v)
2386 {
2387   PetscErrorCode ierr;
2388 
2389   PetscFunctionBegin;
2390   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2391   if (!ts->ops->getsolutioncomponents) *n = 0;
2392   else {
2393     ierr = (*ts->ops->getsolutioncomponents)(ts,n,v);CHKERRQ(ierr);
2394   }
2395   PetscFunctionReturn(0);
2396 }
2397 
2398 /*@
2399    TSGetAuxSolution - Returns an auxiliary solution at the present
2400    timestep, if available for the time integration method being used.
2401 
2402    Not Collective, but Vec returned is parallel if TS is parallel
2403 
2404    Parameters :
2405 .  ts - the TS context obtained from TSCreate() (input parameter).
2406 .  v - the vector containing the auxiliary solution
2407 
2408    Level: intermediate
2409 
2410 .seealso: TSGetSolution()
2411 
2412 .keywords: TS, timestep, get, solution
2413 @*/
2414 PetscErrorCode  TSGetAuxSolution(TS ts,Vec *v)
2415 {
2416   PetscErrorCode ierr;
2417 
2418   PetscFunctionBegin;
2419   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2420   if (ts->ops->getauxsolution) {
2421     ierr = (*ts->ops->getauxsolution)(ts,v);CHKERRQ(ierr);
2422   } else {
2423     ierr = VecZeroEntries(*v); CHKERRQ(ierr);
2424   }
2425   PetscFunctionReturn(0);
2426 }
2427 
2428 /*@
2429    TSGetTimeError - Returns the estimated error vector, if the chosen
2430    TSType has an error estimation functionality.
2431 
2432    Not Collective, but Vec returned is parallel if TS is parallel
2433 
2434    Note: MUST call after TSSetUp()
2435 
2436    Parameters :
2437 .  ts - the TS context obtained from TSCreate() (input parameter).
2438 .  n - current estimate (n=0) or previous one (n=-1)
2439 .  v - the vector containing the error (same size as the solution).
2440 
2441    Level: intermediate
2442 
2443 .seealso: TSGetSolution(), TSSetTimeError()
2444 
2445 .keywords: TS, timestep, get, error
2446 @*/
2447 PetscErrorCode  TSGetTimeError(TS ts,PetscInt n,Vec *v)
2448 {
2449   PetscErrorCode ierr;
2450 
2451   PetscFunctionBegin;
2452   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2453   if (ts->ops->gettimeerror) {
2454     ierr = (*ts->ops->gettimeerror)(ts,n,v);CHKERRQ(ierr);
2455   } else {
2456     ierr = VecZeroEntries(*v);CHKERRQ(ierr);
2457   }
2458   PetscFunctionReturn(0);
2459 }
2460 
2461 /*@
2462    TSSetTimeError - Sets the estimated error vector, if the chosen
2463    TSType has an error estimation functionality. This can be used
2464    to restart such a time integrator with a given error vector.
2465 
2466    Not Collective, but Vec returned is parallel if TS is parallel
2467 
2468    Parameters :
2469 .  ts - the TS context obtained from TSCreate() (input parameter).
2470 .  v - the vector containing the error (same size as the solution).
2471 
2472    Level: intermediate
2473 
2474 .seealso: TSSetSolution(), TSGetTimeError)
2475 
2476 .keywords: TS, timestep, get, error
2477 @*/
2478 PetscErrorCode  TSSetTimeError(TS ts,Vec v)
2479 {
2480   PetscErrorCode ierr;
2481 
2482   PetscFunctionBegin;
2483   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2484   if (!ts->setupcalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetUp() first");
2485   if (ts->ops->settimeerror) {
2486     ierr = (*ts->ops->settimeerror)(ts,v);CHKERRQ(ierr);
2487   }
2488   PetscFunctionReturn(0);
2489 }
2490 
2491 /*@
2492    TSGetCostGradients - Returns the gradients from the TSAdjointSolve()
2493 
2494    Not Collective, but Vec returned is parallel if TS is parallel
2495 
2496    Input Parameter:
2497 .  ts - the TS context obtained from TSCreate()
2498 
2499    Output Parameter:
2500 +  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
2501 -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
2502 
2503    Level: intermediate
2504 
2505 .seealso: TSGetTimeStep()
2506 
2507 .keywords: TS, timestep, get, sensitivity
2508 @*/
2509 PetscErrorCode  TSGetCostGradients(TS ts,PetscInt *numcost,Vec **lambda,Vec **mu)
2510 {
2511   PetscFunctionBegin;
2512   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2513   if (numcost) *numcost = ts->numcost;
2514   if (lambda)  *lambda  = ts->vecs_sensi;
2515   if (mu)      *mu      = ts->vecs_sensip;
2516   PetscFunctionReturn(0);
2517 }
2518 
2519 /* ----- Routines to initialize and destroy a timestepper ---- */
2520 /*@
2521   TSSetProblemType - Sets the type of problem to be solved.
2522 
2523   Not collective
2524 
2525   Input Parameters:
2526 + ts   - The TS
2527 - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
2528 .vb
2529          U_t - A U = 0      (linear)
2530          U_t - A(t) U = 0   (linear)
2531          F(t,U,U_t) = 0     (nonlinear)
2532 .ve
2533 
2534    Level: beginner
2535 
2536 .keywords: TS, problem type
2537 .seealso: TSSetUp(), TSProblemType, TS
2538 @*/
2539 PetscErrorCode  TSSetProblemType(TS ts, TSProblemType type)
2540 {
2541   PetscErrorCode ierr;
2542 
2543   PetscFunctionBegin;
2544   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2545   ts->problem_type = type;
2546   if (type == TS_LINEAR) {
2547     SNES snes;
2548     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2549     ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);
2550   }
2551   PetscFunctionReturn(0);
2552 }
2553 
2554 /*@C
2555   TSGetProblemType - Gets the type of problem to be solved.
2556 
2557   Not collective
2558 
2559   Input Parameter:
2560 . ts   - The TS
2561 
2562   Output Parameter:
2563 . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
2564 .vb
2565          M U_t = A U
2566          M(t) U_t = A(t) U
2567          F(t,U,U_t)
2568 .ve
2569 
2570    Level: beginner
2571 
2572 .keywords: TS, problem type
2573 .seealso: TSSetUp(), TSProblemType, TS
2574 @*/
2575 PetscErrorCode  TSGetProblemType(TS ts, TSProblemType *type)
2576 {
2577   PetscFunctionBegin;
2578   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2579   PetscValidIntPointer(type,2);
2580   *type = ts->problem_type;
2581   PetscFunctionReturn(0);
2582 }
2583 
2584 /*@
2585    TSSetUp - Sets up the internal data structures for the later use
2586    of a timestepper.
2587 
2588    Collective on TS
2589 
2590    Input Parameter:
2591 .  ts - the TS context obtained from TSCreate()
2592 
2593    Notes:
2594    For basic use of the TS solvers the user need not explicitly call
2595    TSSetUp(), since these actions will automatically occur during
2596    the call to TSStep() or TSSolve().  However, if one wishes to control this
2597    phase separately, TSSetUp() should be called after TSCreate()
2598    and optional routines of the form TSSetXXX(), but before TSStep() and TSSolve().
2599 
2600    Level: advanced
2601 
2602 .keywords: TS, timestep, setup
2603 
2604 .seealso: TSCreate(), TSStep(), TSDestroy(), TSSolve()
2605 @*/
2606 PetscErrorCode  TSSetUp(TS ts)
2607 {
2608   PetscErrorCode ierr;
2609   DM             dm;
2610   PetscErrorCode (*func)(SNES,Vec,Vec,void*);
2611   PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*);
2612   TSIFunction    ifun;
2613   TSIJacobian    ijac;
2614   TSI2Jacobian   i2jac;
2615   TSRHSJacobian  rhsjac;
2616   PetscBool      isnone;
2617 
2618   PetscFunctionBegin;
2619   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2620   if (ts->setupcalled) PetscFunctionReturn(0);
2621 
2622   if (!((PetscObject)ts)->type_name) {
2623     ierr = TSGetIFunction(ts,NULL,&ifun,NULL);CHKERRQ(ierr);
2624     ierr = TSSetType(ts,ifun ? TSBEULER : TSEULER);CHKERRQ(ierr);
2625   }
2626 
2627   if (!ts->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first");
2628 
2629   if (ts->rhsjacobian.reuse) {
2630     Mat Amat,Pmat;
2631     SNES snes;
2632     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2633     ierr = SNESGetJacobian(snes,&Amat,&Pmat,NULL,NULL);CHKERRQ(ierr);
2634     /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
2635      * have displaced the RHS matrix */
2636     if (Amat == ts->Arhs) {
2637       /* 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 */
2638       ierr = MatDuplicate(ts->Arhs,MAT_COPY_VALUES,&Amat);CHKERRQ(ierr);
2639       ierr = SNESSetJacobian(snes,Amat,NULL,NULL,NULL);CHKERRQ(ierr);
2640       ierr = MatDestroy(&Amat);CHKERRQ(ierr);
2641     }
2642     if (Pmat == ts->Brhs) {
2643       ierr = MatDuplicate(ts->Brhs,MAT_COPY_VALUES,&Pmat);CHKERRQ(ierr);
2644       ierr = SNESSetJacobian(snes,NULL,Pmat,NULL,NULL);CHKERRQ(ierr);
2645       ierr = MatDestroy(&Pmat);CHKERRQ(ierr);
2646     }
2647   }
2648 
2649   ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr);
2650   ierr = TSAdaptSetDefaultType(ts->adapt,ts->default_adapt_type);CHKERRQ(ierr);
2651 
2652   if (ts->ops->setup) {
2653     ierr = (*ts->ops->setup)(ts);CHKERRQ(ierr);
2654   }
2655 
2656   /* Attempt to check/preset a default value for the exact final time option */
2657   ierr = PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&isnone);CHKERRQ(ierr);
2658   if (!isnone && ts->exact_final_time == TS_EXACTFINALTIME_UNSPECIFIED)
2659     ts->exact_final_time = TS_EXACTFINALTIME_MATCHSTEP;
2660 
2661   /* In the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
2662      to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
2663    */
2664   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2665   ierr = DMSNESGetFunction(dm,&func,NULL);CHKERRQ(ierr);
2666   if (!func) {
2667     ierr = DMSNESSetFunction(dm,SNESTSFormFunction,ts);CHKERRQ(ierr);
2668   }
2669   /* If the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
2670      Otherwise, the SNES will use coloring internally to form the Jacobian.
2671    */
2672   ierr = DMSNESGetJacobian(dm,&jac,NULL);CHKERRQ(ierr);
2673   ierr = DMTSGetIJacobian(dm,&ijac,NULL);CHKERRQ(ierr);
2674   ierr = DMTSGetI2Jacobian(dm,&i2jac,NULL);CHKERRQ(ierr);
2675   ierr = DMTSGetRHSJacobian(dm,&rhsjac,NULL);CHKERRQ(ierr);
2676   if (!jac && (ijac || i2jac || rhsjac)) {
2677     ierr = DMSNESSetJacobian(dm,SNESTSFormJacobian,ts);CHKERRQ(ierr);
2678   }
2679 
2680   /* if time integration scheme has a starting method, call it */
2681   if (ts->ops->startingmethod) {
2682     ierr = (*ts->ops->startingmethod)(ts);CHKERRQ(ierr);
2683   }
2684 
2685   ts->setupcalled = PETSC_TRUE;
2686   PetscFunctionReturn(0);
2687 }
2688 
2689 /*@
2690    TSAdjointSetUp - Sets up the internal data structures for the later use
2691    of an adjoint solver
2692 
2693    Collective on TS
2694 
2695    Input Parameter:
2696 .  ts - the TS context obtained from TSCreate()
2697 
2698    Level: advanced
2699 
2700 .keywords: TS, timestep, setup
2701 
2702 .seealso: TSCreate(), TSAdjointStep(), TSSetCostGradients()
2703 @*/
2704 PetscErrorCode  TSAdjointSetUp(TS ts)
2705 {
2706   PetscErrorCode ierr;
2707 
2708   PetscFunctionBegin;
2709   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2710   if (ts->adjointsetupcalled) PetscFunctionReturn(0);
2711   if (!ts->vecs_sensi) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetCostGradients() first");
2712   if (ts->vecs_sensip && !ts->Jacp) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"Must call TSAdjointSetRHSJacobian() first");
2713 
2714   if (ts->vec_costintegral) { /* if there is integral in the cost function */
2715     ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&ts->vecs_drdy);CHKERRQ(ierr);
2716     if (ts->vecs_sensip){
2717       ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
2718     }
2719   }
2720 
2721   if (ts->ops->adjointsetup) {
2722     ierr = (*ts->ops->adjointsetup)(ts);CHKERRQ(ierr);
2723   }
2724   ts->adjointsetupcalled = PETSC_TRUE;
2725   PetscFunctionReturn(0);
2726 }
2727 
2728 /*@
2729    TSReset - Resets a TS context and removes any allocated Vecs and Mats.
2730 
2731    Collective on TS
2732 
2733    Input Parameter:
2734 .  ts - the TS context obtained from TSCreate()
2735 
2736    Level: beginner
2737 
2738 .keywords: TS, timestep, reset
2739 
2740 .seealso: TSCreate(), TSSetup(), TSDestroy()
2741 @*/
2742 PetscErrorCode  TSReset(TS ts)
2743 {
2744   PetscErrorCode ierr;
2745 
2746   PetscFunctionBegin;
2747   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2748 
2749   if (ts->ops->reset) {
2750     ierr = (*ts->ops->reset)(ts);CHKERRQ(ierr);
2751   }
2752   if (ts->snes) {ierr = SNESReset(ts->snes);CHKERRQ(ierr);}
2753   if (ts->adapt) {ierr = TSAdaptReset(ts->adapt);CHKERRQ(ierr);}
2754 
2755   ierr = MatDestroy(&ts->Arhs);CHKERRQ(ierr);
2756   ierr = MatDestroy(&ts->Brhs);CHKERRQ(ierr);
2757   ierr = VecDestroy(&ts->Frhs);CHKERRQ(ierr);
2758   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
2759   ierr = VecDestroy(&ts->vec_dot);CHKERRQ(ierr);
2760   ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
2761   ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
2762   ierr = VecDestroyVecs(ts->nwork,&ts->work);CHKERRQ(ierr);
2763 
2764   ierr = VecDestroyVecs(ts->numcost,&ts->vecs_drdy);CHKERRQ(ierr);
2765   ierr = VecDestroyVecs(ts->numcost,&ts->vecs_drdp);CHKERRQ(ierr);
2766 
2767   ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
2768   ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr);
2769   ierr = VecDestroy(&ts->vec_costintegrand);CHKERRQ(ierr);
2770   ierr = MatDestroy(&ts->mat_sensip);CHKERRQ(ierr);
2771 
2772   ts->setupcalled = PETSC_FALSE;
2773   PetscFunctionReturn(0);
2774 }
2775 
2776 /*@
2777    TSDestroy - Destroys the timestepper context that was created
2778    with TSCreate().
2779 
2780    Collective on TS
2781 
2782    Input Parameter:
2783 .  ts - the TS context obtained from TSCreate()
2784 
2785    Level: beginner
2786 
2787 .keywords: TS, timestepper, destroy
2788 
2789 .seealso: TSCreate(), TSSetUp(), TSSolve()
2790 @*/
2791 PetscErrorCode  TSDestroy(TS *ts)
2792 {
2793   PetscErrorCode ierr;
2794 
2795   PetscFunctionBegin;
2796   if (!*ts) PetscFunctionReturn(0);
2797   PetscValidHeaderSpecific((*ts),TS_CLASSID,1);
2798   if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; PetscFunctionReturn(0);}
2799 
2800   ierr = TSReset((*ts));CHKERRQ(ierr);
2801 
2802   /* if memory was published with SAWs then destroy it */
2803   ierr = PetscObjectSAWsViewOff((PetscObject)*ts);CHKERRQ(ierr);
2804   if ((*ts)->ops->destroy) {ierr = (*(*ts)->ops->destroy)((*ts));CHKERRQ(ierr);}
2805 
2806   ierr = TSTrajectoryDestroy(&(*ts)->trajectory);CHKERRQ(ierr);
2807 
2808   ierr = TSAdaptDestroy(&(*ts)->adapt);CHKERRQ(ierr);
2809   ierr = TSEventDestroy(&(*ts)->event);CHKERRQ(ierr);
2810 
2811   ierr = SNESDestroy(&(*ts)->snes);CHKERRQ(ierr);
2812   ierr = DMDestroy(&(*ts)->dm);CHKERRQ(ierr);
2813   ierr = TSMonitorCancel((*ts));CHKERRQ(ierr);
2814   ierr = TSAdjointMonitorCancel((*ts));CHKERRQ(ierr);
2815 
2816   ierr = PetscHeaderDestroy(ts);CHKERRQ(ierr);
2817   PetscFunctionReturn(0);
2818 }
2819 
2820 /*@
2821    TSGetSNES - Returns the SNES (nonlinear solver) associated with
2822    a TS (timestepper) context. Valid only for nonlinear problems.
2823 
2824    Not Collective, but SNES is parallel if TS is parallel
2825 
2826    Input Parameter:
2827 .  ts - the TS context obtained from TSCreate()
2828 
2829    Output Parameter:
2830 .  snes - the nonlinear solver context
2831 
2832    Notes:
2833    The user can then directly manipulate the SNES context to set various
2834    options, etc.  Likewise, the user can then extract and manipulate the
2835    KSP, KSP, and PC contexts as well.
2836 
2837    TSGetSNES() does not work for integrators that do not use SNES; in
2838    this case TSGetSNES() returns NULL in snes.
2839 
2840    Level: beginner
2841 
2842 .keywords: timestep, get, SNES
2843 @*/
2844 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
2845 {
2846   PetscErrorCode ierr;
2847 
2848   PetscFunctionBegin;
2849   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2850   PetscValidPointer(snes,2);
2851   if (!ts->snes) {
2852     ierr = SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes);CHKERRQ(ierr);
2853     ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2854     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->snes);CHKERRQ(ierr);
2855     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);CHKERRQ(ierr);
2856     if (ts->dm) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
2857     if (ts->problem_type == TS_LINEAR) {
2858       ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr);
2859     }
2860   }
2861   *snes = ts->snes;
2862   PetscFunctionReturn(0);
2863 }
2864 
2865 /*@
2866    TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
2867 
2868    Collective
2869 
2870    Input Parameter:
2871 +  ts - the TS context obtained from TSCreate()
2872 -  snes - the nonlinear solver context
2873 
2874    Notes:
2875    Most users should have the TS created by calling TSGetSNES()
2876 
2877    Level: developer
2878 
2879 .keywords: timestep, set, SNES
2880 @*/
2881 PetscErrorCode TSSetSNES(TS ts,SNES snes)
2882 {
2883   PetscErrorCode ierr;
2884   PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*);
2885 
2886   PetscFunctionBegin;
2887   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2888   PetscValidHeaderSpecific(snes,SNES_CLASSID,2);
2889   ierr = PetscObjectReference((PetscObject)snes);CHKERRQ(ierr);
2890   ierr = SNESDestroy(&ts->snes);CHKERRQ(ierr);
2891 
2892   ts->snes = snes;
2893 
2894   ierr = SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
2895   ierr = SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL);CHKERRQ(ierr);
2896   if (func == SNESTSFormJacobian) {
2897     ierr = SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts);CHKERRQ(ierr);
2898   }
2899   PetscFunctionReturn(0);
2900 }
2901 
2902 /*@
2903    TSGetKSP - Returns the KSP (linear solver) associated with
2904    a TS (timestepper) context.
2905 
2906    Not Collective, but KSP is parallel if TS is parallel
2907 
2908    Input Parameter:
2909 .  ts - the TS context obtained from TSCreate()
2910 
2911    Output Parameter:
2912 .  ksp - the nonlinear solver context
2913 
2914    Notes:
2915    The user can then directly manipulate the KSP context to set various
2916    options, etc.  Likewise, the user can then extract and manipulate the
2917    KSP and PC contexts as well.
2918 
2919    TSGetKSP() does not work for integrators that do not use KSP;
2920    in this case TSGetKSP() returns NULL in ksp.
2921 
2922    Level: beginner
2923 
2924 .keywords: timestep, get, KSP
2925 @*/
2926 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
2927 {
2928   PetscErrorCode ierr;
2929   SNES           snes;
2930 
2931   PetscFunctionBegin;
2932   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2933   PetscValidPointer(ksp,2);
2934   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
2935   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
2936   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2937   ierr = SNESGetKSP(snes,ksp);CHKERRQ(ierr);
2938   PetscFunctionReturn(0);
2939 }
2940 
2941 /* ----------- Routines to set solver parameters ---------- */
2942 
2943 /*@
2944    TSSetMaxSteps - Sets the maximum number of steps to use.
2945 
2946    Logically Collective on TS
2947 
2948    Input Parameters:
2949 +  ts - the TS context obtained from TSCreate()
2950 -  maxsteps - maximum number of steps to use
2951 
2952    Options Database Keys:
2953 .  -ts_max_steps <maxsteps> - Sets maxsteps
2954 
2955    Notes:
2956    The default maximum number of steps is 5000
2957 
2958    Level: intermediate
2959 
2960 .keywords: TS, timestep, set, maximum, steps
2961 
2962 .seealso: TSGetMaxSteps(), TSSetMaxTime(), TSSetExactFinalTime()
2963 @*/
2964 PetscErrorCode TSSetMaxSteps(TS ts,PetscInt maxsteps)
2965 {
2966   PetscFunctionBegin;
2967   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2968   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
2969   if (maxsteps < 0 ) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of steps must be non-negative");
2970   ts->max_steps = maxsteps;
2971   PetscFunctionReturn(0);
2972 }
2973 
2974 /*@
2975    TSGetMaxSteps - Gets the maximum number of steps to use.
2976 
2977    Not Collective
2978 
2979    Input Parameters:
2980 .  ts - the TS context obtained from TSCreate()
2981 
2982    Output Parameter:
2983 .  maxsteps - maximum number of steps to use
2984 
2985    Level: advanced
2986 
2987 .keywords: TS, timestep, get, maximum, steps
2988 
2989 .seealso: TSSetMaxSteps(), TSGetMaxTime(), TSSetMaxTime()
2990 @*/
2991 PetscErrorCode TSGetMaxSteps(TS ts,PetscInt *maxsteps)
2992 {
2993   PetscFunctionBegin;
2994   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2995   PetscValidIntPointer(maxsteps,2);
2996   *maxsteps = ts->max_steps;
2997   PetscFunctionReturn(0);
2998 }
2999 
3000 /*@
3001    TSSetMaxTime - Sets the maximum (or final) time for timestepping.
3002 
3003    Logically Collective on TS
3004 
3005    Input Parameters:
3006 +  ts - the TS context obtained from TSCreate()
3007 -  maxtime - final time to step to
3008 
3009    Options Database Keys:
3010 .  -ts_max_time <maxtime> - Sets maxtime
3011 
3012    Notes:
3013    The default maximum time is 5.0
3014 
3015    Level: intermediate
3016 
3017 .keywords: TS, timestep, set, maximum, time
3018 
3019 .seealso: TSGetMaxTime(), TSSetMaxSteps(), TSSetExactFinalTime()
3020 @*/
3021 PetscErrorCode TSSetMaxTime(TS ts,PetscReal maxtime)
3022 {
3023   PetscFunctionBegin;
3024   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3025   PetscValidLogicalCollectiveReal(ts,maxtime,2);
3026   ts->max_time = maxtime;
3027   PetscFunctionReturn(0);
3028 }
3029 
3030 /*@
3031    TSGetMaxTime - Gets the maximum (or final) time for timestepping.
3032 
3033    Not Collective
3034 
3035    Input Parameters:
3036 .  ts - the TS context obtained from TSCreate()
3037 
3038    Output Parameter:
3039 .  maxtime - final time to step to
3040 
3041    Level: advanced
3042 
3043 .keywords: TS, timestep, get, maximum, time
3044 
3045 .seealso: TSSetMaxTime(), TSGetMaxSteps(), TSSetMaxSteps()
3046 @*/
3047 PetscErrorCode TSGetMaxTime(TS ts,PetscReal *maxtime)
3048 {
3049   PetscFunctionBegin;
3050   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3051   PetscValidRealPointer(maxtime,2);
3052   *maxtime = ts->max_time;
3053   PetscFunctionReturn(0);
3054 }
3055 
3056 /*@
3057    TSSetInitialTimeStep - Deprecated, use TSSetTime() and TSSetTimeStep().
3058 
3059    Level: deprecated
3060 
3061 @*/
3062 PetscErrorCode  TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step)
3063 {
3064   PetscErrorCode ierr;
3065   PetscFunctionBegin;
3066   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3067   ierr = TSSetTime(ts,initial_time);CHKERRQ(ierr);
3068   ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr);
3069   PetscFunctionReturn(0);
3070 }
3071 
3072 /*@
3073    TSGetDuration - Deprecated, use TSGetMaxSteps() and TSGetMaxTime().
3074 
3075    Level: deprecated
3076 
3077 @*/
3078 PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
3079 {
3080   PetscFunctionBegin;
3081   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3082   if (maxsteps) {
3083     PetscValidIntPointer(maxsteps,2);
3084     *maxsteps = ts->max_steps;
3085   }
3086   if (maxtime) {
3087     PetscValidScalarPointer(maxtime,3);
3088     *maxtime = ts->max_time;
3089   }
3090   PetscFunctionReturn(0);
3091 }
3092 
3093 /*@
3094    TSSetDuration - Deprecated, use TSSetMaxSteps() and TSSetMaxTime().
3095 
3096    Level: deprecated
3097 
3098 @*/
3099 PetscErrorCode TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
3100 {
3101   PetscFunctionBegin;
3102   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3103   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
3104   PetscValidLogicalCollectiveReal(ts,maxtime,2);
3105   if (maxsteps >= 0) ts->max_steps = maxsteps;
3106   if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
3107   PetscFunctionReturn(0);
3108 }
3109 
3110 /*@
3111    TSGetTimeStepNumber - Deprecated, use TSGetStepNumber().
3112 
3113    Level: deprecated
3114 
3115 @*/
3116 PetscErrorCode TSGetTimeStepNumber(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); }
3117 
3118 /*@
3119    TSGetTotalSteps - Deprecated, use TSGetStepNumber().
3120 
3121    Level: deprecated
3122 
3123 @*/
3124 PetscErrorCode TSGetTotalSteps(TS ts,PetscInt *steps) { return TSGetStepNumber(ts,steps); }
3125 
3126 /*@
3127    TSSetSolution - Sets the initial solution vector
3128    for use by the TS routines.
3129 
3130    Logically Collective on TS and Vec
3131 
3132    Input Parameters:
3133 +  ts - the TS context obtained from TSCreate()
3134 -  u - the solution vector
3135 
3136    Level: beginner
3137 
3138 .keywords: TS, timestep, set, solution, initial values
3139 
3140 .seealso: TSSetSolutionFunction(), TSGetSolution(), TSCreate()
3141 @*/
3142 PetscErrorCode  TSSetSolution(TS ts,Vec u)
3143 {
3144   PetscErrorCode ierr;
3145   DM             dm;
3146 
3147   PetscFunctionBegin;
3148   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3149   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
3150   ierr = PetscObjectReference((PetscObject)u);CHKERRQ(ierr);
3151   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
3152   ts->vec_sol = u;
3153 
3154   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
3155   ierr = DMShellSetGlobalVector(dm,u);CHKERRQ(ierr);
3156   PetscFunctionReturn(0);
3157 }
3158 
3159 /*@
3160    TSAdjointSetSteps - Sets the number of steps the adjoint solver should take backward in time
3161 
3162    Logically Collective on TS
3163 
3164    Input Parameters:
3165 +  ts - the TS context obtained from TSCreate()
3166 .  steps - number of steps to use
3167 
3168    Level: intermediate
3169 
3170    Notes: Normally one does not call this and TSAdjointSolve() integrates back to the original timestep. One can call this
3171           so as to integrate back to less than the original timestep
3172 
3173 .keywords: TS, timestep, set, maximum, iterations
3174 
3175 .seealso: TSSetExactFinalTime()
3176 @*/
3177 PetscErrorCode  TSAdjointSetSteps(TS ts,PetscInt steps)
3178 {
3179   PetscFunctionBegin;
3180   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3181   PetscValidLogicalCollectiveInt(ts,steps,2);
3182   if (steps < 0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back a negative number of steps");
3183   if (steps > ts->steps) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Cannot step back more than the total number of forward steps");
3184   ts->adjoint_max_steps = steps;
3185   PetscFunctionReturn(0);
3186 }
3187 
3188 /*@
3189    TSSetCostGradients - Sets the initial value of the gradients of the cost function w.r.t. initial values and w.r.t. the problem parameters
3190       for use by the TSAdjoint routines.
3191 
3192    Logically Collective on TS and Vec
3193 
3194    Input Parameters:
3195 +  ts - the TS context obtained from TSCreate()
3196 .  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
3197 -  mu - gradients with respect to the parameters, the number of entries in these vectors is the same as the number of parameters
3198 
3199    Level: beginner
3200 
3201    Notes: the entries in these vectors must be correctly initialized with the values lamda_i = df/dy|finaltime  mu_i = df/dp|finaltime
3202 
3203    After TSAdjointSolve() is called the lamba and the mu contain the computed sensitivities
3204 
3205 .keywords: TS, timestep, set, sensitivity, initial values
3206 @*/
3207 PetscErrorCode  TSSetCostGradients(TS ts,PetscInt numcost,Vec *lambda,Vec *mu)
3208 {
3209   PetscFunctionBegin;
3210   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3211   PetscValidPointer(lambda,2);
3212   ts->vecs_sensi  = lambda;
3213   ts->vecs_sensip = mu;
3214   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");
3215   ts->numcost  = numcost;
3216   PetscFunctionReturn(0);
3217 }
3218 
3219 /*@C
3220   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.
3221 
3222   Logically Collective on TS
3223 
3224   Input Parameters:
3225 + ts   - The TS context obtained from TSCreate()
3226 - func - The function
3227 
3228   Calling sequence of func:
3229 $ func (TS ts,PetscReal t,Vec y,Mat A,void *ctx);
3230 +   t - current timestep
3231 .   y - input vector (current ODE solution)
3232 .   A - output matrix
3233 -   ctx - [optional] user-defined function context
3234 
3235   Level: intermediate
3236 
3237   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
3238 
3239 .keywords: TS, sensitivity
3240 .seealso:
3241 @*/
3242 PetscErrorCode  TSAdjointSetRHSJacobian(TS ts,Mat Amat,PetscErrorCode (*func)(TS,PetscReal,Vec,Mat,void*),void *ctx)
3243 {
3244   PetscErrorCode ierr;
3245 
3246   PetscFunctionBegin;
3247   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3248   PetscValidHeaderSpecific(Amat,MAT_CLASSID,2);
3249 
3250   ts->rhsjacobianp    = func;
3251   ts->rhsjacobianpctx = ctx;
3252   if(Amat) {
3253     ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr);
3254     ierr = MatDestroy(&ts->Jacp);CHKERRQ(ierr);
3255     ts->Jacp = Amat;
3256   }
3257   PetscFunctionReturn(0);
3258 }
3259 
3260 /*@C
3261   TSAdjointComputeRHSJacobian - Runs the user-defined Jacobian function.
3262 
3263   Collective on TS
3264 
3265   Input Parameters:
3266 . ts   - The TS context obtained from TSCreate()
3267 
3268   Level: developer
3269 
3270 .keywords: TS, sensitivity
3271 .seealso: TSAdjointSetRHSJacobian()
3272 @*/
3273 PetscErrorCode  TSAdjointComputeRHSJacobian(TS ts,PetscReal t,Vec X,Mat Amat)
3274 {
3275   PetscErrorCode ierr;
3276 
3277   PetscFunctionBegin;
3278   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3279   PetscValidHeaderSpecific(X,VEC_CLASSID,3);
3280   PetscValidPointer(Amat,4);
3281 
3282   PetscStackPush("TS user JacobianP function for sensitivity analysis");
3283   ierr = (*ts->rhsjacobianp)(ts,t,X,Amat,ts->rhsjacobianpctx); CHKERRQ(ierr);
3284   PetscStackPop;
3285   PetscFunctionReturn(0);
3286 }
3287 
3288 /*@C
3289     TSSetCostIntegrand - Sets the routine for evaluating the integral term in one or more cost functions
3290 
3291     Logically Collective on TS
3292 
3293     Input Parameters:
3294 +   ts - the TS context obtained from TSCreate()
3295 .   numcost - number of gradients to be computed, this is the number of cost functions
3296 .   costintegral - vector that stores the integral values
3297 .   rf - routine for evaluating the integrand function
3298 .   drdyf - function that computes the gradients of the r's with respect to y,NULL if not a function y
3299 .   drdpf - function that computes the gradients of the r's with respect to p, NULL if not a function of p
3300 .   fwd - flag indicating whether to evaluate cost integral in the forward run or the adjoint run
3301 -   ctx - [optional] user-defined context for private data for the function evaluation routine (may be NULL)
3302 
3303     Calling sequence of rf:
3304 $   PetscErrorCode rf(TS ts,PetscReal t,Vec y,Vec f,void *ctx);
3305 
3306     Calling sequence of drdyf:
3307 $   PetscErroCode drdyf(TS ts,PetscReal t,Vec y,Vec *drdy,void *ctx);
3308 
3309     Calling sequence of drdpf:
3310 $   PetscErroCode drdpf(TS ts,PetscReal t,Vec y,Vec *drdp,void *ctx);
3311 
3312     Level: intermediate
3313 
3314     Notes: For optimization there is usually a single cost function (numcost = 1). For sensitivities there may be multiple cost functions
3315 
3316 .keywords: TS, sensitivity analysis, timestep, set, quadrature, function
3317 
3318 .seealso: TSAdjointSetRHSJacobian(),TSGetCostGradients(), TSSetCostGradients()
3319 @*/
3320 PetscErrorCode  TSSetCostIntegrand(TS ts,PetscInt numcost,Vec costintegral,PetscErrorCode (*rf)(TS,PetscReal,Vec,Vec,void*),
3321                                                           PetscErrorCode (*drdyf)(TS,PetscReal,Vec,Vec*,void*),
3322                                                           PetscErrorCode (*drdpf)(TS,PetscReal,Vec,Vec*,void*),
3323                                                           PetscBool fwd,void *ctx)
3324 {
3325   PetscErrorCode ierr;
3326 
3327   PetscFunctionBegin;
3328   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3329   if (costintegral) PetscValidHeaderSpecific(costintegral,VEC_CLASSID,3);
3330   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()");
3331   if (!ts->numcost) ts->numcost=numcost;
3332 
3333   if (costintegral) {
3334     ierr = PetscObjectReference((PetscObject)costintegral);CHKERRQ(ierr);
3335     ierr = VecDestroy(&ts->vec_costintegral);CHKERRQ(ierr);
3336     ts->vec_costintegral = costintegral;
3337   } else {
3338     if (!ts->vec_costintegral) { /* Create a seq vec if user does not provide one */
3339       ierr = VecCreateSeq(PETSC_COMM_SELF,numcost,&ts->vec_costintegral);CHKERRQ(ierr);
3340     } else {
3341       ierr = VecSet(ts->vec_costintegral,0.0);CHKERRQ(ierr);
3342     }
3343   }
3344   if (!ts->vec_costintegrand) {
3345     ierr = VecDuplicate(ts->vec_costintegral,&ts->vec_costintegrand);CHKERRQ(ierr);
3346   } else {
3347     ierr = VecSet(ts->vec_costintegrand,0.0);CHKERRQ(ierr);
3348   }
3349   ts->costintegralfwd  = fwd; /* Evaluate the cost integral in forward run if fwd is true */
3350   ts->costintegrand    = rf;
3351   ts->costintegrandctx = ctx;
3352   ts->drdyfunction     = drdyf;
3353   ts->drdpfunction     = drdpf;
3354   PetscFunctionReturn(0);
3355 }
3356 
3357 /*@
3358    TSGetCostIntegral - Returns the values of the integral term in the cost functions.
3359    It is valid to call the routine after a backward run.
3360 
3361    Not Collective
3362 
3363    Input Parameter:
3364 .  ts - the TS context obtained from TSCreate()
3365 
3366    Output Parameter:
3367 .  v - the vector containing the integrals for each cost function
3368 
3369    Level: intermediate
3370 
3371 .seealso: TSSetCostIntegrand()
3372 
3373 .keywords: TS, sensitivity analysis
3374 @*/
3375 PetscErrorCode  TSGetCostIntegral(TS ts,Vec *v)
3376 {
3377   PetscFunctionBegin;
3378   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3379   PetscValidPointer(v,2);
3380   *v = ts->vec_costintegral;
3381   PetscFunctionReturn(0);
3382 }
3383 
3384 /*@
3385    TSComputeCostIntegrand - Evaluates the integral function in the cost functions.
3386 
3387    Input Parameters:
3388 +  ts - the TS context
3389 .  t - current time
3390 -  y - state vector, i.e. current solution
3391 
3392    Output Parameter:
3393 .  q - vector of size numcost to hold the outputs
3394 
3395    Note:
3396    Most users should not need to explicitly call this routine, as it
3397    is used internally within the sensitivity analysis context.
3398 
3399    Level: developer
3400 
3401 .keywords: TS, compute
3402 
3403 .seealso: TSSetCostIntegrand()
3404 @*/
3405 PetscErrorCode TSComputeCostIntegrand(TS ts,PetscReal t,Vec y,Vec q)
3406 {
3407   PetscErrorCode ierr;
3408 
3409   PetscFunctionBegin;
3410   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3411   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3412   PetscValidHeaderSpecific(q,VEC_CLASSID,4);
3413 
3414   ierr = PetscLogEventBegin(TS_FunctionEval,ts,y,q,0);CHKERRQ(ierr);
3415   if (ts->costintegrand) {
3416     PetscStackPush("TS user integrand in the cost function");
3417     ierr = (*ts->costintegrand)(ts,t,y,q,ts->costintegrandctx);CHKERRQ(ierr);
3418     PetscStackPop;
3419   } else {
3420     ierr = VecZeroEntries(q);CHKERRQ(ierr);
3421   }
3422 
3423   ierr = PetscLogEventEnd(TS_FunctionEval,ts,y,q,0);CHKERRQ(ierr);
3424   PetscFunctionReturn(0);
3425 }
3426 
3427 /*@
3428   TSAdjointComputeDRDYFunction - Runs the user-defined DRDY function.
3429 
3430   Collective on TS
3431 
3432   Input Parameters:
3433 . ts   - The TS context obtained from TSCreate()
3434 
3435   Notes:
3436   TSAdjointComputeDRDYFunction() is typically used for sensitivity implementation,
3437   so most users would not generally call this routine themselves.
3438 
3439   Level: developer
3440 
3441 .keywords: TS, sensitivity
3442 .seealso: TSAdjointComputeDRDYFunction()
3443 @*/
3444 PetscErrorCode  TSAdjointComputeDRDYFunction(TS ts,PetscReal t,Vec y,Vec *drdy)
3445 {
3446   PetscErrorCode ierr;
3447 
3448   PetscFunctionBegin;
3449   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3450   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3451 
3452   PetscStackPush("TS user DRDY function for sensitivity analysis");
3453   ierr = (*ts->drdyfunction)(ts,t,y,drdy,ts->costintegrandctx); CHKERRQ(ierr);
3454   PetscStackPop;
3455   PetscFunctionReturn(0);
3456 }
3457 
3458 /*@
3459   TSAdjointComputeDRDPFunction - Runs the user-defined DRDP function.
3460 
3461   Collective on TS
3462 
3463   Input Parameters:
3464 . ts   - The TS context obtained from TSCreate()
3465 
3466   Notes:
3467   TSDRDPFunction() is typically used for sensitivity implementation,
3468   so most users would not generally call this routine themselves.
3469 
3470   Level: developer
3471 
3472 .keywords: TS, sensitivity
3473 .seealso: TSAdjointSetDRDPFunction()
3474 @*/
3475 PetscErrorCode  TSAdjointComputeDRDPFunction(TS ts,PetscReal t,Vec y,Vec *drdp)
3476 {
3477   PetscErrorCode ierr;
3478 
3479   PetscFunctionBegin;
3480   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3481   PetscValidHeaderSpecific(y,VEC_CLASSID,3);
3482 
3483   PetscStackPush("TS user DRDP function for sensitivity analysis");
3484   ierr = (*ts->drdpfunction)(ts,t,y,drdp,ts->costintegrandctx); CHKERRQ(ierr);
3485   PetscStackPop;
3486   PetscFunctionReturn(0);
3487 }
3488 
3489 /*@C
3490   TSSetPreStep - Sets the general-purpose function
3491   called once at the beginning of each time step.
3492 
3493   Logically Collective on TS
3494 
3495   Input Parameters:
3496 + ts   - The TS context obtained from TSCreate()
3497 - func - The function
3498 
3499   Calling sequence of func:
3500 . func (TS ts);
3501 
3502   Level: intermediate
3503 
3504 .keywords: TS, timestep
3505 .seealso: TSSetPreStage(), TSSetPostStage(), TSSetPostStep(), TSStep(), TSRestartStep()
3506 @*/
3507 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
3508 {
3509   PetscFunctionBegin;
3510   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3511   ts->prestep = func;
3512   PetscFunctionReturn(0);
3513 }
3514 
3515 /*@
3516   TSPreStep - Runs the user-defined pre-step function.
3517 
3518   Collective on TS
3519 
3520   Input Parameters:
3521 . ts   - The TS context obtained from TSCreate()
3522 
3523   Notes:
3524   TSPreStep() is typically used within time stepping implementations,
3525   so most users would not generally call this routine themselves.
3526 
3527   Level: developer
3528 
3529 .keywords: TS, timestep
3530 .seealso: TSSetPreStep(), TSPreStage(), TSPostStage(), TSPostStep()
3531 @*/
3532 PetscErrorCode  TSPreStep(TS ts)
3533 {
3534   PetscErrorCode ierr;
3535 
3536   PetscFunctionBegin;
3537   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3538   if (ts->prestep) {
3539     Vec              U;
3540     PetscObjectState sprev,spost;
3541 
3542     ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
3543     ierr = PetscObjectStateGet((PetscObject)U,&sprev);CHKERRQ(ierr);
3544     PetscStackCallStandard((*ts->prestep),(ts));
3545     ierr = PetscObjectStateGet((PetscObject)U,&spost);CHKERRQ(ierr);
3546     if (sprev != spost) {ierr = TSRestartStep(ts);CHKERRQ(ierr);}
3547   }
3548   PetscFunctionReturn(0);
3549 }
3550 
3551 /*@C
3552   TSSetPreStage - Sets the general-purpose function
3553   called once at the beginning of each stage.
3554 
3555   Logically Collective on TS
3556 
3557   Input Parameters:
3558 + ts   - The TS context obtained from TSCreate()
3559 - func - The function
3560 
3561   Calling sequence of func:
3562 . PetscErrorCode func(TS ts, PetscReal stagetime);
3563 
3564   Level: intermediate
3565 
3566   Note:
3567   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3568   The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being
3569   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3570 
3571 .keywords: TS, timestep
3572 .seealso: TSSetPostStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3573 @*/
3574 PetscErrorCode  TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
3575 {
3576   PetscFunctionBegin;
3577   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3578   ts->prestage = func;
3579   PetscFunctionReturn(0);
3580 }
3581 
3582 /*@C
3583   TSSetPostStage - Sets the general-purpose function
3584   called once at the end of each stage.
3585 
3586   Logically Collective on TS
3587 
3588   Input Parameters:
3589 + ts   - The TS context obtained from TSCreate()
3590 - func - The function
3591 
3592   Calling sequence of func:
3593 . PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y);
3594 
3595   Level: intermediate
3596 
3597   Note:
3598   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
3599   The time step number being computed can be queried using TSGetStepNumber() and the total size of the step being
3600   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
3601 
3602 .keywords: TS, timestep
3603 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3604 @*/
3605 PetscErrorCode  TSSetPostStage(TS ts, PetscErrorCode (*func)(TS,PetscReal,PetscInt,Vec*))
3606 {
3607   PetscFunctionBegin;
3608   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3609   ts->poststage = func;
3610   PetscFunctionReturn(0);
3611 }
3612 
3613 /*@C
3614   TSSetPostEvaluate - Sets the general-purpose function
3615   called once at the end of each step evaluation.
3616 
3617   Logically Collective on TS
3618 
3619   Input Parameters:
3620 + ts   - The TS context obtained from TSCreate()
3621 - func - The function
3622 
3623   Calling sequence of func:
3624 . PetscErrorCode func(TS ts);
3625 
3626   Level: intermediate
3627 
3628   Note:
3629   Semantically, TSSetPostEvaluate() differs from TSSetPostStep() since the function it sets is called before event-handling
3630   thus guaranteeing the same solution (computed by the time-stepper) will be passed to it. On the other hand, TSPostStep()
3631   may be passed a different solution, possibly changed by the event handler. TSPostEvaluate() is called after the next step
3632   solution is evaluated allowing to modify it, if need be. The solution can be obtained with TSGetSolution(), the time step
3633   with TSGetTimeStep(), and the time at the start of the step is available via TSGetTime()
3634 
3635 .keywords: TS, timestep
3636 .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
3637 @*/
3638 PetscErrorCode  TSSetPostEvaluate(TS ts, PetscErrorCode (*func)(TS))
3639 {
3640   PetscFunctionBegin;
3641   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3642   ts->postevaluate = func;
3643   PetscFunctionReturn(0);
3644 }
3645 
3646 /*@
3647   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
3648 
3649   Collective on TS
3650 
3651   Input Parameters:
3652 . ts          - The TS context obtained from TSCreate()
3653   stagetime   - The absolute time of the current stage
3654 
3655   Notes:
3656   TSPreStage() is typically used within time stepping implementations,
3657   most users would not generally call this routine themselves.
3658 
3659   Level: developer
3660 
3661 .keywords: TS, timestep
3662 .seealso: TSPostStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
3663 @*/
3664 PetscErrorCode  TSPreStage(TS ts, PetscReal stagetime)
3665 {
3666   PetscErrorCode ierr;
3667 
3668   PetscFunctionBegin;
3669   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3670   if (ts->prestage) {
3671     PetscStackCallStandard((*ts->prestage),(ts,stagetime));
3672   }
3673   PetscFunctionReturn(0);
3674 }
3675 
3676 /*@
3677   TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage()
3678 
3679   Collective on TS
3680 
3681   Input Parameters:
3682 . ts          - The TS context obtained from TSCreate()
3683   stagetime   - The absolute time of the current stage
3684   stageindex  - Stage number
3685   Y           - Array of vectors (of size = total number
3686                 of stages) with the stage solutions
3687 
3688   Notes:
3689   TSPostStage() is typically used within time stepping implementations,
3690   most users would not generally call this routine themselves.
3691 
3692   Level: developer
3693 
3694 .keywords: TS, timestep
3695 .seealso: TSPreStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
3696 @*/
3697 PetscErrorCode  TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
3698 {
3699   PetscErrorCode ierr;
3700 
3701   PetscFunctionBegin;
3702   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3703   if (ts->poststage) {
3704     PetscStackCallStandard((*ts->poststage),(ts,stagetime,stageindex,Y));
3705   }
3706   PetscFunctionReturn(0);
3707 }
3708 
3709 /*@
3710   TSPostEvaluate - Runs the user-defined post-evaluate function set using TSSetPostEvaluate()
3711 
3712   Collective on TS
3713 
3714   Input Parameters:
3715 . ts          - The TS context obtained from TSCreate()
3716 
3717   Notes:
3718   TSPostEvaluate() is typically used within time stepping implementations,
3719   most users would not generally call this routine themselves.
3720 
3721   Level: developer
3722 
3723 .keywords: TS, timestep
3724 .seealso: TSSetPostEvaluate(), TSSetPreStep(), TSPreStep(), TSPostStep()
3725 @*/
3726 PetscErrorCode  TSPostEvaluate(TS ts)
3727 {
3728   PetscErrorCode ierr;
3729 
3730   PetscFunctionBegin;
3731   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3732   if (ts->postevaluate) {
3733     Vec              U;
3734     PetscObjectState sprev,spost;
3735 
3736     ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
3737     ierr = PetscObjectStateGet((PetscObject)U,&sprev);CHKERRQ(ierr);
3738     PetscStackCallStandard((*ts->postevaluate),(ts));
3739     ierr = PetscObjectStateGet((PetscObject)U,&spost);CHKERRQ(ierr);
3740     if (sprev != spost) {ierr = TSRestartStep(ts);CHKERRQ(ierr);}
3741   }
3742   PetscFunctionReturn(0);
3743 }
3744 
3745 /*@C
3746   TSSetPostStep - Sets the general-purpose function
3747   called once at the end of each time step.
3748 
3749   Logically Collective on TS
3750 
3751   Input Parameters:
3752 + ts   - The TS context obtained from TSCreate()
3753 - func - The function
3754 
3755   Calling sequence of func:
3756 $ func (TS ts);
3757 
3758   Notes:
3759   The function set by TSSetPostStep() is called after each successful step. The solution vector X
3760   obtained by TSGetSolution() may be different than that computed at the step end if the event handler
3761   locates an event and TSPostEvent() modifies it. Use TSSetPostEvaluate() if an unmodified solution is needed instead.
3762 
3763   Level: intermediate
3764 
3765 .keywords: TS, timestep
3766 .seealso: TSSetPreStep(), TSSetPreStage(), TSSetPostEvaluate(), TSGetTimeStep(), TSGetStepNumber(), TSGetTime(), TSRestartStep()
3767 @*/
3768 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
3769 {
3770   PetscFunctionBegin;
3771   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
3772   ts->poststep = func;
3773   PetscFunctionReturn(0);
3774 }
3775 
3776 /*@
3777   TSPostStep - Runs the user-defined post-step function.
3778 
3779   Collective on TS
3780 
3781   Input Parameters:
3782 . ts   - The TS context obtained from TSCreate()
3783 
3784   Notes:
3785   TSPostStep() is typically used within time stepping implementations,
3786   so most users would not generally call this routine themselves.
3787 
3788   Level: developer
3789 
3790 .keywords: TS, timestep
3791 @*/
3792 PetscErrorCode  TSPostStep(TS ts)
3793 {
3794   PetscErrorCode ierr;
3795 
3796   PetscFunctionBegin;
3797   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3798   if (ts->poststep) {
3799     Vec              U;
3800     PetscObjectState sprev,spost;
3801 
3802     ierr = TSGetSolution(ts,&U);CHKERRQ(ierr);
3803     ierr = PetscObjectStateGet((PetscObject)U,&sprev);CHKERRQ(ierr);
3804     PetscStackCallStandard((*ts->poststep),(ts));
3805     ierr = PetscObjectStateGet((PetscObject)U,&spost);CHKERRQ(ierr);
3806     if (sprev != spost) {ierr = TSRestartStep(ts);CHKERRQ(ierr);}
3807   }
3808   PetscFunctionReturn(0);
3809 }
3810 
3811 /* ------------ Routines to set performance monitoring options ----------- */
3812 
3813 /*@C
3814    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
3815    timestep to display the iteration's  progress.
3816 
3817    Logically Collective on TS
3818 
3819    Input Parameters:
3820 +  ts - the TS context obtained from TSCreate()
3821 .  monitor - monitoring routine
3822 .  mctx - [optional] user-defined context for private data for the
3823              monitor routine (use NULL if no context is desired)
3824 -  monitordestroy - [optional] routine that frees monitor context
3825           (may be NULL)
3826 
3827    Calling sequence of monitor:
3828 $    PetscErrorCode monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
3829 
3830 +    ts - the TS context
3831 .    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)
3832 .    time - current time
3833 .    u - current iterate
3834 -    mctx - [optional] monitoring context
3835 
3836    Notes:
3837    This routine adds an additional monitor to the list of monitors that
3838    already has been loaded.
3839 
3840    Fortran notes: Only a single monitor function can be set for each TS object
3841 
3842    Level: intermediate
3843 
3844 .keywords: TS, timestep, set, monitor
3845 
3846 .seealso: TSMonitorDefault(), TSMonitorCancel()
3847 @*/
3848 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
3849 {
3850   PetscErrorCode ierr;
3851   PetscInt       i;
3852   PetscBool      identical;
3853 
3854   PetscFunctionBegin;
3855   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3856   for (i=0; i<ts->numbermonitors;i++) {
3857     ierr = PetscMonitorCompare((PetscErrorCode (*)(void))monitor,mctx,mdestroy,(PetscErrorCode (*)(void))ts->monitor[i],ts->monitorcontext[i],ts->monitordestroy[i],&identical);CHKERRQ(ierr);
3858     if (identical) PetscFunctionReturn(0);
3859   }
3860   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
3861   ts->monitor[ts->numbermonitors]          = monitor;
3862   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
3863   ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
3864   PetscFunctionReturn(0);
3865 }
3866 
3867 /*@C
3868    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
3869 
3870    Logically Collective on TS
3871 
3872    Input Parameters:
3873 .  ts - the TS context obtained from TSCreate()
3874 
3875    Notes:
3876    There is no way to remove a single, specific monitor.
3877 
3878    Level: intermediate
3879 
3880 .keywords: TS, timestep, set, monitor
3881 
3882 .seealso: TSMonitorDefault(), TSMonitorSet()
3883 @*/
3884 PetscErrorCode  TSMonitorCancel(TS ts)
3885 {
3886   PetscErrorCode ierr;
3887   PetscInt       i;
3888 
3889   PetscFunctionBegin;
3890   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3891   for (i=0; i<ts->numbermonitors; i++) {
3892     if (ts->monitordestroy[i]) {
3893       ierr = (*ts->monitordestroy[i])(&ts->monitorcontext[i]);CHKERRQ(ierr);
3894     }
3895   }
3896   ts->numbermonitors = 0;
3897   PetscFunctionReturn(0);
3898 }
3899 
3900 /*@C
3901    TSMonitorDefault - The Default monitor, prints the timestep and time for each step
3902 
3903    Level: intermediate
3904 
3905 .keywords: TS, set, monitor
3906 
3907 .seealso:  TSMonitorSet()
3908 @*/
3909 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscViewerAndFormat *vf)
3910 {
3911   PetscErrorCode ierr;
3912   PetscViewer    viewer =  vf->viewer;
3913   PetscBool      iascii,ibinary;
3914 
3915   PetscFunctionBegin;
3916   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
3917   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
3918   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
3919   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
3920   if (iascii) {
3921     ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3922     if (step == -1){ /* this indicates it is an interpolated solution */
3923       ierr = PetscViewerASCIIPrintf(viewer,"Interpolated solution at time %g between steps %D and %D\n",(double)ptime,ts->steps-1,ts->steps);CHKERRQ(ierr);
3924     } else {
3925       ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr);
3926     }
3927     ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
3928   } else if (ibinary) {
3929     PetscMPIInt rank;
3930     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
3931     if (!rank) {
3932       PetscBool skipHeader;
3933       PetscInt  classid = REAL_FILE_CLASSID;
3934 
3935       ierr = PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);CHKERRQ(ierr);
3936       if (!skipHeader) {
3937          ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
3938        }
3939       ierr = PetscRealView(1,&ptime,viewer);CHKERRQ(ierr);
3940     } else {
3941       ierr = PetscRealView(0,&ptime,viewer);CHKERRQ(ierr);
3942     }
3943   }
3944   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
3945   PetscFunctionReturn(0);
3946 }
3947 
3948 /*@C
3949    TSAdjointMonitorSet - Sets an ADDITIONAL function that is to be used at every
3950    timestep to display the iteration's  progress.
3951 
3952    Logically Collective on TS
3953 
3954    Input Parameters:
3955 +  ts - the TS context obtained from TSCreate()
3956 .  adjointmonitor - monitoring routine
3957 .  adjointmctx - [optional] user-defined context for private data for the
3958              monitor routine (use NULL if no context is desired)
3959 -  adjointmonitordestroy - [optional] routine that frees monitor context
3960           (may be NULL)
3961 
3962    Calling sequence of monitor:
3963 $    int adjointmonitor(TS ts,PetscInt steps,PetscReal time,Vec u,PetscInt numcost,Vec *lambda, Vec *mu,void *adjointmctx)
3964 
3965 +    ts - the TS context
3966 .    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
3967                                been interpolated to)
3968 .    time - current time
3969 .    u - current iterate
3970 .    numcost - number of cost functionos
3971 .    lambda - sensitivities to initial conditions
3972 .    mu - sensitivities to parameters
3973 -    adjointmctx - [optional] adjoint monitoring context
3974 
3975    Notes:
3976    This routine adds an additional monitor to the list of monitors that
3977    already has been loaded.
3978 
3979    Fortran notes: Only a single monitor function can be set for each TS object
3980 
3981    Level: intermediate
3982 
3983 .keywords: TS, timestep, set, adjoint, monitor
3984 
3985 .seealso: TSAdjointMonitorCancel()
3986 @*/
3987 PetscErrorCode  TSAdjointMonitorSet(TS ts,PetscErrorCode (*adjointmonitor)(TS,PetscInt,PetscReal,Vec,PetscInt,Vec*,Vec*,void*),void *adjointmctx,PetscErrorCode (*adjointmdestroy)(void**))
3988 {
3989   PetscErrorCode ierr;
3990   PetscInt       i;
3991   PetscBool      identical;
3992 
3993   PetscFunctionBegin;
3994   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3995   for (i=0; i<ts->numbermonitors;i++) {
3996     ierr = PetscMonitorCompare((PetscErrorCode (*)(void))adjointmonitor,adjointmctx,adjointmdestroy,(PetscErrorCode (*)(void))ts->adjointmonitor[i],ts->adjointmonitorcontext[i],ts->adjointmonitordestroy[i],&identical);CHKERRQ(ierr);
3997     if (identical) PetscFunctionReturn(0);
3998   }
3999   if (ts->numberadjointmonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many adjoint monitors set");
4000   ts->adjointmonitor[ts->numberadjointmonitors]          = adjointmonitor;
4001   ts->adjointmonitordestroy[ts->numberadjointmonitors]   = adjointmdestroy;
4002   ts->adjointmonitorcontext[ts->numberadjointmonitors++] = (void*)adjointmctx;
4003   PetscFunctionReturn(0);
4004 }
4005 
4006 /*@C
4007    TSAdjointMonitorCancel - Clears all the adjoint monitors that have been set on a time-step object.
4008 
4009    Logically Collective on TS
4010 
4011    Input Parameters:
4012 .  ts - the TS context obtained from TSCreate()
4013 
4014    Notes:
4015    There is no way to remove a single, specific monitor.
4016 
4017    Level: intermediate
4018 
4019 .keywords: TS, timestep, set, adjoint, monitor
4020 
4021 .seealso: TSAdjointMonitorSet()
4022 @*/
4023 PetscErrorCode  TSAdjointMonitorCancel(TS ts)
4024 {
4025   PetscErrorCode ierr;
4026   PetscInt       i;
4027 
4028   PetscFunctionBegin;
4029   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4030   for (i=0; i<ts->numberadjointmonitors; i++) {
4031     if (ts->adjointmonitordestroy[i]) {
4032       ierr = (*ts->adjointmonitordestroy[i])(&ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
4033     }
4034   }
4035   ts->numberadjointmonitors = 0;
4036   PetscFunctionReturn(0);
4037 }
4038 
4039 /*@C
4040    TSAdjointMonitorDefault - the default monitor of adjoint computations
4041 
4042    Level: intermediate
4043 
4044 .keywords: TS, set, monitor
4045 
4046 .seealso: TSAdjointMonitorSet()
4047 @*/
4048 PetscErrorCode TSAdjointMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,PetscInt numcost,Vec *lambda,Vec *mu,PetscViewerAndFormat *vf)
4049 {
4050   PetscErrorCode ierr;
4051   PetscViewer    viewer = vf->viewer;
4052 
4053   PetscFunctionBegin;
4054   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4);
4055   ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr);
4056   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
4057   ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g%s",step,(double)ts->time_step,(double)ptime,ts->steprollback ? " (r)\n" : "\n");CHKERRQ(ierr);
4058   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
4059   ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
4060   PetscFunctionReturn(0);
4061 }
4062 
4063 /*@
4064    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
4065 
4066    Collective on TS
4067 
4068    Input Argument:
4069 +  ts - time stepping context
4070 -  t - time to interpolate to
4071 
4072    Output Argument:
4073 .  U - state at given time
4074 
4075    Level: intermediate
4076 
4077    Developer Notes:
4078    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
4079 
4080 .keywords: TS, set
4081 
4082 .seealso: TSSetExactFinalTime(), TSSolve()
4083 @*/
4084 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
4085 {
4086   PetscErrorCode ierr;
4087 
4088   PetscFunctionBegin;
4089   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4090   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
4091   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);
4092   if (!ts->ops->interpolate) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
4093   ierr = (*ts->ops->interpolate)(ts,t,U);CHKERRQ(ierr);
4094   PetscFunctionReturn(0);
4095 }
4096 
4097 /*@
4098    TSStep - Steps one time step
4099 
4100    Collective on TS
4101 
4102    Input Parameter:
4103 .  ts - the TS context obtained from TSCreate()
4104 
4105    Level: developer
4106 
4107    Notes:
4108    The public interface for the ODE/DAE solvers is TSSolve(), you should almost for sure be using that routine and not this routine.
4109 
4110    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
4111    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
4112 
4113    This may over-step the final time provided in TSSetMaxTime() depending on the time-step used. TSSolve() interpolates to exactly the
4114    time provided in TSSetMaxTime(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
4115 
4116 .keywords: TS, timestep, solve
4117 
4118 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate()
4119 @*/
4120 PetscErrorCode  TSStep(TS ts)
4121 {
4122   PetscErrorCode   ierr;
4123   static PetscBool cite = PETSC_FALSE;
4124   PetscReal        ptime;
4125 
4126   PetscFunctionBegin;
4127   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4128   ierr = PetscCitationsRegister("@techreport{tspaper,\n"
4129                                 "  title       = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
4130                                 "  author      = {Shrirang Abhyankar and Jed Brown and Emil Constantinescu and Debojyoti Ghosh and Barry F. Smith},\n"
4131                                 "  type        = {Preprint},\n"
4132                                 "  number      = {ANL/MCS-P5061-0114},\n"
4133                                 "  institution = {Argonne National Laboratory},\n"
4134                                 "  year        = {2014}\n}\n",&cite);CHKERRQ(ierr);
4135 
4136   ierr = TSSetUp(ts);CHKERRQ(ierr);
4137   ierr = TSTrajectorySetUp(ts->trajectory,ts);CHKERRQ(ierr);
4138 
4139   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>");
4140   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()");
4141   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");
4142 
4143   if (!ts->steps) ts->ptime_prev = ts->ptime;
4144   ptime = ts->ptime; ts->ptime_prev_rollback = ts->ptime_prev;
4145   ts->reason = TS_CONVERGED_ITERATING;
4146   if (!ts->ops->step) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSStep not implemented for type '%s'",((PetscObject)ts)->type_name);
4147   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
4148   ierr = (*ts->ops->step)(ts);CHKERRQ(ierr);
4149   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
4150   ts->ptime_prev = ptime;
4151   ts->steps++;
4152   ts->steprollback = PETSC_FALSE;
4153   ts->steprestart  = PETSC_FALSE;
4154 
4155   if (ts->reason < 0) {
4156     if (ts->errorifstepfailed) {
4157       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]);
4158       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
4159     }
4160   } else if (!ts->reason) {
4161     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4162     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4163   }
4164   PetscFunctionReturn(0);
4165 }
4166 
4167 /*@
4168    TSAdjointStep - Steps one time step backward in the adjoint run
4169 
4170    Collective on TS
4171 
4172    Input Parameter:
4173 .  ts - the TS context obtained from TSCreate()
4174 
4175    Level: intermediate
4176 
4177 .keywords: TS, adjoint, step
4178 
4179 .seealso: TSAdjointSetUp(), TSAdjointSolve()
4180 @*/
4181 PetscErrorCode  TSAdjointStep(TS ts)
4182 {
4183   DM               dm;
4184   PetscErrorCode   ierr;
4185 
4186   PetscFunctionBegin;
4187   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4188   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4189   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
4190 
4191   ierr = VecViewFromOptions(ts->vec_sol,(PetscObject)ts,"-ts_view_solution");CHKERRQ(ierr);
4192 
4193   ts->reason = TS_CONVERGED_ITERATING;
4194   ts->ptime_prev = ts->ptime;
4195   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);
4196   ierr = PetscLogEventBegin(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
4197   ierr = (*ts->ops->adjointstep)(ts);CHKERRQ(ierr);
4198   ierr = PetscLogEventEnd(TS_AdjointStep,ts,0,0,0);CHKERRQ(ierr);
4199   ts->adjoint_steps++; ts->steps--;
4200 
4201   if (ts->reason < 0) {
4202     if (ts->errorifstepfailed) {
4203       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]);
4204       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]);
4205       else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
4206     }
4207   } else if (!ts->reason) {
4208     if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
4209   }
4210   PetscFunctionReturn(0);
4211 }
4212 
4213 /*@
4214    TSEvaluateWLTE - Evaluate the weighted local truncation error norm
4215    at the end of a time step with a given order of accuracy.
4216 
4217    Collective on TS
4218 
4219    Input Arguments:
4220 +  ts - time stepping context
4221 .  wnormtype - norm type, either NORM_2 or NORM_INFINITY
4222 -  order - optional, desired order for the error evaluation or PETSC_DECIDE
4223 
4224    Output Arguments:
4225 +  order - optional, the actual order of the error evaluation
4226 -  wlte - the weighted local truncation error norm
4227 
4228    Level: advanced
4229 
4230    Notes:
4231    If the timestepper cannot evaluate the error in a particular step
4232    (eg. in the first step or restart steps after event handling),
4233    this routine returns wlte=-1.0 .
4234 
4235 .seealso: TSStep(), TSAdapt, TSErrorWeightedNorm()
4236 @*/
4237 PetscErrorCode TSEvaluateWLTE(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte)
4238 {
4239   PetscErrorCode ierr;
4240 
4241   PetscFunctionBegin;
4242   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4243   PetscValidType(ts,1);
4244   PetscValidLogicalCollectiveEnum(ts,wnormtype,4);
4245   if (order) PetscValidIntPointer(order,3);
4246   if (order) PetscValidLogicalCollectiveInt(ts,*order,3);
4247   PetscValidRealPointer(wlte,4);
4248   if (wnormtype != NORM_2 && wnormtype != NORM_INFINITY) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
4249   if (!ts->ops->evaluatewlte) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateWLTE not implemented for type '%s'",((PetscObject)ts)->type_name);
4250   ierr = (*ts->ops->evaluatewlte)(ts,wnormtype,order,wlte);CHKERRQ(ierr);
4251   PetscFunctionReturn(0);
4252 }
4253 
4254 /*@
4255    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
4256 
4257    Collective on TS
4258 
4259    Input Arguments:
4260 +  ts - time stepping context
4261 .  order - desired order of accuracy
4262 -  done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
4263 
4264    Output Arguments:
4265 .  U - state at the end of the current step
4266 
4267    Level: advanced
4268 
4269    Notes:
4270    This function cannot be called until all stages have been evaluated.
4271    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.
4272 
4273 .seealso: TSStep(), TSAdapt
4274 @*/
4275 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
4276 {
4277   PetscErrorCode ierr;
4278 
4279   PetscFunctionBegin;
4280   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4281   PetscValidType(ts,1);
4282   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
4283   if (!ts->ops->evaluatestep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
4284   ierr = (*ts->ops->evaluatestep)(ts,order,U,done);CHKERRQ(ierr);
4285   PetscFunctionReturn(0);
4286 }
4287 
4288 /*@
4289    TSForwardCostIntegral - Evaluate the cost integral in the forward run.
4290 
4291    Collective on TS
4292 
4293    Input Arguments:
4294 .  ts - time stepping context
4295 
4296    Level: advanced
4297 
4298    Notes:
4299    This function cannot be called until TSStep() has been completed.
4300 
4301 .seealso: TSSolve(), TSAdjointCostIntegral()
4302 @*/
4303 PetscErrorCode TSForwardCostIntegral(TS ts)
4304 {
4305   PetscErrorCode ierr;
4306   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4307   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);
4308   ierr = (*ts->ops->forwardintegral)(ts);CHKERRQ(ierr);
4309   PetscFunctionReturn(0);
4310 }
4311 
4312 /*@
4313    TSSolve - Steps the requested number of timesteps.
4314 
4315    Collective on TS
4316 
4317    Input Parameter:
4318 +  ts - the TS context obtained from TSCreate()
4319 -  u - the solution vector  (can be null if TSSetSolution() was used and TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP) was not used,
4320                              otherwise must contain the initial conditions and will contain the solution at the final requested time
4321 
4322    Level: beginner
4323 
4324    Notes:
4325    The final time returned by this function may be different from the time of the internally
4326    held state accessible by TSGetSolution() and TSGetTime() because the method may have
4327    stepped over the final time.
4328 
4329 .keywords: TS, timestep, solve
4330 
4331 .seealso: TSCreate(), TSSetSolution(), TSStep(), TSGetTime(), TSGetSolveTime()
4332 @*/
4333 PetscErrorCode TSSolve(TS ts,Vec u)
4334 {
4335   Vec               solution;
4336   PetscErrorCode    ierr;
4337 
4338   PetscFunctionBegin;
4339   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4340   if (u) PetscValidHeaderSpecific(u,VEC_CLASSID,2);
4341 
4342   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 */
4343     if (!ts->vec_sol || u == ts->vec_sol) {
4344       ierr = VecDuplicate(u,&solution);CHKERRQ(ierr);
4345       ierr = TSSetSolution(ts,solution);CHKERRQ(ierr);
4346       ierr = VecDestroy(&solution);CHKERRQ(ierr); /* grant ownership */
4347     }
4348     ierr = VecCopy(u,ts->vec_sol);CHKERRQ(ierr);
4349     if (ts->forward_solve) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Sensitivity analysis does not support the mode TS_EXACTFINALTIME_INTERPOLATE");
4350   } else if (u) {
4351     ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
4352   }
4353   ierr = TSSetUp(ts);CHKERRQ(ierr);
4354   ierr = TSTrajectorySetUp(ts->trajectory,ts);CHKERRQ(ierr);
4355 
4356   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>");
4357   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()");
4358   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");
4359 
4360   if (ts->forward_solve) {
4361     ierr = TSForwardSetUp(ts);CHKERRQ(ierr);
4362   }
4363 
4364   /* reset number of steps only when the step is not restarted. ARKIMEX
4365      restarts the step after an event. Resetting these counters in such case causes
4366      TSTrajectory to incorrectly save the output files
4367   */
4368   /* reset time step and iteration counters */
4369   if (!ts->steps) {
4370     ts->ksp_its           = 0;
4371     ts->snes_its          = 0;
4372     ts->num_snes_failures = 0;
4373     ts->reject            = 0;
4374     ts->steprestart       = PETSC_TRUE;
4375     ts->steprollback      = PETSC_FALSE;
4376   }
4377   if (ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP && ts->ptime + ts->time_step > ts->max_time) ts->time_step = ts->max_time - ts->ptime;
4378   ts->reason = TS_CONVERGED_ITERATING;
4379 
4380   ierr = TSViewFromOptions(ts,NULL,"-ts_view_pre");CHKERRQ(ierr);
4381 
4382   if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
4383     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
4384     if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
4385     ts->solvetime = ts->ptime;
4386     solution = ts->vec_sol;
4387   } else { /* Step the requested number of timesteps. */
4388     if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
4389     else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
4390 
4391     if (!ts->steps) {
4392       ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4393       ierr = TSEventInitialize(ts->event,ts,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4394     }
4395 
4396     while (!ts->reason) {
4397       ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4398       if (!ts->steprollback) {
4399         ierr = TSPreStep(ts);CHKERRQ(ierr);
4400       }
4401       ierr = TSStep(ts);CHKERRQ(ierr);
4402       if (ts->testjacobian) {
4403         ierr = TSRHSJacobianTest(ts,NULL);CHKERRQ(ierr);
4404       }
4405       if (ts->testjacobiantranspose) {
4406         ierr = TSRHSJacobianTestTranspose(ts,NULL);CHKERRQ(ierr);
4407       }
4408       if (ts->vec_costintegral && ts->costintegralfwd) { /* Must evaluate the cost integral before event is handled. The cost integral value can also be rolled back. */
4409         ierr = TSForwardCostIntegral(ts);CHKERRQ(ierr);
4410       }
4411       if (ts->forward_solve) { /* compute forward sensitivities before event handling because postevent() may change RHS and jump conditions may have to be applied */
4412         ierr = TSForwardStep(ts);CHKERRQ(ierr);
4413       }
4414       ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
4415       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. */
4416       if (ts->steprollback) {
4417         ierr = TSPostEvaluate(ts);CHKERRQ(ierr);
4418       }
4419       if (!ts->steprollback) {
4420         ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4421         ierr = TSPostStep(ts);CHKERRQ(ierr);
4422       }
4423     }
4424     ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
4425 
4426     if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
4427       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
4428       ts->solvetime = ts->max_time;
4429       solution = u;
4430       ierr = TSMonitor(ts,-1,ts->solvetime,solution);CHKERRQ(ierr);
4431     } else {
4432       if (u) {ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);}
4433       ts->solvetime = ts->ptime;
4434       solution = ts->vec_sol;
4435     }
4436   }
4437 
4438   ierr = TSViewFromOptions(ts,NULL,"-ts_view");CHKERRQ(ierr);
4439   ierr = VecViewFromOptions(solution,NULL,"-ts_view_solution");CHKERRQ(ierr);
4440   ierr = PetscObjectSAWsBlock((PetscObject)ts);CHKERRQ(ierr);
4441   if (ts->adjoint_solve) {
4442     ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
4443   }
4444   PetscFunctionReturn(0);
4445 }
4446 
4447 /*@
4448  TSAdjointCostIntegral - Evaluate the cost integral in the adjoint run.
4449 
4450  Collective on TS
4451 
4452  Input Arguments:
4453  .  ts - time stepping context
4454 
4455  Level: advanced
4456 
4457  Notes:
4458  This function cannot be called until TSAdjointStep() has been completed.
4459 
4460  .seealso: TSAdjointSolve(), TSAdjointStep
4461  @*/
4462 PetscErrorCode TSAdjointCostIntegral(TS ts)
4463 {
4464     PetscErrorCode ierr;
4465     PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4466     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);
4467     ierr = (*ts->ops->adjointintegral)(ts);CHKERRQ(ierr);
4468     PetscFunctionReturn(0);
4469 }
4470 
4471 /*@
4472    TSAdjointSolve - Solves the discrete ajoint problem for an ODE/DAE
4473 
4474    Collective on TS
4475 
4476    Input Parameter:
4477 .  ts - the TS context obtained from TSCreate()
4478 
4479    Options Database:
4480 . -ts_adjoint_view_solution <viewerinfo> - views the first gradient with respect to the initial values
4481 
4482    Level: intermediate
4483 
4484    Notes:
4485    This must be called after a call to TSSolve() that solves the forward problem
4486 
4487    By default this will integrate back to the initial time, one can use TSAdjointSetSteps() to step back to a later time
4488 
4489 .keywords: TS, timestep, solve
4490 
4491 .seealso: TSCreate(), TSSetCostGradients(), TSSetSolution(), TSAdjointStep()
4492 @*/
4493 PetscErrorCode TSAdjointSolve(TS ts)
4494 {
4495   PetscErrorCode    ierr;
4496 
4497   PetscFunctionBegin;
4498   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4499   ierr = TSAdjointSetUp(ts);CHKERRQ(ierr);
4500 
4501   /* reset time step and iteration counters */
4502   ts->adjoint_steps     = 0;
4503   ts->ksp_its           = 0;
4504   ts->snes_its          = 0;
4505   ts->num_snes_failures = 0;
4506   ts->reject            = 0;
4507   ts->reason            = TS_CONVERGED_ITERATING;
4508 
4509   if (!ts->adjoint_max_steps) ts->adjoint_max_steps = ts->steps;
4510   if (ts->adjoint_steps >= ts->adjoint_max_steps) ts->reason = TS_CONVERGED_ITS;
4511 
4512   while (!ts->reason) {
4513     ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
4514     ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
4515     ierr = TSAdjointEventHandler(ts);CHKERRQ(ierr);
4516     ierr = TSAdjointStep(ts);CHKERRQ(ierr);
4517     if (ts->vec_costintegral && !ts->costintegralfwd) {
4518       ierr = TSAdjointCostIntegral(ts);CHKERRQ(ierr);
4519     }
4520   }
4521   ierr = TSTrajectoryGet(ts->trajectory,ts,ts->steps,&ts->ptime);CHKERRQ(ierr);
4522   ierr = TSAdjointMonitor(ts,ts->steps,ts->ptime,ts->vec_sol,ts->numcost,ts->vecs_sensi,ts->vecs_sensip);CHKERRQ(ierr);
4523   ts->solvetime = ts->ptime;
4524   ierr = TSTrajectoryViewFromOptions(ts->trajectory,NULL,"-ts_trajectory_view");CHKERRQ(ierr);
4525   ierr = VecViewFromOptions(ts->vecs_sensi[0],(PetscObject) ts, "-ts_adjoint_view_solution");CHKERRQ(ierr);
4526   ts->adjoint_max_steps = 0;
4527   PetscFunctionReturn(0);
4528 }
4529 
4530 /*@C
4531    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
4532 
4533    Collective on TS
4534 
4535    Input Parameters:
4536 +  ts - time stepping context obtained from TSCreate()
4537 .  step - step number that has just completed
4538 .  ptime - model time of the state
4539 -  u - state at the current model time
4540 
4541    Notes:
4542    TSMonitor() is typically used automatically within the time stepping implementations.
4543    Users would almost never call this routine directly.
4544 
4545    A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
4546 
4547    Level: developer
4548 
4549 .keywords: TS, timestep
4550 @*/
4551 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
4552 {
4553   DM             dm;
4554   PetscInt       i,n = ts->numbermonitors;
4555   PetscErrorCode ierr;
4556 
4557   PetscFunctionBegin;
4558   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4559   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4560 
4561   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4562   ierr = DMSetOutputSequenceNumber(dm,step,ptime);CHKERRQ(ierr);
4563 
4564   ierr = VecLockPush(u);CHKERRQ(ierr);
4565   for (i=0; i<n; i++) {
4566     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
4567   }
4568   ierr = VecLockPop(u);CHKERRQ(ierr);
4569   PetscFunctionReturn(0);
4570 }
4571 
4572 /*@C
4573    TSAdjointMonitor - Runs all user-provided adjoint monitor routines set using TSAdjointMonitorSet()
4574 
4575    Collective on TS
4576 
4577    Input Parameters:
4578 +  ts - time stepping context obtained from TSCreate()
4579 .  step - step number that has just completed
4580 .  ptime - model time of the state
4581 .  u - state at the current model time
4582 .  numcost - number of cost functions (dimension of lambda  or mu)
4583 .  lambda - vectors containing the gradients of the cost functions with respect to the ODE/DAE solution variables
4584 -  mu - vectors containing the gradients of the cost functions with respect to the problem parameters
4585 
4586    Notes:
4587    TSAdjointMonitor() is typically used automatically within the time stepping implementations.
4588    Users would almost never call this routine directly.
4589 
4590    Level: developer
4591 
4592 .keywords: TS, timestep
4593 @*/
4594 PetscErrorCode TSAdjointMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda, Vec *mu)
4595 {
4596   PetscErrorCode ierr;
4597   PetscInt       i,n = ts->numberadjointmonitors;
4598 
4599   PetscFunctionBegin;
4600   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4601   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4602   ierr = VecLockPush(u);CHKERRQ(ierr);
4603   for (i=0; i<n; i++) {
4604     ierr = (*ts->adjointmonitor[i])(ts,step,ptime,u,numcost,lambda,mu,ts->adjointmonitorcontext[i]);CHKERRQ(ierr);
4605   }
4606   ierr = VecLockPop(u);CHKERRQ(ierr);
4607   PetscFunctionReturn(0);
4608 }
4609 
4610 /* ------------------------------------------------------------------------*/
4611 /*@C
4612    TSMonitorLGCtxCreate - Creates a TSMonitorLGCtx context for use with
4613    TS to monitor the solution process graphically in various ways
4614 
4615    Collective on TS
4616 
4617    Input Parameters:
4618 +  host - the X display to open, or null for the local machine
4619 .  label - the title to put in the title bar
4620 .  x, y - the screen coordinates of the upper left coordinate of the window
4621 .  m, n - the screen width and height in pixels
4622 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
4623 
4624    Output Parameter:
4625 .  ctx - the context
4626 
4627    Options Database Key:
4628 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
4629 +  -ts_monitor_lg_timestep_log - automatically sets line graph monitor
4630 .  -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling TSMonitorLGSetDisplayVariables() or TSMonitorLGCtxSetDisplayVariables())
4631 .  -ts_monitor_lg_error -  monitor the error
4632 .  -ts_monitor_lg_ksp_iterations - monitor the number of KSP iterations needed for each timestep
4633 .  -ts_monitor_lg_snes_iterations - monitor the number of SNES iterations needed for each timestep
4634 -  -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
4635 
4636    Notes:
4637    Use TSMonitorLGCtxDestroy() to destroy.
4638 
4639    One can provide a function that transforms the solution before plotting it with TSMonitorLGCtxSetTransform() or TSMonitorLGSetTransform()
4640 
4641    Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a TS object as the
4642    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
4643    as the first argument.
4644 
4645    One can control the names displayed for each solution or error variable with TSMonitorLGCtxSetVariableNames() or TSMonitorLGSetVariableNames()
4646 
4647    Level: intermediate
4648 
4649 .keywords: TS, monitor, line graph, residual
4650 
4651 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError(), TSMonitorDefault(), VecView(),
4652            TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
4653            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
4654            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
4655            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
4656 
4657 @*/
4658 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
4659 {
4660   PetscDraw      draw;
4661   PetscErrorCode ierr;
4662 
4663   PetscFunctionBegin;
4664   ierr = PetscNew(ctx);CHKERRQ(ierr);
4665   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&draw);CHKERRQ(ierr);
4666   ierr = PetscDrawSetFromOptions(draw);CHKERRQ(ierr);
4667   ierr = PetscDrawLGCreate(draw,1,&(*ctx)->lg);CHKERRQ(ierr);
4668   ierr = PetscDrawLGSetFromOptions((*ctx)->lg);CHKERRQ(ierr);
4669   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
4670   (*ctx)->howoften = howoften;
4671   PetscFunctionReturn(0);
4672 }
4673 
4674 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
4675 {
4676   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4677   PetscReal      x   = ptime,y;
4678   PetscErrorCode ierr;
4679 
4680   PetscFunctionBegin;
4681   if (step < 0) PetscFunctionReturn(0); /* -1 indicates an interpolated solution */
4682   if (!step) {
4683     PetscDrawAxis axis;
4684     const char *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
4685     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4686     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time",ylabel);CHKERRQ(ierr);
4687     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4688   }
4689   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
4690   if (ctx->semilogy) y = PetscLog10Real(y);
4691   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4692   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4693     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4694     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
4695   }
4696   PetscFunctionReturn(0);
4697 }
4698 
4699 /*@C
4700    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
4701    with TSMonitorLGCtxCreate().
4702 
4703    Collective on TSMonitorLGCtx
4704 
4705    Input Parameter:
4706 .  ctx - the monitor context
4707 
4708    Level: intermediate
4709 
4710 .keywords: TS, monitor, line graph, destroy
4711 
4712 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
4713 @*/
4714 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
4715 {
4716   PetscErrorCode ierr;
4717 
4718   PetscFunctionBegin;
4719   if ((*ctx)->transformdestroy) {
4720     ierr = ((*ctx)->transformdestroy)((*ctx)->transformctx);CHKERRQ(ierr);
4721   }
4722   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
4723   ierr = PetscStrArrayDestroy(&(*ctx)->names);CHKERRQ(ierr);
4724   ierr = PetscStrArrayDestroy(&(*ctx)->displaynames);CHKERRQ(ierr);
4725   ierr = PetscFree((*ctx)->displayvariables);CHKERRQ(ierr);
4726   ierr = PetscFree((*ctx)->displayvalues);CHKERRQ(ierr);
4727   ierr = PetscFree(*ctx);CHKERRQ(ierr);
4728   PetscFunctionReturn(0);
4729 }
4730 
4731 /*@
4732    TSGetTime - Gets the time of the most recently completed step.
4733 
4734    Not Collective
4735 
4736    Input Parameter:
4737 .  ts - the TS context obtained from TSCreate()
4738 
4739    Output Parameter:
4740 .  t  - the current time. This time may not corresponds to the final time set with TSSetMaxTime(), use TSGetSolveTime().
4741 
4742    Level: beginner
4743 
4744    Note:
4745    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
4746    TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
4747 
4748 .seealso:  TSGetSolveTime(), TSSetTime(), TSGetTimeStep()
4749 
4750 .keywords: TS, get, time
4751 @*/
4752 PetscErrorCode  TSGetTime(TS ts,PetscReal *t)
4753 {
4754   PetscFunctionBegin;
4755   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4756   PetscValidRealPointer(t,2);
4757   *t = ts->ptime;
4758   PetscFunctionReturn(0);
4759 }
4760 
4761 /*@
4762    TSGetPrevTime - Gets the starting time of the previously completed step.
4763 
4764    Not Collective
4765 
4766    Input Parameter:
4767 .  ts - the TS context obtained from TSCreate()
4768 
4769    Output Parameter:
4770 .  t  - the previous time
4771 
4772    Level: beginner
4773 
4774 .seealso: TSGetTime(), TSGetSolveTime(), TSGetTimeStep()
4775 
4776 .keywords: TS, get, time
4777 @*/
4778 PetscErrorCode  TSGetPrevTime(TS ts,PetscReal *t)
4779 {
4780   PetscFunctionBegin;
4781   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4782   PetscValidRealPointer(t,2);
4783   *t = ts->ptime_prev;
4784   PetscFunctionReturn(0);
4785 }
4786 
4787 /*@
4788    TSSetTime - Allows one to reset the time.
4789 
4790    Logically Collective on TS
4791 
4792    Input Parameters:
4793 +  ts - the TS context obtained from TSCreate()
4794 -  time - the time
4795 
4796    Level: intermediate
4797 
4798 .seealso: TSGetTime(), TSSetMaxSteps()
4799 
4800 .keywords: TS, set, time
4801 @*/
4802 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
4803 {
4804   PetscFunctionBegin;
4805   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4806   PetscValidLogicalCollectiveReal(ts,t,2);
4807   ts->ptime = t;
4808   PetscFunctionReturn(0);
4809 }
4810 
4811 /*@C
4812    TSSetOptionsPrefix - Sets the prefix used for searching for all
4813    TS options in the database.
4814 
4815    Logically Collective on TS
4816 
4817    Input Parameter:
4818 +  ts     - The TS context
4819 -  prefix - The prefix to prepend to all option names
4820 
4821    Notes:
4822    A hyphen (-) must NOT be given at the beginning of the prefix name.
4823    The first character of all runtime options is AUTOMATICALLY the
4824    hyphen.
4825 
4826    Level: advanced
4827 
4828 .keywords: TS, set, options, prefix, database
4829 
4830 .seealso: TSSetFromOptions()
4831 
4832 @*/
4833 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
4834 {
4835   PetscErrorCode ierr;
4836   SNES           snes;
4837 
4838   PetscFunctionBegin;
4839   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4840   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4841   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4842   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4843   PetscFunctionReturn(0);
4844 }
4845 
4846 /*@C
4847    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
4848    TS options in the database.
4849 
4850    Logically Collective on TS
4851 
4852    Input Parameter:
4853 +  ts     - The TS context
4854 -  prefix - The prefix to prepend to all option names
4855 
4856    Notes:
4857    A hyphen (-) must NOT be given at the beginning of the prefix name.
4858    The first character of all runtime options is AUTOMATICALLY the
4859    hyphen.
4860 
4861    Level: advanced
4862 
4863 .keywords: TS, append, options, prefix, database
4864 
4865 .seealso: TSGetOptionsPrefix()
4866 
4867 @*/
4868 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
4869 {
4870   PetscErrorCode ierr;
4871   SNES           snes;
4872 
4873   PetscFunctionBegin;
4874   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4875   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4876   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4877   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
4878   PetscFunctionReturn(0);
4879 }
4880 
4881 /*@C
4882    TSGetOptionsPrefix - Sets the prefix used for searching for all
4883    TS options in the database.
4884 
4885    Not Collective
4886 
4887    Input Parameter:
4888 .  ts - The TS context
4889 
4890    Output Parameter:
4891 .  prefix - A pointer to the prefix string used
4892 
4893    Notes: On the fortran side, the user should pass in a string 'prifix' of
4894    sufficient length to hold the prefix.
4895 
4896    Level: intermediate
4897 
4898 .keywords: TS, get, options, prefix, database
4899 
4900 .seealso: TSAppendOptionsPrefix()
4901 @*/
4902 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
4903 {
4904   PetscErrorCode ierr;
4905 
4906   PetscFunctionBegin;
4907   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4908   PetscValidPointer(prefix,2);
4909   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
4910   PetscFunctionReturn(0);
4911 }
4912 
4913 /*@C
4914    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
4915 
4916    Not Collective, but parallel objects are returned if TS is parallel
4917 
4918    Input Parameter:
4919 .  ts  - The TS context obtained from TSCreate()
4920 
4921    Output Parameters:
4922 +  Amat - The (approximate) Jacobian J of G, where U_t = G(U,t)  (or NULL)
4923 .  Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat  (or NULL)
4924 .  func - Function to compute the Jacobian of the RHS  (or NULL)
4925 -  ctx - User-defined context for Jacobian evaluation routine  (or NULL)
4926 
4927    Notes: You can pass in NULL for any return argument you do not need.
4928 
4929    Level: intermediate
4930 
4931 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4932 
4933 .keywords: TS, timestep, get, matrix, Jacobian
4934 @*/
4935 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
4936 {
4937   PetscErrorCode ierr;
4938   DM             dm;
4939 
4940   PetscFunctionBegin;
4941   if (Amat || Pmat) {
4942     SNES snes;
4943     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4944     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4945     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4946   }
4947   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4948   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
4949   PetscFunctionReturn(0);
4950 }
4951 
4952 /*@C
4953    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
4954 
4955    Not Collective, but parallel objects are returned if TS is parallel
4956 
4957    Input Parameter:
4958 .  ts  - The TS context obtained from TSCreate()
4959 
4960    Output Parameters:
4961 +  Amat  - The (approximate) Jacobian of F(t,U,U_t)
4962 .  Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
4963 .  f   - The function to compute the matrices
4964 - ctx - User-defined context for Jacobian evaluation routine
4965 
4966    Notes: You can pass in NULL for any return argument you do not need.
4967 
4968    Level: advanced
4969 
4970 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetStepNumber()
4971 
4972 .keywords: TS, timestep, get, matrix, Jacobian
4973 @*/
4974 PetscErrorCode  TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
4975 {
4976   PetscErrorCode ierr;
4977   DM             dm;
4978 
4979   PetscFunctionBegin;
4980   if (Amat || Pmat) {
4981     SNES snes;
4982     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
4983     ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4984     ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr);
4985   }
4986   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
4987   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
4988   PetscFunctionReturn(0);
4989 }
4990 
4991 /*@C
4992    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
4993    VecView() for the solution at each timestep
4994 
4995    Collective on TS
4996 
4997    Input Parameters:
4998 +  ts - the TS context
4999 .  step - current time-step
5000 .  ptime - current time
5001 -  dummy - either a viewer or NULL
5002 
5003    Options Database:
5004 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
5005 
5006    Notes: the initial solution and current solution are not display with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
5007        will look bad
5008 
5009    Level: intermediate
5010 
5011 .keywords: TS,  vector, monitor, view
5012 
5013 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5014 @*/
5015 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5016 {
5017   PetscErrorCode   ierr;
5018   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
5019   PetscDraw        draw;
5020 
5021   PetscFunctionBegin;
5022   if (!step && ictx->showinitial) {
5023     if (!ictx->initialsolution) {
5024       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
5025     }
5026     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
5027   }
5028   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
5029 
5030   if (ictx->showinitial) {
5031     PetscReal pause;
5032     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
5033     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
5034     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
5035     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
5036     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
5037   }
5038   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
5039   if (ictx->showtimestepandtime) {
5040     PetscReal xl,yl,xr,yr,h;
5041     char      time[32];
5042 
5043     ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
5044     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
5045     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
5046     h    = yl + .95*(yr - yl);
5047     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
5048     ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
5049   }
5050 
5051   if (ictx->showinitial) {
5052     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
5053   }
5054   PetscFunctionReturn(0);
5055 }
5056 
5057 /*@C
5058    TSAdjointMonitorDrawSensi - Monitors progress of the adjoint TS solvers by calling
5059    VecView() for the sensitivities to initial states at each timestep
5060 
5061    Collective on TS
5062 
5063    Input Parameters:
5064 +  ts - the TS context
5065 .  step - current time-step
5066 .  ptime - current time
5067 .  u - current state
5068 .  numcost - number of cost functions
5069 .  lambda - sensitivities to initial conditions
5070 .  mu - sensitivities to parameters
5071 -  dummy - either a viewer or NULL
5072 
5073    Level: intermediate
5074 
5075 .keywords: TS,  vector, adjoint, monitor, view
5076 
5077 .seealso: TSAdjointMonitorSet(), TSAdjointMonitorDefault(), VecView()
5078 @*/
5079 PetscErrorCode  TSAdjointMonitorDrawSensi(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscInt numcost,Vec *lambda,Vec *mu,void *dummy)
5080 {
5081   PetscErrorCode   ierr;
5082   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
5083   PetscDraw        draw;
5084   PetscReal        xl,yl,xr,yr,h;
5085   char             time[32];
5086 
5087   PetscFunctionBegin;
5088   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
5089 
5090   ierr = VecView(lambda[0],ictx->viewer);CHKERRQ(ierr);
5091   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
5092   ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
5093   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
5094   h    = yl + .95*(yr - yl);
5095   ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
5096   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
5097   PetscFunctionReturn(0);
5098 }
5099 
5100 /*@C
5101    TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
5102 
5103    Collective on TS
5104 
5105    Input Parameters:
5106 +  ts - the TS context
5107 .  step - current time-step
5108 .  ptime - current time
5109 -  dummy - either a viewer or NULL
5110 
5111    Level: intermediate
5112 
5113 .keywords: TS,  vector, monitor, view
5114 
5115 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5116 @*/
5117 PetscErrorCode  TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5118 {
5119   PetscErrorCode    ierr;
5120   TSMonitorDrawCtx  ictx = (TSMonitorDrawCtx)dummy;
5121   PetscDraw         draw;
5122   PetscDrawAxis     axis;
5123   PetscInt          n;
5124   PetscMPIInt       size;
5125   PetscReal         U0,U1,xl,yl,xr,yr,h;
5126   char              time[32];
5127   const PetscScalar *U;
5128 
5129   PetscFunctionBegin;
5130   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)ts),&size);CHKERRQ(ierr);
5131   if (size != 1) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only allowed for sequential runs");
5132   ierr = VecGetSize(u,&n);CHKERRQ(ierr);
5133   if (n != 2) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Only for ODEs with two unknowns");
5134 
5135   ierr = PetscViewerDrawGetDraw(ictx->viewer,0,&draw);CHKERRQ(ierr);
5136   ierr = PetscViewerDrawGetDrawAxis(ictx->viewer,0,&axis);CHKERRQ(ierr);
5137   ierr = PetscDrawAxisGetLimits(axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
5138   if (!step) {
5139     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
5140     ierr = PetscDrawAxisDraw(axis);CHKERRQ(ierr);
5141   }
5142 
5143   ierr = VecGetArrayRead(u,&U);CHKERRQ(ierr);
5144   U0 = PetscRealPart(U[0]);
5145   U1 = PetscRealPart(U[1]);
5146   ierr = VecRestoreArrayRead(u,&U);CHKERRQ(ierr);
5147   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(0);
5148 
5149   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
5150   ierr = PetscDrawPoint(draw,U0,U1,PETSC_DRAW_BLACK);CHKERRQ(ierr);
5151   if (ictx->showtimestepandtime) {
5152     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
5153     ierr = PetscSNPrintf(time,32,"Timestep %d Time %g",(int)step,(double)ptime);CHKERRQ(ierr);
5154     h    = yl + .95*(yr - yl);
5155     ierr = PetscDrawStringCentered(draw,.5*(xl+xr),h,PETSC_DRAW_BLACK,time);CHKERRQ(ierr);
5156   }
5157   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
5158   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
5159   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
5160   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
5161   PetscFunctionReturn(0);
5162 }
5163 
5164 /*@C
5165    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
5166 
5167    Collective on TS
5168 
5169    Input Parameters:
5170 .    ctx - the monitor context
5171 
5172    Level: intermediate
5173 
5174 .keywords: TS,  vector, monitor, view
5175 
5176 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
5177 @*/
5178 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
5179 {
5180   PetscErrorCode ierr;
5181 
5182   PetscFunctionBegin;
5183   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
5184   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
5185   ierr = PetscFree(*ictx);CHKERRQ(ierr);
5186   PetscFunctionReturn(0);
5187 }
5188 
5189 /*@C
5190    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
5191 
5192    Collective on TS
5193 
5194    Input Parameter:
5195 .    ts - time-step context
5196 
5197    Output Patameter:
5198 .    ctx - the monitor context
5199 
5200    Options Database:
5201 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
5202 
5203    Level: intermediate
5204 
5205 .keywords: TS,  vector, monitor, view
5206 
5207 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
5208 @*/
5209 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
5210 {
5211   PetscErrorCode   ierr;
5212 
5213   PetscFunctionBegin;
5214   ierr = PetscNew(ctx);CHKERRQ(ierr);
5215   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
5216   ierr = PetscViewerSetFromOptions((*ctx)->viewer);CHKERRQ(ierr);
5217 
5218   (*ctx)->howoften    = howoften;
5219   (*ctx)->showinitial = PETSC_FALSE;
5220   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);CHKERRQ(ierr);
5221 
5222   (*ctx)->showtimestepandtime = PETSC_FALSE;
5223   ierr = PetscOptionsGetBool(NULL,NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);CHKERRQ(ierr);
5224   PetscFunctionReturn(0);
5225 }
5226 
5227 /*@C
5228    TSMonitorDrawSolutionFunction - Monitors progress of the TS solvers by calling
5229    VecView() for the solution provided by TSSetSolutionFunction() at each timestep
5230 
5231    Collective on TS
5232 
5233    Input Parameters:
5234 +  ts - the TS context
5235 .  step - current time-step
5236 .  ptime - current time
5237 -  dummy - either a viewer or NULL
5238 
5239    Options Database:
5240 .  -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
5241 
5242    Level: intermediate
5243 
5244 .keywords: TS,  vector, monitor, view
5245 
5246 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
5247 @*/
5248 PetscErrorCode  TSMonitorDrawSolutionFunction(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5249 {
5250   PetscErrorCode   ierr;
5251   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
5252   PetscViewer      viewer = ctx->viewer;
5253   Vec              work;
5254 
5255   PetscFunctionBegin;
5256   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
5257   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
5258   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
5259   ierr = VecView(work,viewer);CHKERRQ(ierr);
5260   ierr = VecDestroy(&work);CHKERRQ(ierr);
5261   PetscFunctionReturn(0);
5262 }
5263 
5264 /*@C
5265    TSMonitorDrawError - Monitors progress of the TS solvers by calling
5266    VecView() for the error at each timestep
5267 
5268    Collective on TS
5269 
5270    Input Parameters:
5271 +  ts - the TS context
5272 .  step - current time-step
5273 .  ptime - current time
5274 -  dummy - either a viewer or NULL
5275 
5276    Options Database:
5277 .  -ts_monitor_draw_error - Monitor error graphically, requires user to have provided TSSetSolutionFunction()
5278 
5279    Level: intermediate
5280 
5281 .keywords: TS,  vector, monitor, view
5282 
5283 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
5284 @*/
5285 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
5286 {
5287   PetscErrorCode   ierr;
5288   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
5289   PetscViewer      viewer = ctx->viewer;
5290   Vec              work;
5291 
5292   PetscFunctionBegin;
5293   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(0);
5294   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
5295   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
5296   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
5297   ierr = VecView(work,viewer);CHKERRQ(ierr);
5298   ierr = VecDestroy(&work);CHKERRQ(ierr);
5299   PetscFunctionReturn(0);
5300 }
5301 
5302 #include <petsc/private/dmimpl.h>
5303 /*@
5304    TSSetDM - Sets the DM that may be used by some nonlinear solvers or preconditioners under the TS
5305 
5306    Logically Collective on TS and DM
5307 
5308    Input Parameters:
5309 +  ts - the ODE integrator object
5310 -  dm - the dm, cannot be NULL
5311 
5312    Level: intermediate
5313 
5314 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
5315 @*/
5316 PetscErrorCode  TSSetDM(TS ts,DM dm)
5317 {
5318   PetscErrorCode ierr;
5319   SNES           snes;
5320   DMTS           tsdm;
5321 
5322   PetscFunctionBegin;
5323   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5324   PetscValidHeaderSpecific(dm,DM_CLASSID,2);
5325   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
5326   if (ts->dm) {               /* Move the DMTS context over to the new DM unless the new DM already has one */
5327     if (ts->dm->dmts && !dm->dmts) {
5328       ierr = DMCopyDMTS(ts->dm,dm);CHKERRQ(ierr);
5329       ierr = DMGetDMTS(ts->dm,&tsdm);CHKERRQ(ierr);
5330       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
5331         tsdm->originaldm = dm;
5332       }
5333     }
5334     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
5335   }
5336   ts->dm = dm;
5337 
5338   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
5339   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
5340   PetscFunctionReturn(0);
5341 }
5342 
5343 /*@
5344    TSGetDM - Gets the DM that may be used by some preconditioners
5345 
5346    Not Collective
5347 
5348    Input Parameter:
5349 . ts - the preconditioner context
5350 
5351    Output Parameter:
5352 .  dm - the dm
5353 
5354    Level: intermediate
5355 
5356 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
5357 @*/
5358 PetscErrorCode  TSGetDM(TS ts,DM *dm)
5359 {
5360   PetscErrorCode ierr;
5361 
5362   PetscFunctionBegin;
5363   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5364   if (!ts->dm) {
5365     ierr = DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);CHKERRQ(ierr);
5366     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
5367   }
5368   *dm = ts->dm;
5369   PetscFunctionReturn(0);
5370 }
5371 
5372 /*@
5373    SNESTSFormFunction - Function to evaluate nonlinear residual
5374 
5375    Logically Collective on SNES
5376 
5377    Input Parameter:
5378 + snes - nonlinear solver
5379 . U - the current state at which to evaluate the residual
5380 - ctx - user context, must be a TS
5381 
5382    Output Parameter:
5383 . F - the nonlinear residual
5384 
5385    Notes:
5386    This function is not normally called by users and is automatically registered with the SNES used by TS.
5387    It is most frequently passed to MatFDColoringSetFunction().
5388 
5389    Level: advanced
5390 
5391 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
5392 @*/
5393 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
5394 {
5395   TS             ts = (TS)ctx;
5396   PetscErrorCode ierr;
5397 
5398   PetscFunctionBegin;
5399   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
5400   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5401   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
5402   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
5403   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
5404   PetscFunctionReturn(0);
5405 }
5406 
5407 /*@
5408    SNESTSFormJacobian - Function to evaluate the Jacobian
5409 
5410    Collective on SNES
5411 
5412    Input Parameter:
5413 + snes - nonlinear solver
5414 . U - the current state at which to evaluate the residual
5415 - ctx - user context, must be a TS
5416 
5417    Output Parameter:
5418 + A - the Jacobian
5419 . B - the preconditioning matrix (may be the same as A)
5420 - flag - indicates any structure change in the matrix
5421 
5422    Notes:
5423    This function is not normally called by users and is automatically registered with the SNES used by TS.
5424 
5425    Level: developer
5426 
5427 .seealso: SNESSetJacobian()
5428 @*/
5429 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
5430 {
5431   TS             ts = (TS)ctx;
5432   PetscErrorCode ierr;
5433 
5434   PetscFunctionBegin;
5435   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
5436   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
5437   PetscValidPointer(A,3);
5438   PetscValidHeaderSpecific(A,MAT_CLASSID,3);
5439   PetscValidPointer(B,4);
5440   PetscValidHeaderSpecific(B,MAT_CLASSID,4);
5441   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
5442   ierr = (ts->ops->snesjacobian)(snes,U,A,B,ts);CHKERRQ(ierr);
5443   PetscFunctionReturn(0);
5444 }
5445 
5446 /*@C
5447    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems Udot = A U only
5448 
5449    Collective on TS
5450 
5451    Input Arguments:
5452 +  ts - time stepping context
5453 .  t - time at which to evaluate
5454 .  U - state at which to evaluate
5455 -  ctx - context
5456 
5457    Output Arguments:
5458 .  F - right hand side
5459 
5460    Level: intermediate
5461 
5462    Notes:
5463    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
5464    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
5465 
5466 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
5467 @*/
5468 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
5469 {
5470   PetscErrorCode ierr;
5471   Mat            Arhs,Brhs;
5472 
5473   PetscFunctionBegin;
5474   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
5475   ierr = TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);CHKERRQ(ierr);
5476   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
5477   PetscFunctionReturn(0);
5478 }
5479 
5480 /*@C
5481    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
5482 
5483    Collective on TS
5484 
5485    Input Arguments:
5486 +  ts - time stepping context
5487 .  t - time at which to evaluate
5488 .  U - state at which to evaluate
5489 -  ctx - context
5490 
5491    Output Arguments:
5492 +  A - pointer to operator
5493 .  B - pointer to preconditioning matrix
5494 -  flg - matrix structure flag
5495 
5496    Level: intermediate
5497 
5498    Notes:
5499    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
5500 
5501 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
5502 @*/
5503 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
5504 {
5505   PetscFunctionBegin;
5506   PetscFunctionReturn(0);
5507 }
5508 
5509 /*@C
5510    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
5511 
5512    Collective on TS
5513 
5514    Input Arguments:
5515 +  ts - time stepping context
5516 .  t - time at which to evaluate
5517 .  U - state at which to evaluate
5518 .  Udot - time derivative of state vector
5519 -  ctx - context
5520 
5521    Output Arguments:
5522 .  F - left hand side
5523 
5524    Level: intermediate
5525 
5526    Notes:
5527    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
5528    user is required to write their own TSComputeIFunction.
5529    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
5530    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
5531 
5532    Note that using this function is NOT equivalent to using TSComputeRHSFunctionLinear() since that solves Udot = A U
5533 
5534 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant(), TSComputeRHSFunctionLinear()
5535 @*/
5536 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
5537 {
5538   PetscErrorCode ierr;
5539   Mat            A,B;
5540 
5541   PetscFunctionBegin;
5542   ierr = TSGetIJacobian(ts,&A,&B,NULL,NULL);CHKERRQ(ierr);
5543   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE);CHKERRQ(ierr);
5544   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
5545   PetscFunctionReturn(0);
5546 }
5547 
5548 /*@C
5549    TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
5550 
5551    Collective on TS
5552 
5553    Input Arguments:
5554 +  ts - time stepping context
5555 .  t - time at which to evaluate
5556 .  U - state at which to evaluate
5557 .  Udot - time derivative of state vector
5558 .  shift - shift to apply
5559 -  ctx - context
5560 
5561    Output Arguments:
5562 +  A - pointer to operator
5563 .  B - pointer to preconditioning matrix
5564 -  flg - matrix structure flag
5565 
5566    Level: advanced
5567 
5568    Notes:
5569    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
5570 
5571    It is only appropriate for problems of the form
5572 
5573 $     M Udot = F(U,t)
5574 
5575   where M is constant and F is non-stiff.  The user must pass M to TSSetIJacobian().  The current implementation only
5576   works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
5577   an implicit operator of the form
5578 
5579 $    shift*M + J
5580 
5581   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
5582   a copy of M or reassemble it when requested.
5583 
5584 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
5585 @*/
5586 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
5587 {
5588   PetscErrorCode ierr;
5589 
5590   PetscFunctionBegin;
5591   ierr = MatScale(A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
5592   ts->ijacobian.shift = shift;
5593   PetscFunctionReturn(0);
5594 }
5595 
5596 /*@
5597    TSGetEquationType - Gets the type of the equation that TS is solving.
5598 
5599    Not Collective
5600 
5601    Input Parameter:
5602 .  ts - the TS context
5603 
5604    Output Parameter:
5605 .  equation_type - see TSEquationType
5606 
5607    Level: beginner
5608 
5609 .keywords: TS, equation type
5610 
5611 .seealso: TSSetEquationType(), TSEquationType
5612 @*/
5613 PetscErrorCode  TSGetEquationType(TS ts,TSEquationType *equation_type)
5614 {
5615   PetscFunctionBegin;
5616   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5617   PetscValidPointer(equation_type,2);
5618   *equation_type = ts->equation_type;
5619   PetscFunctionReturn(0);
5620 }
5621 
5622 /*@
5623    TSSetEquationType - Sets the type of the equation that TS is solving.
5624 
5625    Not Collective
5626 
5627    Input Parameter:
5628 +  ts - the TS context
5629 -  equation_type - see TSEquationType
5630 
5631    Level: advanced
5632 
5633 .keywords: TS, equation type
5634 
5635 .seealso: TSGetEquationType(), TSEquationType
5636 @*/
5637 PetscErrorCode  TSSetEquationType(TS ts,TSEquationType equation_type)
5638 {
5639   PetscFunctionBegin;
5640   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5641   ts->equation_type = equation_type;
5642   PetscFunctionReturn(0);
5643 }
5644 
5645 /*@
5646    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
5647 
5648    Not Collective
5649 
5650    Input Parameter:
5651 .  ts - the TS context
5652 
5653    Output Parameter:
5654 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5655             manual pages for the individual convergence tests for complete lists
5656 
5657    Level: beginner
5658 
5659    Notes:
5660    Can only be called after the call to TSSolve() is complete.
5661 
5662 .keywords: TS, nonlinear, set, convergence, test
5663 
5664 .seealso: TSSetConvergenceTest(), TSConvergedReason
5665 @*/
5666 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
5667 {
5668   PetscFunctionBegin;
5669   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5670   PetscValidPointer(reason,2);
5671   *reason = ts->reason;
5672   PetscFunctionReturn(0);
5673 }
5674 
5675 /*@
5676    TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
5677 
5678    Not Collective
5679 
5680    Input Parameter:
5681 +  ts - the TS context
5682 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
5683             manual pages for the individual convergence tests for complete lists
5684 
5685    Level: advanced
5686 
5687    Notes:
5688    Can only be called during TSSolve() is active.
5689 
5690 .keywords: TS, nonlinear, set, convergence, test
5691 
5692 .seealso: TSConvergedReason
5693 @*/
5694 PetscErrorCode  TSSetConvergedReason(TS ts,TSConvergedReason reason)
5695 {
5696   PetscFunctionBegin;
5697   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5698   ts->reason = reason;
5699   PetscFunctionReturn(0);
5700 }
5701 
5702 /*@
5703    TSGetSolveTime - Gets the time after a call to TSSolve()
5704 
5705    Not Collective
5706 
5707    Input Parameter:
5708 .  ts - the TS context
5709 
5710    Output Parameter:
5711 .  ftime - the final time. This time corresponds to the final time set with TSSetMaxTime()
5712 
5713    Level: beginner
5714 
5715    Notes:
5716    Can only be called after the call to TSSolve() is complete.
5717 
5718 .keywords: TS, nonlinear, set, convergence, test
5719 
5720 .seealso: TSSetConvergenceTest(), TSConvergedReason
5721 @*/
5722 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
5723 {
5724   PetscFunctionBegin;
5725   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5726   PetscValidPointer(ftime,2);
5727   *ftime = ts->solvetime;
5728   PetscFunctionReturn(0);
5729 }
5730 
5731 /*@
5732    TSGetSNESIterations - Gets the total number of nonlinear iterations
5733    used by the time integrator.
5734 
5735    Not Collective
5736 
5737    Input Parameter:
5738 .  ts - TS context
5739 
5740    Output Parameter:
5741 .  nits - number of nonlinear iterations
5742 
5743    Notes:
5744    This counter is reset to zero for each successive call to TSSolve().
5745 
5746    Level: intermediate
5747 
5748 .keywords: TS, get, number, nonlinear, iterations
5749 
5750 .seealso:  TSGetKSPIterations()
5751 @*/
5752 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
5753 {
5754   PetscFunctionBegin;
5755   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5756   PetscValidIntPointer(nits,2);
5757   *nits = ts->snes_its;
5758   PetscFunctionReturn(0);
5759 }
5760 
5761 /*@
5762    TSGetKSPIterations - Gets the total number of linear iterations
5763    used by the time integrator.
5764 
5765    Not Collective
5766 
5767    Input Parameter:
5768 .  ts - TS context
5769 
5770    Output Parameter:
5771 .  lits - number of linear iterations
5772 
5773    Notes:
5774    This counter is reset to zero for each successive call to TSSolve().
5775 
5776    Level: intermediate
5777 
5778 .keywords: TS, get, number, linear, iterations
5779 
5780 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
5781 @*/
5782 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
5783 {
5784   PetscFunctionBegin;
5785   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5786   PetscValidIntPointer(lits,2);
5787   *lits = ts->ksp_its;
5788   PetscFunctionReturn(0);
5789 }
5790 
5791 /*@
5792    TSGetStepRejections - Gets the total number of rejected steps.
5793 
5794    Not Collective
5795 
5796    Input Parameter:
5797 .  ts - TS context
5798 
5799    Output Parameter:
5800 .  rejects - number of steps rejected
5801 
5802    Notes:
5803    This counter is reset to zero for each successive call to TSSolve().
5804 
5805    Level: intermediate
5806 
5807 .keywords: TS, get, number
5808 
5809 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
5810 @*/
5811 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
5812 {
5813   PetscFunctionBegin;
5814   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5815   PetscValidIntPointer(rejects,2);
5816   *rejects = ts->reject;
5817   PetscFunctionReturn(0);
5818 }
5819 
5820 /*@
5821    TSGetSNESFailures - Gets the total number of failed SNES solves
5822 
5823    Not Collective
5824 
5825    Input Parameter:
5826 .  ts - TS context
5827 
5828    Output Parameter:
5829 .  fails - number of failed nonlinear solves
5830 
5831    Notes:
5832    This counter is reset to zero for each successive call to TSSolve().
5833 
5834    Level: intermediate
5835 
5836 .keywords: TS, get, number
5837 
5838 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
5839 @*/
5840 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
5841 {
5842   PetscFunctionBegin;
5843   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5844   PetscValidIntPointer(fails,2);
5845   *fails = ts->num_snes_failures;
5846   PetscFunctionReturn(0);
5847 }
5848 
5849 /*@
5850    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
5851 
5852    Not Collective
5853 
5854    Input Parameter:
5855 +  ts - TS context
5856 -  rejects - maximum number of rejected steps, pass -1 for unlimited
5857 
5858    Notes:
5859    The counter is reset to zero for each step
5860 
5861    Options Database Key:
5862  .  -ts_max_reject - Maximum number of step rejections before a step fails
5863 
5864    Level: intermediate
5865 
5866 .keywords: TS, set, maximum, number
5867 
5868 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5869 @*/
5870 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
5871 {
5872   PetscFunctionBegin;
5873   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5874   ts->max_reject = rejects;
5875   PetscFunctionReturn(0);
5876 }
5877 
5878 /*@
5879    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
5880 
5881    Not Collective
5882 
5883    Input Parameter:
5884 +  ts - TS context
5885 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
5886 
5887    Notes:
5888    The counter is reset to zero for each successive call to TSSolve().
5889 
5890    Options Database Key:
5891  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
5892 
5893    Level: intermediate
5894 
5895 .keywords: TS, set, maximum, number
5896 
5897 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
5898 @*/
5899 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
5900 {
5901   PetscFunctionBegin;
5902   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5903   ts->max_snes_failures = fails;
5904   PetscFunctionReturn(0);
5905 }
5906 
5907 /*@
5908    TSSetErrorIfStepFails - Error if no step succeeds
5909 
5910    Not Collective
5911 
5912    Input Parameter:
5913 +  ts - TS context
5914 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
5915 
5916    Options Database Key:
5917  .  -ts_error_if_step_fails - Error if no step succeeds
5918 
5919    Level: intermediate
5920 
5921 .keywords: TS, set, error
5922 
5923 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
5924 @*/
5925 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
5926 {
5927   PetscFunctionBegin;
5928   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
5929   ts->errorifstepfailed = err;
5930   PetscFunctionReturn(0);
5931 }
5932 
5933 /*@C
5934    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
5935 
5936    Collective on TS
5937 
5938    Input Parameters:
5939 +  ts - the TS context
5940 .  step - current time-step
5941 .  ptime - current time
5942 .  u - current state
5943 -  vf - viewer and its format
5944 
5945    Level: intermediate
5946 
5947 .keywords: TS,  vector, monitor, view
5948 
5949 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5950 @*/
5951 PetscErrorCode  TSMonitorSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
5952 {
5953   PetscErrorCode ierr;
5954 
5955   PetscFunctionBegin;
5956   ierr = PetscViewerPushFormat(vf->viewer,vf->format);CHKERRQ(ierr);
5957   ierr = VecView(u,vf->viewer);CHKERRQ(ierr);
5958   ierr = PetscViewerPopFormat(vf->viewer);CHKERRQ(ierr);
5959   PetscFunctionReturn(0);
5960 }
5961 
5962 /*@C
5963    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
5964 
5965    Collective on TS
5966 
5967    Input Parameters:
5968 +  ts - the TS context
5969 .  step - current time-step
5970 .  ptime - current time
5971 .  u - current state
5972 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
5973 
5974    Level: intermediate
5975 
5976    Notes:
5977    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.
5978    These are named according to the file name template.
5979 
5980    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
5981 
5982 .keywords: TS,  vector, monitor, view
5983 
5984 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
5985 @*/
5986 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
5987 {
5988   PetscErrorCode ierr;
5989   char           filename[PETSC_MAX_PATH_LEN];
5990   PetscViewer    viewer;
5991 
5992   PetscFunctionBegin;
5993   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
5994   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
5995   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
5996   ierr = VecView(u,viewer);CHKERRQ(ierr);
5997   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5998   PetscFunctionReturn(0);
5999 }
6000 
6001 /*@C
6002    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
6003 
6004    Collective on TS
6005 
6006    Input Parameters:
6007 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
6008 
6009    Level: intermediate
6010 
6011    Note:
6012    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
6013 
6014 .keywords: TS,  vector, monitor, view
6015 
6016 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
6017 @*/
6018 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
6019 {
6020   PetscErrorCode ierr;
6021 
6022   PetscFunctionBegin;
6023   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
6024   PetscFunctionReturn(0);
6025 }
6026 
6027 /*@
6028    TSGetAdapt - Get the adaptive controller context for the current method
6029 
6030    Collective on TS if controller has not been created yet
6031 
6032    Input Arguments:
6033 .  ts - time stepping context
6034 
6035    Output Arguments:
6036 .  adapt - adaptive controller
6037 
6038    Level: intermediate
6039 
6040 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
6041 @*/
6042 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
6043 {
6044   PetscErrorCode ierr;
6045 
6046   PetscFunctionBegin;
6047   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6048   PetscValidPointer(adapt,2);
6049   if (!ts->adapt) {
6050     ierr = TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);CHKERRQ(ierr);
6051     ierr = PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt);CHKERRQ(ierr);
6052     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
6053   }
6054   *adapt = ts->adapt;
6055   PetscFunctionReturn(0);
6056 }
6057 
6058 /*@
6059    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
6060 
6061    Logically Collective
6062 
6063    Input Arguments:
6064 +  ts - time integration context
6065 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
6066 .  vatol - vector of absolute tolerances or NULL, used in preference to atol if present
6067 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
6068 -  vrtol - vector of relative tolerances or NULL, used in preference to atol if present
6069 
6070    Options Database keys:
6071 +  -ts_rtol <rtol> - relative tolerance for local truncation error
6072 -  -ts_atol <atol> Absolute tolerance for local truncation error
6073 
6074    Notes:
6075    With PETSc's implicit schemes for DAE problems, the calculation of the local truncation error
6076    (LTE) includes both the differential and the algebraic variables. If one wants the LTE to be
6077    computed only for the differential or the algebraic part then this can be done using the vector of
6078    tolerances vatol. For example, by setting the tolerance vector with the desired tolerance for the
6079    differential part and infinity for the algebraic part, the LTE calculation will include only the
6080    differential variables.
6081 
6082    Level: beginner
6083 
6084 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
6085 @*/
6086 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
6087 {
6088   PetscErrorCode ierr;
6089 
6090   PetscFunctionBegin;
6091   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
6092   if (vatol) {
6093     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
6094     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
6095     ts->vatol = vatol;
6096   }
6097   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
6098   if (vrtol) {
6099     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
6100     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
6101     ts->vrtol = vrtol;
6102   }
6103   PetscFunctionReturn(0);
6104 }
6105 
6106 /*@
6107    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
6108 
6109    Logically Collective
6110 
6111    Input Arguments:
6112 .  ts - time integration context
6113 
6114    Output Arguments:
6115 +  atol - scalar absolute tolerances, NULL to ignore
6116 .  vatol - vector of absolute tolerances, NULL to ignore
6117 .  rtol - scalar relative tolerances, NULL to ignore
6118 -  vrtol - vector of relative tolerances, NULL to ignore
6119 
6120    Level: beginner
6121 
6122 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
6123 @*/
6124 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
6125 {
6126   PetscFunctionBegin;
6127   if (atol)  *atol  = ts->atol;
6128   if (vatol) *vatol = ts->vatol;
6129   if (rtol)  *rtol  = ts->rtol;
6130   if (vrtol) *vrtol = ts->vrtol;
6131   PetscFunctionReturn(0);
6132 }
6133 
6134 /*@
6135    TSErrorWeightedNorm2 - compute a weighted 2-norm of the difference between two state vectors
6136 
6137    Collective on TS
6138 
6139    Input Arguments:
6140 +  ts - time stepping context
6141 .  U - state vector, usually ts->vec_sol
6142 -  Y - state vector to be compared to U
6143 
6144    Output Arguments:
6145 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6146 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6147 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6148 
6149    Level: developer
6150 
6151 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNormInfinity()
6152 @*/
6153 PetscErrorCode TSErrorWeightedNorm2(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6154 {
6155   PetscErrorCode    ierr;
6156   PetscInt          i,n,N,rstart;
6157   PetscInt          n_loc,na_loc,nr_loc;
6158   PetscReal         n_glb,na_glb,nr_glb;
6159   const PetscScalar *u,*y;
6160   PetscReal         sum,suma,sumr,gsum,gsuma,gsumr,diff;
6161   PetscReal         tol,tola,tolr;
6162   PetscReal         err_loc[6],err_glb[6];
6163 
6164   PetscFunctionBegin;
6165   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6166   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
6167   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
6168   PetscValidType(U,2);
6169   PetscValidType(Y,3);
6170   PetscCheckSameComm(U,2,Y,3);
6171   PetscValidPointer(norm,4);
6172   PetscValidPointer(norma,5);
6173   PetscValidPointer(normr,6);
6174   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
6175 
6176   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
6177   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
6178   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
6179   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6180   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6181   sum  = 0.; n_loc  = 0;
6182   suma = 0.; na_loc = 0;
6183   sumr = 0.; nr_loc = 0;
6184   if (ts->vatol && ts->vrtol) {
6185     const PetscScalar *atol,*rtol;
6186     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6187     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6188     for (i=0; i<n; i++) {
6189       diff = PetscAbsScalar(y[i] - u[i]);
6190       tola = PetscRealPart(atol[i]);
6191       if(tola>0.){
6192         suma  += PetscSqr(diff/tola);
6193         na_loc++;
6194       }
6195       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6196       if(tolr>0.){
6197         sumr  += PetscSqr(diff/tolr);
6198         nr_loc++;
6199       }
6200       tol=tola+tolr;
6201       if(tol>0.){
6202         sum  += PetscSqr(diff/tol);
6203         n_loc++;
6204       }
6205     }
6206     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6207     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6208   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6209     const PetscScalar *atol;
6210     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6211     for (i=0; i<n; i++) {
6212       diff = PetscAbsScalar(y[i] - u[i]);
6213       tola = PetscRealPart(atol[i]);
6214       if(tola>0.){
6215         suma  += PetscSqr(diff/tola);
6216         na_loc++;
6217       }
6218       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6219       if(tolr>0.){
6220         sumr  += PetscSqr(diff/tolr);
6221         nr_loc++;
6222       }
6223       tol=tola+tolr;
6224       if(tol>0.){
6225         sum  += PetscSqr(diff/tol);
6226         n_loc++;
6227       }
6228     }
6229     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6230   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6231     const PetscScalar *rtol;
6232     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6233     for (i=0; i<n; i++) {
6234       diff = PetscAbsScalar(y[i] - u[i]);
6235       tola = ts->atol;
6236       if(tola>0.){
6237         suma  += PetscSqr(diff/tola);
6238         na_loc++;
6239       }
6240       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6241       if(tolr>0.){
6242         sumr  += PetscSqr(diff/tolr);
6243         nr_loc++;
6244       }
6245       tol=tola+tolr;
6246       if(tol>0.){
6247         sum  += PetscSqr(diff/tol);
6248         n_loc++;
6249       }
6250     }
6251     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6252   } else {                      /* scalar atol, scalar rtol */
6253     for (i=0; i<n; i++) {
6254       diff = PetscAbsScalar(y[i] - u[i]);
6255      tola = ts->atol;
6256       if(tola>0.){
6257         suma  += PetscSqr(diff/tola);
6258         na_loc++;
6259       }
6260       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6261       if(tolr>0.){
6262         sumr  += PetscSqr(diff/tolr);
6263         nr_loc++;
6264       }
6265       tol=tola+tolr;
6266       if(tol>0.){
6267         sum  += PetscSqr(diff/tol);
6268         n_loc++;
6269       }
6270     }
6271   }
6272   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6273   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6274 
6275   err_loc[0] = sum;
6276   err_loc[1] = suma;
6277   err_loc[2] = sumr;
6278   err_loc[3] = (PetscReal)n_loc;
6279   err_loc[4] = (PetscReal)na_loc;
6280   err_loc[5] = (PetscReal)nr_loc;
6281 
6282   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6283 
6284   gsum   = err_glb[0];
6285   gsuma  = err_glb[1];
6286   gsumr  = err_glb[2];
6287   n_glb  = err_glb[3];
6288   na_glb = err_glb[4];
6289   nr_glb = err_glb[5];
6290 
6291   *norm  = 0.;
6292   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
6293   *norma = 0.;
6294   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
6295   *normr = 0.;
6296   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
6297 
6298   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6299   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6300   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6301   PetscFunctionReturn(0);
6302 }
6303 
6304 /*@
6305    TSErrorWeightedNormInfinity - compute a weighted infinity-norm of the difference between two state vectors
6306 
6307    Collective on TS
6308 
6309    Input Arguments:
6310 +  ts - time stepping context
6311 .  U - state vector, usually ts->vec_sol
6312 -  Y - state vector to be compared to U
6313 
6314    Output Arguments:
6315 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6316 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6317 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6318 
6319    Level: developer
6320 
6321 .seealso: TSErrorWeightedNorm(), TSErrorWeightedNorm2()
6322 @*/
6323 PetscErrorCode TSErrorWeightedNormInfinity(TS ts,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6324 {
6325   PetscErrorCode    ierr;
6326   PetscInt          i,n,N,rstart;
6327   const PetscScalar *u,*y;
6328   PetscReal         max,gmax,maxa,gmaxa,maxr,gmaxr;
6329   PetscReal         tol,tola,tolr,diff;
6330   PetscReal         err_loc[3],err_glb[3];
6331 
6332   PetscFunctionBegin;
6333   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6334   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
6335   PetscValidHeaderSpecific(Y,VEC_CLASSID,3);
6336   PetscValidType(U,2);
6337   PetscValidType(Y,3);
6338   PetscCheckSameComm(U,2,Y,3);
6339   PetscValidPointer(norm,4);
6340   PetscValidPointer(norma,5);
6341   PetscValidPointer(normr,6);
6342   if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"U and Y cannot be the same vector");
6343 
6344   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
6345   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
6346   ierr = VecGetOwnershipRange(U,&rstart,NULL);CHKERRQ(ierr);
6347   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6348   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6349 
6350   max=0.;
6351   maxa=0.;
6352   maxr=0.;
6353 
6354   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
6355     const PetscScalar *atol,*rtol;
6356     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6357     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6358 
6359     for (i=0; i<n; i++) {
6360       diff = PetscAbsScalar(y[i] - u[i]);
6361       tola = PetscRealPart(atol[i]);
6362       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6363       tol  = tola+tolr;
6364       if(tola>0.){
6365         maxa = PetscMax(maxa,diff / tola);
6366       }
6367       if(tolr>0.){
6368         maxr = PetscMax(maxr,diff / tolr);
6369       }
6370       if(tol>0.){
6371         max = PetscMax(max,diff / tol);
6372       }
6373     }
6374     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6375     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6376   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6377     const PetscScalar *atol;
6378     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6379     for (i=0; i<n; i++) {
6380       diff = PetscAbsScalar(y[i] - u[i]);
6381       tola = PetscRealPart(atol[i]);
6382       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6383       tol  = tola+tolr;
6384       if(tola>0.){
6385         maxa = PetscMax(maxa,diff / tola);
6386       }
6387       if(tolr>0.){
6388         maxr = PetscMax(maxr,diff / tolr);
6389       }
6390       if(tol>0.){
6391         max = PetscMax(max,diff / tol);
6392       }
6393     }
6394     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6395   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6396     const PetscScalar *rtol;
6397     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6398 
6399     for (i=0; i<n; i++) {
6400       diff = PetscAbsScalar(y[i] - u[i]);
6401       tola = ts->atol;
6402       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6403       tol  = tola+tolr;
6404       if(tola>0.){
6405         maxa = PetscMax(maxa,diff / tola);
6406       }
6407       if(tolr>0.){
6408         maxr = PetscMax(maxr,diff / tolr);
6409       }
6410       if(tol>0.){
6411         max = PetscMax(max,diff / tol);
6412       }
6413     }
6414     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6415   } else {                      /* scalar atol, scalar rtol */
6416 
6417     for (i=0; i<n; i++) {
6418       diff = PetscAbsScalar(y[i] - u[i]);
6419       tola = ts->atol;
6420       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6421       tol  = tola+tolr;
6422       if(tola>0.){
6423         maxa = PetscMax(maxa,diff / tola);
6424       }
6425       if(tolr>0.){
6426         maxr = PetscMax(maxr,diff / tolr);
6427       }
6428       if(tol>0.){
6429         max = PetscMax(max,diff / tol);
6430       }
6431     }
6432   }
6433   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6434   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6435   err_loc[0] = max;
6436   err_loc[1] = maxa;
6437   err_loc[2] = maxr;
6438   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6439   gmax   = err_glb[0];
6440   gmaxa  = err_glb[1];
6441   gmaxr  = err_glb[2];
6442 
6443   *norm = gmax;
6444   *norma = gmaxa;
6445   *normr = gmaxr;
6446   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6447     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6448     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6449   PetscFunctionReturn(0);
6450 }
6451 
6452 /*@
6453    TSErrorWeightedNorm - compute a weighted norm of the difference between two state vectors based on supplied absolute and relative tolerances
6454 
6455    Collective on TS
6456 
6457    Input Arguments:
6458 +  ts - time stepping context
6459 .  U - state vector, usually ts->vec_sol
6460 .  Y - state vector to be compared to U
6461 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6462 
6463    Output Arguments:
6464 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6465 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6466 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6467 
6468    Options Database Keys:
6469 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6470 
6471    Level: developer
6472 
6473 .seealso: TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2(), TSErrorWeightedENorm
6474 @*/
6475 PetscErrorCode TSErrorWeightedNorm(TS ts,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6476 {
6477   PetscErrorCode ierr;
6478 
6479   PetscFunctionBegin;
6480   if (wnormtype == NORM_2) {
6481     ierr = TSErrorWeightedNorm2(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
6482   } else if(wnormtype == NORM_INFINITY) {
6483     ierr = TSErrorWeightedNormInfinity(ts,U,Y,norm,norma,normr);CHKERRQ(ierr);
6484   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6485   PetscFunctionReturn(0);
6486 }
6487 
6488 
6489 /*@
6490    TSErrorWeightedENorm2 - compute a weighted 2 error norm based on supplied absolute and relative tolerances
6491 
6492    Collective on TS
6493 
6494    Input Arguments:
6495 +  ts - time stepping context
6496 .  E - error vector
6497 .  U - state vector, usually ts->vec_sol
6498 -  Y - state vector, previous time step
6499 
6500    Output Arguments:
6501 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6502 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6503 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6504 
6505    Level: developer
6506 
6507 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENormInfinity()
6508 @*/
6509 PetscErrorCode TSErrorWeightedENorm2(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6510 {
6511   PetscErrorCode    ierr;
6512   PetscInt          i,n,N,rstart;
6513   PetscInt          n_loc,na_loc,nr_loc;
6514   PetscReal         n_glb,na_glb,nr_glb;
6515   const PetscScalar *e,*u,*y;
6516   PetscReal         err,sum,suma,sumr,gsum,gsuma,gsumr;
6517   PetscReal         tol,tola,tolr;
6518   PetscReal         err_loc[6],err_glb[6];
6519 
6520   PetscFunctionBegin;
6521   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6522   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
6523   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
6524   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
6525   PetscValidType(E,2);
6526   PetscValidType(U,3);
6527   PetscValidType(Y,4);
6528   PetscCheckSameComm(E,2,U,3);
6529   PetscCheckSameComm(U,2,Y,3);
6530   PetscValidPointer(norm,5);
6531   PetscValidPointer(norma,6);
6532   PetscValidPointer(normr,7);
6533 
6534   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
6535   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
6536   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
6537   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
6538   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6539   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6540   sum  = 0.; n_loc  = 0;
6541   suma = 0.; na_loc = 0;
6542   sumr = 0.; nr_loc = 0;
6543   if (ts->vatol && ts->vrtol) {
6544     const PetscScalar *atol,*rtol;
6545     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6546     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6547     for (i=0; i<n; i++) {
6548       err = PetscAbsScalar(e[i]);
6549       tola = PetscRealPart(atol[i]);
6550       if(tola>0.){
6551         suma  += PetscSqr(err/tola);
6552         na_loc++;
6553       }
6554       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6555       if(tolr>0.){
6556         sumr  += PetscSqr(err/tolr);
6557         nr_loc++;
6558       }
6559       tol=tola+tolr;
6560       if(tol>0.){
6561         sum  += PetscSqr(err/tol);
6562         n_loc++;
6563       }
6564     }
6565     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6566     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6567   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6568     const PetscScalar *atol;
6569     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6570     for (i=0; i<n; i++) {
6571       err = PetscAbsScalar(e[i]);
6572       tola = PetscRealPart(atol[i]);
6573       if(tola>0.){
6574         suma  += PetscSqr(err/tola);
6575         na_loc++;
6576       }
6577       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6578       if(tolr>0.){
6579         sumr  += PetscSqr(err/tolr);
6580         nr_loc++;
6581       }
6582       tol=tola+tolr;
6583       if(tol>0.){
6584         sum  += PetscSqr(err/tol);
6585         n_loc++;
6586       }
6587     }
6588     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6589   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6590     const PetscScalar *rtol;
6591     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6592     for (i=0; i<n; i++) {
6593       err = PetscAbsScalar(e[i]);
6594       tola = ts->atol;
6595       if(tola>0.){
6596         suma  += PetscSqr(err/tola);
6597         na_loc++;
6598       }
6599       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6600       if(tolr>0.){
6601         sumr  += PetscSqr(err/tolr);
6602         nr_loc++;
6603       }
6604       tol=tola+tolr;
6605       if(tol>0.){
6606         sum  += PetscSqr(err/tol);
6607         n_loc++;
6608       }
6609     }
6610     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6611   } else {                      /* scalar atol, scalar rtol */
6612     for (i=0; i<n; i++) {
6613       err = PetscAbsScalar(e[i]);
6614      tola = ts->atol;
6615       if(tola>0.){
6616         suma  += PetscSqr(err/tola);
6617         na_loc++;
6618       }
6619       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6620       if(tolr>0.){
6621         sumr  += PetscSqr(err/tolr);
6622         nr_loc++;
6623       }
6624       tol=tola+tolr;
6625       if(tol>0.){
6626         sum  += PetscSqr(err/tol);
6627         n_loc++;
6628       }
6629     }
6630   }
6631   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6632   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6633   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6634 
6635   err_loc[0] = sum;
6636   err_loc[1] = suma;
6637   err_loc[2] = sumr;
6638   err_loc[3] = (PetscReal)n_loc;
6639   err_loc[4] = (PetscReal)na_loc;
6640   err_loc[5] = (PetscReal)nr_loc;
6641 
6642   ierr = MPIU_Allreduce(err_loc,err_glb,6,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6643 
6644   gsum   = err_glb[0];
6645   gsuma  = err_glb[1];
6646   gsumr  = err_glb[2];
6647   n_glb  = err_glb[3];
6648   na_glb = err_glb[4];
6649   nr_glb = err_glb[5];
6650 
6651   *norm  = 0.;
6652   if(n_glb>0. ){*norm  = PetscSqrtReal(gsum  / n_glb );}
6653   *norma = 0.;
6654   if(na_glb>0.){*norma = PetscSqrtReal(gsuma / na_glb);}
6655   *normr = 0.;
6656   if(nr_glb>0.){*normr = PetscSqrtReal(gsumr / nr_glb);}
6657 
6658   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6659   if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6660   if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6661   PetscFunctionReturn(0);
6662 }
6663 
6664 /*@
6665    TSErrorWeightedENormInfinity - compute a weighted infinity error norm based on supplied absolute and relative tolerances
6666    Collective on TS
6667 
6668    Input Arguments:
6669 +  ts - time stepping context
6670 .  E - error vector
6671 .  U - state vector, usually ts->vec_sol
6672 -  Y - state vector, previous time step
6673 
6674    Output Arguments:
6675 .  norm - weighted norm, a value of 1.0 means that the error matches the tolerances
6676 .  norma - weighted norm based on the absolute tolerance, a value of 1.0 means that the error matches the tolerances
6677 .  normr - weighted norm based on the relative tolerance, a value of 1.0 means that the error matches the tolerances
6678 
6679    Level: developer
6680 
6681 .seealso: TSErrorWeightedENorm(), TSErrorWeightedENorm2()
6682 @*/
6683 PetscErrorCode TSErrorWeightedENormInfinity(TS ts,Vec E,Vec U,Vec Y,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6684 {
6685   PetscErrorCode    ierr;
6686   PetscInt          i,n,N,rstart;
6687   const PetscScalar *e,*u,*y;
6688   PetscReal         err,max,gmax,maxa,gmaxa,maxr,gmaxr;
6689   PetscReal         tol,tola,tolr;
6690   PetscReal         err_loc[3],err_glb[3];
6691 
6692   PetscFunctionBegin;
6693   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6694   PetscValidHeaderSpecific(E,VEC_CLASSID,2);
6695   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
6696   PetscValidHeaderSpecific(Y,VEC_CLASSID,4);
6697   PetscValidType(E,2);
6698   PetscValidType(U,3);
6699   PetscValidType(Y,4);
6700   PetscCheckSameComm(E,2,U,3);
6701   PetscCheckSameComm(U,2,Y,3);
6702   PetscValidPointer(norm,5);
6703   PetscValidPointer(norma,6);
6704   PetscValidPointer(normr,7);
6705 
6706   ierr = VecGetSize(E,&N);CHKERRQ(ierr);
6707   ierr = VecGetLocalSize(E,&n);CHKERRQ(ierr);
6708   ierr = VecGetOwnershipRange(E,&rstart,NULL);CHKERRQ(ierr);
6709   ierr = VecGetArrayRead(E,&e);CHKERRQ(ierr);
6710   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
6711   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
6712 
6713   max=0.;
6714   maxa=0.;
6715   maxr=0.;
6716 
6717   if (ts->vatol && ts->vrtol) {     /* vector atol, vector rtol */
6718     const PetscScalar *atol,*rtol;
6719     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6720     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6721 
6722     for (i=0; i<n; i++) {
6723       err = PetscAbsScalar(e[i]);
6724       tola = PetscRealPart(atol[i]);
6725       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6726       tol  = tola+tolr;
6727       if(tola>0.){
6728         maxa = PetscMax(maxa,err / tola);
6729       }
6730       if(tolr>0.){
6731         maxr = PetscMax(maxr,err / tolr);
6732       }
6733       if(tol>0.){
6734         max = PetscMax(max,err / tol);
6735       }
6736     }
6737     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6738     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6739   } else if (ts->vatol) {       /* vector atol, scalar rtol */
6740     const PetscScalar *atol;
6741     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6742     for (i=0; i<n; i++) {
6743       err = PetscAbsScalar(e[i]);
6744       tola = PetscRealPart(atol[i]);
6745       tolr = ts->rtol  * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6746       tol  = tola+tolr;
6747       if(tola>0.){
6748         maxa = PetscMax(maxa,err / tola);
6749       }
6750       if(tolr>0.){
6751         maxr = PetscMax(maxr,err / tolr);
6752       }
6753       if(tol>0.){
6754         max = PetscMax(max,err / tol);
6755       }
6756     }
6757     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
6758   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
6759     const PetscScalar *rtol;
6760     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6761 
6762     for (i=0; i<n; i++) {
6763       err = PetscAbsScalar(e[i]);
6764       tola = ts->atol;
6765       tolr = PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6766       tol  = tola+tolr;
6767       if(tola>0.){
6768         maxa = PetscMax(maxa,err / tola);
6769       }
6770       if(tolr>0.){
6771         maxr = PetscMax(maxr,err / tolr);
6772       }
6773       if(tol>0.){
6774         max = PetscMax(max,err / tol);
6775       }
6776     }
6777     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
6778   } else {                      /* scalar atol, scalar rtol */
6779 
6780     for (i=0; i<n; i++) {
6781       err = PetscAbsScalar(e[i]);
6782       tola = ts->atol;
6783       tolr = ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
6784       tol  = tola+tolr;
6785       if(tola>0.){
6786         maxa = PetscMax(maxa,err / tola);
6787       }
6788       if(tolr>0.){
6789         maxr = PetscMax(maxr,err / tolr);
6790       }
6791       if(tol>0.){
6792         max = PetscMax(max,err / tol);
6793       }
6794     }
6795   }
6796   ierr = VecRestoreArrayRead(E,&e);CHKERRQ(ierr);
6797   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
6798   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
6799   err_loc[0] = max;
6800   err_loc[1] = maxa;
6801   err_loc[2] = maxr;
6802   ierr  = MPIU_Allreduce(err_loc,err_glb,3,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6803   gmax   = err_glb[0];
6804   gmaxa  = err_glb[1];
6805   gmaxr  = err_glb[2];
6806 
6807   *norm = gmax;
6808   *norma = gmaxa;
6809   *normr = gmaxr;
6810   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
6811     if (PetscIsInfOrNanScalar(*norma)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norma");
6812     if (PetscIsInfOrNanScalar(*normr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in normr");
6813   PetscFunctionReturn(0);
6814 }
6815 
6816 /*@
6817    TSErrorWeightedENorm - compute a weighted error norm based on supplied absolute and relative tolerances
6818 
6819    Collective on TS
6820 
6821    Input Arguments:
6822 +  ts - time stepping context
6823 .  E - error vector
6824 .  U - state vector, usually ts->vec_sol
6825 .  Y - state vector, previous time step
6826 -  wnormtype - norm type, either NORM_2 or NORM_INFINITY
6827 
6828    Output Arguments:
6829 .  norm  - weighted norm, a value of 1.0 achieves a balance between absolute and relative tolerances
6830 .  norma - weighted norm, a value of 1.0 means that the error meets the absolute tolerance set by the user
6831 .  normr - weighted norm, a value of 1.0 means that the error meets the relative tolerance set by the user
6832 
6833    Options Database Keys:
6834 .  -ts_adapt_wnormtype <wnormtype> - 2, INFINITY
6835 
6836    Level: developer
6837 
6838 .seealso: TSErrorWeightedENormInfinity(), TSErrorWeightedENorm2(), TSErrorWeightedNormInfinity(), TSErrorWeightedNorm2()
6839 @*/
6840 PetscErrorCode TSErrorWeightedENorm(TS ts,Vec E,Vec U,Vec Y,NormType wnormtype,PetscReal *norm,PetscReal *norma,PetscReal *normr)
6841 {
6842   PetscErrorCode ierr;
6843 
6844   PetscFunctionBegin;
6845   if (wnormtype == NORM_2) {
6846     ierr = TSErrorWeightedENorm2(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6847   } else if(wnormtype == NORM_INFINITY) {
6848     ierr = TSErrorWeightedENormInfinity(ts,E,U,Y,norm,norma,normr);CHKERRQ(ierr);
6849   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for norm type %s",NormTypes[wnormtype]);
6850   PetscFunctionReturn(0);
6851 }
6852 
6853 
6854 /*@
6855    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
6856 
6857    Logically Collective on TS
6858 
6859    Input Arguments:
6860 +  ts - time stepping context
6861 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
6862 
6863    Note:
6864    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
6865 
6866    Level: intermediate
6867 
6868 .seealso: TSGetCFLTime(), TSADAPTCFL
6869 @*/
6870 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
6871 {
6872   PetscFunctionBegin;
6873   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
6874   ts->cfltime_local = cfltime;
6875   ts->cfltime       = -1.;
6876   PetscFunctionReturn(0);
6877 }
6878 
6879 /*@
6880    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
6881 
6882    Collective on TS
6883 
6884    Input Arguments:
6885 .  ts - time stepping context
6886 
6887    Output Arguments:
6888 .  cfltime - maximum stable time step for forward Euler
6889 
6890    Level: advanced
6891 
6892 .seealso: TSSetCFLTimeLocal()
6893 @*/
6894 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
6895 {
6896   PetscErrorCode ierr;
6897 
6898   PetscFunctionBegin;
6899   if (ts->cfltime < 0) {
6900     ierr = MPIU_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));CHKERRQ(ierr);
6901   }
6902   *cfltime = ts->cfltime;
6903   PetscFunctionReturn(0);
6904 }
6905 
6906 /*@
6907    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
6908 
6909    Input Parameters:
6910 .  ts   - the TS context.
6911 .  xl   - lower bound.
6912 .  xu   - upper bound.
6913 
6914    Notes:
6915    If this routine is not called then the lower and upper bounds are set to
6916    PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
6917 
6918    Level: advanced
6919 
6920 @*/
6921 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
6922 {
6923   PetscErrorCode ierr;
6924   SNES           snes;
6925 
6926   PetscFunctionBegin;
6927   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
6928   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
6929   PetscFunctionReturn(0);
6930 }
6931 
6932 #if defined(PETSC_HAVE_MATLAB_ENGINE)
6933 #include <mex.h>
6934 
6935 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
6936 
6937 /*
6938    TSComputeFunction_Matlab - Calls the function that has been set with
6939                          TSSetFunctionMatlab().
6940 
6941    Collective on TS
6942 
6943    Input Parameters:
6944 +  snes - the TS context
6945 -  u - input vector
6946 
6947    Output Parameter:
6948 .  y - function vector, as set by TSSetFunction()
6949 
6950    Notes:
6951    TSComputeFunction() is typically used within nonlinear solvers
6952    implementations, so most users would not generally call this routine
6953    themselves.
6954 
6955    Level: developer
6956 
6957 .keywords: TS, nonlinear, compute, function
6958 
6959 .seealso: TSSetFunction(), TSGetFunction()
6960 */
6961 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
6962 {
6963   PetscErrorCode  ierr;
6964   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
6965   int             nlhs  = 1,nrhs = 7;
6966   mxArray         *plhs[1],*prhs[7];
6967   long long int   lx = 0,lxdot = 0,ly = 0,ls = 0;
6968 
6969   PetscFunctionBegin;
6970   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
6971   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
6972   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
6973   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
6974   PetscCheckSameComm(snes,1,u,3);
6975   PetscCheckSameComm(snes,1,y,5);
6976 
6977   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
6978   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
6979   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
6980   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
6981 
6982   prhs[0] =  mxCreateDoubleScalar((double)ls);
6983   prhs[1] =  mxCreateDoubleScalar(time);
6984   prhs[2] =  mxCreateDoubleScalar((double)lx);
6985   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
6986   prhs[4] =  mxCreateDoubleScalar((double)ly);
6987   prhs[5] =  mxCreateString(sctx->funcname);
6988   prhs[6] =  sctx->ctx;
6989   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
6990   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
6991   mxDestroyArray(prhs[0]);
6992   mxDestroyArray(prhs[1]);
6993   mxDestroyArray(prhs[2]);
6994   mxDestroyArray(prhs[3]);
6995   mxDestroyArray(prhs[4]);
6996   mxDestroyArray(prhs[5]);
6997   mxDestroyArray(plhs[0]);
6998   PetscFunctionReturn(0);
6999 }
7000 
7001 /*
7002    TSSetFunctionMatlab - Sets the function evaluation routine and function
7003    vector for use by the TS routines in solving ODEs
7004    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
7005 
7006    Logically Collective on TS
7007 
7008    Input Parameters:
7009 +  ts - the TS context
7010 -  func - function evaluation routine
7011 
7012    Calling sequence of func:
7013 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
7014 
7015    Level: beginner
7016 
7017 .keywords: TS, nonlinear, set, function
7018 
7019 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
7020 */
7021 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
7022 {
7023   PetscErrorCode  ierr;
7024   TSMatlabContext *sctx;
7025 
7026   PetscFunctionBegin;
7027   /* currently sctx is memory bleed */
7028   ierr = PetscNew(&sctx);CHKERRQ(ierr);
7029   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
7030   /*
7031      This should work, but it doesn't
7032   sctx->ctx = ctx;
7033   mexMakeArrayPersistent(sctx->ctx);
7034   */
7035   sctx->ctx = mxDuplicateArray(ctx);
7036 
7037   ierr = TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
7038   PetscFunctionReturn(0);
7039 }
7040 
7041 /*
7042    TSComputeJacobian_Matlab - Calls the function that has been set with
7043                          TSSetJacobianMatlab().
7044 
7045    Collective on TS
7046 
7047    Input Parameters:
7048 +  ts - the TS context
7049 .  u - input vector
7050 .  A, B - the matrices
7051 -  ctx - user context
7052 
7053    Level: developer
7054 
7055 .keywords: TS, nonlinear, compute, function
7056 
7057 .seealso: TSSetFunction(), TSGetFunction()
7058 @*/
7059 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat A,Mat B,void *ctx)
7060 {
7061   PetscErrorCode  ierr;
7062   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
7063   int             nlhs  = 2,nrhs = 9;
7064   mxArray         *plhs[2],*prhs[9];
7065   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
7066 
7067   PetscFunctionBegin;
7068   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7069   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
7070 
7071   /* call Matlab function in ctx with arguments u and y */
7072 
7073   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
7074   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
7075   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
7076   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
7077   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
7078 
7079   prhs[0] =  mxCreateDoubleScalar((double)ls);
7080   prhs[1] =  mxCreateDoubleScalar((double)time);
7081   prhs[2] =  mxCreateDoubleScalar((double)lx);
7082   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
7083   prhs[4] =  mxCreateDoubleScalar((double)shift);
7084   prhs[5] =  mxCreateDoubleScalar((double)lA);
7085   prhs[6] =  mxCreateDoubleScalar((double)lB);
7086   prhs[7] =  mxCreateString(sctx->funcname);
7087   prhs[8] =  sctx->ctx;
7088   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
7089   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
7090   mxDestroyArray(prhs[0]);
7091   mxDestroyArray(prhs[1]);
7092   mxDestroyArray(prhs[2]);
7093   mxDestroyArray(prhs[3]);
7094   mxDestroyArray(prhs[4]);
7095   mxDestroyArray(prhs[5]);
7096   mxDestroyArray(prhs[6]);
7097   mxDestroyArray(prhs[7]);
7098   mxDestroyArray(plhs[0]);
7099   mxDestroyArray(plhs[1]);
7100   PetscFunctionReturn(0);
7101 }
7102 
7103 /*
7104    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
7105    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
7106 
7107    Logically Collective on TS
7108 
7109    Input Parameters:
7110 +  ts - the TS context
7111 .  A,B - Jacobian matrices
7112 .  func - function evaluation routine
7113 -  ctx - user context
7114 
7115    Calling sequence of func:
7116 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
7117 
7118    Level: developer
7119 
7120 .keywords: TS, nonlinear, set, function
7121 
7122 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
7123 */
7124 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
7125 {
7126   PetscErrorCode  ierr;
7127   TSMatlabContext *sctx;
7128 
7129   PetscFunctionBegin;
7130   /* currently sctx is memory bleed */
7131   ierr = PetscNew(&sctx);CHKERRQ(ierr);
7132   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
7133   /*
7134      This should work, but it doesn't
7135   sctx->ctx = ctx;
7136   mexMakeArrayPersistent(sctx->ctx);
7137   */
7138   sctx->ctx = mxDuplicateArray(ctx);
7139 
7140   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
7141   PetscFunctionReturn(0);
7142 }
7143 
7144 /*
7145    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
7146 
7147    Collective on TS
7148 
7149 .seealso: TSSetFunction(), TSGetFunction()
7150 @*/
7151 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
7152 {
7153   PetscErrorCode  ierr;
7154   TSMatlabContext *sctx = (TSMatlabContext*)ctx;
7155   int             nlhs  = 1,nrhs = 6;
7156   mxArray         *plhs[1],*prhs[6];
7157   long long int   lx = 0,ls = 0;
7158 
7159   PetscFunctionBegin;
7160   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7161   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
7162 
7163   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
7164   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
7165 
7166   prhs[0] =  mxCreateDoubleScalar((double)ls);
7167   prhs[1] =  mxCreateDoubleScalar((double)it);
7168   prhs[2] =  mxCreateDoubleScalar((double)time);
7169   prhs[3] =  mxCreateDoubleScalar((double)lx);
7170   prhs[4] =  mxCreateString(sctx->funcname);
7171   prhs[5] =  sctx->ctx;
7172   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
7173   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
7174   mxDestroyArray(prhs[0]);
7175   mxDestroyArray(prhs[1]);
7176   mxDestroyArray(prhs[2]);
7177   mxDestroyArray(prhs[3]);
7178   mxDestroyArray(prhs[4]);
7179   mxDestroyArray(plhs[0]);
7180   PetscFunctionReturn(0);
7181 }
7182 
7183 /*
7184    TSMonitorSetMatlab - Sets the monitor function from Matlab
7185 
7186    Level: developer
7187 
7188 .keywords: TS, nonlinear, set, function
7189 
7190 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
7191 */
7192 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
7193 {
7194   PetscErrorCode  ierr;
7195   TSMatlabContext *sctx;
7196 
7197   PetscFunctionBegin;
7198   /* currently sctx is memory bleed */
7199   ierr = PetscNew(&sctx);CHKERRQ(ierr);
7200   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
7201   /*
7202      This should work, but it doesn't
7203   sctx->ctx = ctx;
7204   mexMakeArrayPersistent(sctx->ctx);
7205   */
7206   sctx->ctx = mxDuplicateArray(ctx);
7207 
7208   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);CHKERRQ(ierr);
7209   PetscFunctionReturn(0);
7210 }
7211 #endif
7212 
7213 /*@C
7214    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
7215        in a time based line graph
7216 
7217    Collective on TS
7218 
7219    Input Parameters:
7220 +  ts - the TS context
7221 .  step - current time-step
7222 .  ptime - current time
7223 .  u - current solution
7224 -  dctx - the TSMonitorLGCtx object that contains all the options for the monitoring, this is created with TSMonitorLGCtxCreate()
7225 
7226    Options Database:
7227 .   -ts_monitor_lg_solution_variables
7228 
7229    Level: intermediate
7230 
7231    Notes: Each process in a parallel run displays its component solutions in a separate window
7232 
7233 .keywords: TS,  vector, monitor, view
7234 
7235 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGCtxCreate(), TSMonitorLGCtxSetVariableNames(), TSMonitorLGCtxGetVariableNames(),
7236            TSMonitorLGSetVariableNames(), TSMonitorLGGetVariableNames(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetDisplayVariables(),
7237            TSMonitorLGCtxSetTransform(), TSMonitorLGSetTransform(), TSMonitorLGError(), TSMonitorLGSNESIterations(), TSMonitorLGKSPIterations(),
7238            TSMonitorEnvelopeCtxCreate(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxDestroy(), TSMonitorEnvelop()
7239 @*/
7240 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
7241 {
7242   PetscErrorCode    ierr;
7243   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dctx;
7244   const PetscScalar *yy;
7245   Vec               v;
7246 
7247   PetscFunctionBegin;
7248   if (step < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7249   if (!step) {
7250     PetscDrawAxis axis;
7251     PetscInt      dim;
7252     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7253     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
7254     if (!ctx->names) {
7255       PetscBool flg;
7256       /* user provides names of variables to plot but no names has been set so assume names are integer values */
7257       ierr = PetscOptionsHasName(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",&flg);CHKERRQ(ierr);
7258       if (flg) {
7259         PetscInt i,n;
7260         char     **names;
7261         ierr = VecGetSize(u,&n);CHKERRQ(ierr);
7262         ierr = PetscMalloc1(n+1,&names);CHKERRQ(ierr);
7263         for (i=0; i<n; i++) {
7264           ierr = PetscMalloc1(5,&names[i]);CHKERRQ(ierr);
7265           ierr = PetscSNPrintf(names[i],5,"%D",i);CHKERRQ(ierr);
7266         }
7267         names[n] = NULL;
7268         ctx->names = names;
7269       }
7270     }
7271     if (ctx->names && !ctx->displaynames) {
7272       char      **displaynames;
7273       PetscBool flg;
7274       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7275       ierr = PetscMalloc1(dim+1,&displaynames);CHKERRQ(ierr);
7276       ierr = PetscMemzero(displaynames,(dim+1)*sizeof(char*));CHKERRQ(ierr);
7277       ierr = PetscOptionsGetStringArray(((PetscObject)ts)->options,((PetscObject)ts)->prefix,"-ts_monitor_lg_solution_variables",displaynames,&dim,&flg);CHKERRQ(ierr);
7278       if (flg) {
7279         ierr = TSMonitorLGCtxSetDisplayVariables(ctx,(const char *const *)displaynames);CHKERRQ(ierr);
7280       }
7281       ierr = PetscStrArrayDestroy(&displaynames);CHKERRQ(ierr);
7282     }
7283     if (ctx->displaynames) {
7284       ierr = PetscDrawLGSetDimension(ctx->lg,ctx->ndisplayvariables);CHKERRQ(ierr);
7285       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->displaynames);CHKERRQ(ierr);
7286     } else if (ctx->names) {
7287       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7288       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
7289       ierr = PetscDrawLGSetLegend(ctx->lg,(const char *const *)ctx->names);CHKERRQ(ierr);
7290     } else {
7291       ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7292       ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
7293     }
7294     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7295   }
7296 
7297   if (!ctx->transform) v = u;
7298   else {ierr = (*ctx->transform)(ctx->transformctx,u,&v);CHKERRQ(ierr);}
7299   ierr = VecGetArrayRead(v,&yy);CHKERRQ(ierr);
7300   if (ctx->displaynames) {
7301     PetscInt i;
7302     for (i=0; i<ctx->ndisplayvariables; i++)
7303       ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
7304     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,ctx->displayvalues);CHKERRQ(ierr);
7305   } else {
7306 #if defined(PETSC_USE_COMPLEX)
7307     PetscInt  i,n;
7308     PetscReal *yreal;
7309     ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
7310     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
7311     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
7312     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
7313     ierr = PetscFree(yreal);CHKERRQ(ierr);
7314 #else
7315     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
7316 #endif
7317   }
7318   ierr = VecRestoreArrayRead(v,&yy);CHKERRQ(ierr);
7319   if (ctx->transform) {ierr = VecDestroy(&v);CHKERRQ(ierr);}
7320 
7321   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
7322     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7323     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7324   }
7325   PetscFunctionReturn(0);
7326 }
7327 
7328 /*@C
7329    TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
7330 
7331    Collective on TS
7332 
7333    Input Parameters:
7334 +  ts - the TS context
7335 -  names - the names of the components, final string must be NULL
7336 
7337    Level: intermediate
7338 
7339    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7340 
7341 .keywords: TS,  vector, monitor, view
7342 
7343 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGCtxSetVariableNames()
7344 @*/
7345 PetscErrorCode  TSMonitorLGSetVariableNames(TS ts,const char * const *names)
7346 {
7347   PetscErrorCode    ierr;
7348   PetscInt          i;
7349 
7350   PetscFunctionBegin;
7351   for (i=0; i<ts->numbermonitors; i++) {
7352     if (ts->monitor[i] == TSMonitorLGSolution) {
7353       ierr = TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i],names);CHKERRQ(ierr);
7354       break;
7355     }
7356   }
7357   PetscFunctionReturn(0);
7358 }
7359 
7360 /*@C
7361    TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
7362 
7363    Collective on TS
7364 
7365    Input Parameters:
7366 +  ts - the TS context
7367 -  names - the names of the components, final string must be NULL
7368 
7369    Level: intermediate
7370 
7371 .keywords: TS,  vector, monitor, view
7372 
7373 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables(), TSMonitorLGSetVariableNames()
7374 @*/
7375 PetscErrorCode  TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx,const char * const *names)
7376 {
7377   PetscErrorCode    ierr;
7378 
7379   PetscFunctionBegin;
7380   ierr = PetscStrArrayDestroy(&ctx->names);CHKERRQ(ierr);
7381   ierr = PetscStrArrayallocpy(names,&ctx->names);CHKERRQ(ierr);
7382   PetscFunctionReturn(0);
7383 }
7384 
7385 /*@C
7386    TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
7387 
7388    Collective on TS
7389 
7390    Input Parameter:
7391 .  ts - the TS context
7392 
7393    Output Parameter:
7394 .  names - the names of the components, final string must be NULL
7395 
7396    Level: intermediate
7397 
7398    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7399 
7400 .keywords: TS,  vector, monitor, view
7401 
7402 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
7403 @*/
7404 PetscErrorCode  TSMonitorLGGetVariableNames(TS ts,const char *const **names)
7405 {
7406   PetscInt       i;
7407 
7408   PetscFunctionBegin;
7409   *names = NULL;
7410   for (i=0; i<ts->numbermonitors; i++) {
7411     if (ts->monitor[i] == TSMonitorLGSolution) {
7412       TSMonitorLGCtx  ctx = (TSMonitorLGCtx) ts->monitorcontext[i];
7413       *names = (const char *const *)ctx->names;
7414       break;
7415     }
7416   }
7417   PetscFunctionReturn(0);
7418 }
7419 
7420 /*@C
7421    TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
7422 
7423    Collective on TS
7424 
7425    Input Parameters:
7426 +  ctx - the TSMonitorLG context
7427 .  displaynames - the names of the components, final string must be NULL
7428 
7429    Level: intermediate
7430 
7431 .keywords: TS,  vector, monitor, view
7432 
7433 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
7434 @*/
7435 PetscErrorCode  TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx,const char * const *displaynames)
7436 {
7437   PetscInt          j = 0,k;
7438   PetscErrorCode    ierr;
7439 
7440   PetscFunctionBegin;
7441   if (!ctx->names) PetscFunctionReturn(0);
7442   ierr = PetscStrArrayDestroy(&ctx->displaynames);CHKERRQ(ierr);
7443   ierr = PetscStrArrayallocpy(displaynames,&ctx->displaynames);CHKERRQ(ierr);
7444   while (displaynames[j]) j++;
7445   ctx->ndisplayvariables = j;
7446   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvariables);CHKERRQ(ierr);
7447   ierr = PetscMalloc1(ctx->ndisplayvariables,&ctx->displayvalues);CHKERRQ(ierr);
7448   j = 0;
7449   while (displaynames[j]) {
7450     k = 0;
7451     while (ctx->names[k]) {
7452       PetscBool flg;
7453       ierr = PetscStrcmp(displaynames[j],ctx->names[k],&flg);CHKERRQ(ierr);
7454       if (flg) {
7455         ctx->displayvariables[j] = k;
7456         break;
7457       }
7458       k++;
7459     }
7460     j++;
7461   }
7462   PetscFunctionReturn(0);
7463 }
7464 
7465 /*@C
7466    TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
7467 
7468    Collective on TS
7469 
7470    Input Parameters:
7471 +  ts - the TS context
7472 .  displaynames - the names of the components, final string must be NULL
7473 
7474    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7475 
7476    Level: intermediate
7477 
7478 .keywords: TS,  vector, monitor, view
7479 
7480 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames()
7481 @*/
7482 PetscErrorCode  TSMonitorLGSetDisplayVariables(TS ts,const char * const *displaynames)
7483 {
7484   PetscInt          i;
7485   PetscErrorCode    ierr;
7486 
7487   PetscFunctionBegin;
7488   for (i=0; i<ts->numbermonitors; i++) {
7489     if (ts->monitor[i] == TSMonitorLGSolution) {
7490       ierr = TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i],displaynames);CHKERRQ(ierr);
7491       break;
7492     }
7493   }
7494   PetscFunctionReturn(0);
7495 }
7496 
7497 /*@C
7498    TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
7499 
7500    Collective on TS
7501 
7502    Input Parameters:
7503 +  ts - the TS context
7504 .  transform - the transform function
7505 .  destroy - function to destroy the optional context
7506 -  ctx - optional context used by transform function
7507 
7508    Notes: If the TS object does not have a TSMonitorLGCtx associated with it then this function is ignored
7509 
7510    Level: intermediate
7511 
7512 .keywords: TS,  vector, monitor, view
7513 
7514 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGCtxSetTransform()
7515 @*/
7516 PetscErrorCode  TSMonitorLGSetTransform(TS ts,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
7517 {
7518   PetscInt          i;
7519   PetscErrorCode    ierr;
7520 
7521   PetscFunctionBegin;
7522   for (i=0; i<ts->numbermonitors; i++) {
7523     if (ts->monitor[i] == TSMonitorLGSolution) {
7524       ierr = TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i],transform,destroy,tctx);CHKERRQ(ierr);
7525     }
7526   }
7527   PetscFunctionReturn(0);
7528 }
7529 
7530 /*@C
7531    TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
7532 
7533    Collective on TSLGCtx
7534 
7535    Input Parameters:
7536 +  ts - the TS context
7537 .  transform - the transform function
7538 .  destroy - function to destroy the optional context
7539 -  ctx - optional context used by transform function
7540 
7541    Level: intermediate
7542 
7543 .keywords: TS,  vector, monitor, view
7544 
7545 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetVariableNames(), TSMonitorLGSetTransform()
7546 @*/
7547 PetscErrorCode  TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx,PetscErrorCode (*transform)(void*,Vec,Vec*),PetscErrorCode (*destroy)(void*),void *tctx)
7548 {
7549   PetscFunctionBegin;
7550   ctx->transform    = transform;
7551   ctx->transformdestroy = destroy;
7552   ctx->transformctx = tctx;
7553   PetscFunctionReturn(0);
7554 }
7555 
7556 /*@C
7557    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the error
7558        in a time based line graph
7559 
7560    Collective on TS
7561 
7562    Input Parameters:
7563 +  ts - the TS context
7564 .  step - current time-step
7565 .  ptime - current time
7566 .  u - current solution
7567 -  dctx - TSMonitorLGCtx object created with TSMonitorLGCtxCreate()
7568 
7569    Level: intermediate
7570 
7571    Notes: Each process in a parallel run displays its component errors in a separate window
7572 
7573    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
7574 
7575    Options Database Keys:
7576 .  -ts_monitor_lg_error - create a graphical monitor of error history
7577 
7578 .keywords: TS,  vector, monitor, view
7579 
7580 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
7581 @*/
7582 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
7583 {
7584   PetscErrorCode    ierr;
7585   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
7586   const PetscScalar *yy;
7587   Vec               y;
7588 
7589   PetscFunctionBegin;
7590   if (!step) {
7591     PetscDrawAxis axis;
7592     PetscInt      dim;
7593     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7594     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Error");CHKERRQ(ierr);
7595     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
7596     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
7597     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7598   }
7599   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
7600   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
7601   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
7602   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
7603 #if defined(PETSC_USE_COMPLEX)
7604   {
7605     PetscReal *yreal;
7606     PetscInt  i,n;
7607     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
7608     ierr = PetscMalloc1(n,&yreal);CHKERRQ(ierr);
7609     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
7610     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
7611     ierr = PetscFree(yreal);CHKERRQ(ierr);
7612   }
7613 #else
7614   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
7615 #endif
7616   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
7617   ierr = VecDestroy(&y);CHKERRQ(ierr);
7618   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
7619     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7620     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7621   }
7622   PetscFunctionReturn(0);
7623 }
7624 
7625 /*@C
7626    TSMonitorError - Monitors progress of the TS solvers by printing the 2 norm of the error at each timestep
7627 
7628    Collective on TS
7629 
7630    Input Parameters:
7631 +  ts - the TS context
7632 .  step - current time-step
7633 .  ptime - current time
7634 .  u - current solution
7635 -  dctx - unused context
7636 
7637    Level: intermediate
7638 
7639    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
7640 
7641    Options Database Keys:
7642 .  -ts_monitor_error - create a graphical monitor of error history
7643 
7644 .keywords: TS,  vector, monitor, view
7645 
7646 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
7647 @*/
7648 PetscErrorCode  TSMonitorError(TS ts,PetscInt step,PetscReal ptime,Vec u,PetscViewerAndFormat *vf)
7649 {
7650   PetscErrorCode    ierr;
7651   Vec               y;
7652   PetscReal         nrm;
7653   PetscBool         flg;
7654 
7655   PetscFunctionBegin;
7656   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
7657   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
7658   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
7659   ierr = PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERASCII,&flg);CHKERRQ(ierr);
7660   if (flg) {
7661     ierr = VecNorm(y,NORM_2,&nrm);CHKERRQ(ierr);
7662     ierr = PetscViewerASCIIPrintf(vf->viewer,"2-norm of error %g\n",(double)nrm);CHKERRQ(ierr);
7663   }
7664   ierr = PetscObjectTypeCompare((PetscObject)vf->viewer,PETSCVIEWERDRAW,&flg);CHKERRQ(ierr);
7665   if (flg) {
7666     ierr = VecView(y,vf->viewer);CHKERRQ(ierr);
7667   }
7668   ierr = VecDestroy(&y);CHKERRQ(ierr);
7669   PetscFunctionReturn(0);
7670 }
7671 
7672 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
7673 {
7674   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7675   PetscReal      x   = ptime,y;
7676   PetscErrorCode ierr;
7677   PetscInt       its;
7678 
7679   PetscFunctionBegin;
7680   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7681   if (!n) {
7682     PetscDrawAxis axis;
7683     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7684     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
7685     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7686     ctx->snes_its = 0;
7687   }
7688   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
7689   y    = its - ctx->snes_its;
7690   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7691   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7692     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7693     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7694   }
7695   ctx->snes_its = its;
7696   PetscFunctionReturn(0);
7697 }
7698 
7699 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
7700 {
7701   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
7702   PetscReal      x   = ptime,y;
7703   PetscErrorCode ierr;
7704   PetscInt       its;
7705 
7706   PetscFunctionBegin;
7707   if (n < 0) PetscFunctionReturn(0); /* -1 indicates interpolated solution */
7708   if (!n) {
7709     PetscDrawAxis axis;
7710     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
7711     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
7712     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
7713     ctx->ksp_its = 0;
7714   }
7715   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
7716   y    = its - ctx->ksp_its;
7717   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
7718   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
7719     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
7720     ierr = PetscDrawLGSave(ctx->lg);CHKERRQ(ierr);
7721   }
7722   ctx->ksp_its = its;
7723   PetscFunctionReturn(0);
7724 }
7725 
7726 /*@
7727    TSComputeLinearStability - computes the linear stability function at a point
7728 
7729    Collective on TS and Vec
7730 
7731    Input Parameters:
7732 +  ts - the TS context
7733 -  xr,xi - real and imaginary part of input arguments
7734 
7735    Output Parameters:
7736 .  yr,yi - real and imaginary part of function value
7737 
7738    Level: developer
7739 
7740 .keywords: TS, compute
7741 
7742 .seealso: TSSetRHSFunction(), TSComputeIFunction()
7743 @*/
7744 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
7745 {
7746   PetscErrorCode ierr;
7747 
7748   PetscFunctionBegin;
7749   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7750   if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
7751   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
7752   PetscFunctionReturn(0);
7753 }
7754 
7755 /* ------------------------------------------------------------------------*/
7756 /*@C
7757    TSMonitorEnvelopeCtxCreate - Creates a context for use with TSMonitorEnvelope()
7758 
7759    Collective on TS
7760 
7761    Input Parameters:
7762 .  ts  - the ODE solver object
7763 
7764    Output Parameter:
7765 .  ctx - the context
7766 
7767    Level: intermediate
7768 
7769 .keywords: TS, monitor, line graph, residual, seealso
7770 
7771 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
7772 
7773 @*/
7774 PetscErrorCode  TSMonitorEnvelopeCtxCreate(TS ts,TSMonitorEnvelopeCtx *ctx)
7775 {
7776   PetscErrorCode ierr;
7777 
7778   PetscFunctionBegin;
7779   ierr = PetscNew(ctx);CHKERRQ(ierr);
7780   PetscFunctionReturn(0);
7781 }
7782 
7783 /*@C
7784    TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
7785 
7786    Collective on TS
7787 
7788    Input Parameters:
7789 +  ts - the TS context
7790 .  step - current time-step
7791 .  ptime - current time
7792 .  u  - current solution
7793 -  dctx - the envelope context
7794 
7795    Options Database:
7796 .  -ts_monitor_envelope
7797 
7798    Level: intermediate
7799 
7800    Notes: after a solve you can use TSMonitorEnvelopeGetBounds() to access the envelope
7801 
7802 .keywords: TS,  vector, monitor, view
7803 
7804 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorEnvelopeGetBounds(), TSMonitorEnvelopeCtxCreate()
7805 @*/
7806 PetscErrorCode  TSMonitorEnvelope(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dctx)
7807 {
7808   PetscErrorCode       ierr;
7809   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
7810 
7811   PetscFunctionBegin;
7812   if (!ctx->max) {
7813     ierr = VecDuplicate(u,&ctx->max);CHKERRQ(ierr);
7814     ierr = VecDuplicate(u,&ctx->min);CHKERRQ(ierr);
7815     ierr = VecCopy(u,ctx->max);CHKERRQ(ierr);
7816     ierr = VecCopy(u,ctx->min);CHKERRQ(ierr);
7817   } else {
7818     ierr = VecPointwiseMax(ctx->max,u,ctx->max);CHKERRQ(ierr);
7819     ierr = VecPointwiseMin(ctx->min,u,ctx->min);CHKERRQ(ierr);
7820   }
7821   PetscFunctionReturn(0);
7822 }
7823 
7824 /*@C
7825    TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
7826 
7827    Collective on TS
7828 
7829    Input Parameter:
7830 .  ts - the TS context
7831 
7832    Output Parameter:
7833 +  max - the maximum values
7834 -  min - the minimum values
7835 
7836    Notes: If the TS does not have a TSMonitorEnvelopeCtx associated with it then this function is ignored
7837 
7838    Level: intermediate
7839 
7840 .keywords: TS,  vector, monitor, view
7841 
7842 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorLGSetDisplayVariables()
7843 @*/
7844 PetscErrorCode  TSMonitorEnvelopeGetBounds(TS ts,Vec *max,Vec *min)
7845 {
7846   PetscInt i;
7847 
7848   PetscFunctionBegin;
7849   if (max) *max = NULL;
7850   if (min) *min = NULL;
7851   for (i=0; i<ts->numbermonitors; i++) {
7852     if (ts->monitor[i] == TSMonitorEnvelope) {
7853       TSMonitorEnvelopeCtx  ctx = (TSMonitorEnvelopeCtx) ts->monitorcontext[i];
7854       if (max) *max = ctx->max;
7855       if (min) *min = ctx->min;
7856       break;
7857     }
7858   }
7859   PetscFunctionReturn(0);
7860 }
7861 
7862 /*@C
7863    TSMonitorEnvelopeCtxDestroy - Destroys a context that was created  with TSMonitorEnvelopeCtxCreate().
7864 
7865    Collective on TSMonitorEnvelopeCtx
7866 
7867    Input Parameter:
7868 .  ctx - the monitor context
7869 
7870    Level: intermediate
7871 
7872 .keywords: TS, monitor, line graph, destroy
7873 
7874 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep()
7875 @*/
7876 PetscErrorCode  TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
7877 {
7878   PetscErrorCode ierr;
7879 
7880   PetscFunctionBegin;
7881   ierr = VecDestroy(&(*ctx)->min);CHKERRQ(ierr);
7882   ierr = VecDestroy(&(*ctx)->max);CHKERRQ(ierr);
7883   ierr = PetscFree(*ctx);CHKERRQ(ierr);
7884   PetscFunctionReturn(0);
7885 }
7886 
7887 /*@
7888    TSRestartStep - Flags the solver to restart the next step
7889 
7890    Collective on TS
7891 
7892    Input Parameter:
7893 .  ts - the TS context obtained from TSCreate()
7894 
7895    Level: advanced
7896 
7897    Notes:
7898    Multistep methods like BDF or Runge-Kutta methods with FSAL property require restarting the solver in the event of
7899    discontinuities. These discontinuities may be introduced as a consequence of explicitly modifications to the solution
7900    vector (which PETSc attempts to detect and handle) or problem coefficients (which PETSc is not able to detect). For
7901    the sake of correctness and maximum safety, users are expected to call TSRestart() whenever they introduce
7902    discontinuities in callback routines (e.g. prestep and poststep routines, or implicit/rhs function routines with
7903    discontinuous source terms).
7904 
7905 .keywords: TS, timestep, restart
7906 
7907 .seealso: TSSolve(), TSSetPreStep(), TSSetPostStep()
7908 @*/
7909 PetscErrorCode TSRestartStep(TS ts)
7910 {
7911   PetscFunctionBegin;
7912   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
7913   ts->steprestart = PETSC_TRUE;
7914   PetscFunctionReturn(0);
7915 }
7916 
7917 /*@
7918    TSRollBack - Rolls back one time step
7919 
7920    Collective on TS
7921 
7922    Input Parameter:
7923 .  ts - the TS context obtained from TSCreate()
7924 
7925    Level: advanced
7926 
7927 .keywords: TS, timestep, rollback
7928 
7929 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
7930 @*/
7931 PetscErrorCode  TSRollBack(TS ts)
7932 {
7933   PetscErrorCode ierr;
7934 
7935   PetscFunctionBegin;
7936   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7937   if (ts->steprollback) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONGSTATE,"TSRollBack already called");
7938   if (!ts->ops->rollback) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
7939   ierr = (*ts->ops->rollback)(ts);CHKERRQ(ierr);
7940   ts->time_step = ts->ptime - ts->ptime_prev;
7941   ts->ptime = ts->ptime_prev;
7942   ts->ptime_prev = ts->ptime_prev_rollback;
7943   ts->steps--;
7944   ts->steprollback = PETSC_TRUE;
7945   PetscFunctionReturn(0);
7946 }
7947 
7948 /*@
7949    TSGetStages - Get the number of stages and stage values
7950 
7951    Input Parameter:
7952 .  ts - the TS context obtained from TSCreate()
7953 
7954    Level: advanced
7955 
7956 .keywords: TS, getstages
7957 
7958 .seealso: TSCreate()
7959 @*/
7960 PetscErrorCode  TSGetStages(TS ts,PetscInt *ns,Vec **Y)
7961 {
7962   PetscErrorCode ierr;
7963 
7964   PetscFunctionBegin;
7965   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
7966   PetscValidPointer(ns,2);
7967 
7968   if (!ts->ops->getstages) *ns=0;
7969   else {
7970     ierr = (*ts->ops->getstages)(ts,ns,Y);CHKERRQ(ierr);
7971   }
7972   PetscFunctionReturn(0);
7973 }
7974 
7975 /*@C
7976   TSComputeIJacobianDefaultColor - Computes the Jacobian using finite differences and coloring to exploit matrix sparsity.
7977 
7978   Collective on SNES
7979 
7980   Input Parameters:
7981 + ts - the TS context
7982 . t - current timestep
7983 . U - state vector
7984 . Udot - time derivative of state vector
7985 . shift - shift to apply, see note below
7986 - ctx - an optional user context
7987 
7988   Output Parameters:
7989 + J - Jacobian matrix (not altered in this routine)
7990 - B - newly computed Jacobian matrix to use with preconditioner (generally the same as J)
7991 
7992   Level: intermediate
7993 
7994   Notes:
7995   If F(t,U,Udot)=0 is the DAE, the required Jacobian is
7996 
7997   dF/dU + shift*dF/dUdot
7998 
7999   Most users should not need to explicitly call this routine, as it
8000   is used internally within the nonlinear solvers.
8001 
8002   This will first try to get the coloring from the DM.  If the DM type has no coloring
8003   routine, then it will try to get the coloring from the matrix.  This requires that the
8004   matrix have nonzero entries precomputed.
8005 
8006 .keywords: TS, finite differences, Jacobian, coloring, sparse
8007 .seealso: TSSetIJacobian(), MatFDColoringCreate(), MatFDColoringSetFunction()
8008 @*/
8009 PetscErrorCode TSComputeIJacobianDefaultColor(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat J,Mat B,void *ctx)
8010 {
8011   SNES           snes;
8012   MatFDColoring  color;
8013   PetscBool      hascolor, matcolor = PETSC_FALSE;
8014   PetscErrorCode ierr;
8015 
8016   PetscFunctionBegin;
8017   ierr = PetscOptionsGetBool(((PetscObject)ts)->options,((PetscObject) ts)->prefix, "-ts_fd_color_use_mat", &matcolor, NULL);CHKERRQ(ierr);
8018   ierr = PetscObjectQuery((PetscObject) B, "TSMatFDColoring", (PetscObject *) &color);CHKERRQ(ierr);
8019   if (!color) {
8020     DM         dm;
8021     ISColoring iscoloring;
8022 
8023     ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
8024     ierr = DMHasColoring(dm, &hascolor);CHKERRQ(ierr);
8025     if (hascolor && !matcolor) {
8026       ierr = DMCreateColoring(dm, IS_COLORING_GLOBAL, &iscoloring);CHKERRQ(ierr);
8027       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
8028       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
8029       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
8030       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
8031       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
8032     } else {
8033       MatColoring mc;
8034 
8035       ierr = MatColoringCreate(B, &mc);CHKERRQ(ierr);
8036       ierr = MatColoringSetDistance(mc, 2);CHKERRQ(ierr);
8037       ierr = MatColoringSetType(mc, MATCOLORINGSL);CHKERRQ(ierr);
8038       ierr = MatColoringSetFromOptions(mc);CHKERRQ(ierr);
8039       ierr = MatColoringApply(mc, &iscoloring);CHKERRQ(ierr);
8040       ierr = MatColoringDestroy(&mc);CHKERRQ(ierr);
8041       ierr = MatFDColoringCreate(B, iscoloring, &color);CHKERRQ(ierr);
8042       ierr = MatFDColoringSetFunction(color, (PetscErrorCode (*)(void)) SNESTSFormFunction, (void *) ts);CHKERRQ(ierr);
8043       ierr = MatFDColoringSetFromOptions(color);CHKERRQ(ierr);
8044       ierr = MatFDColoringSetUp(B, iscoloring, color);CHKERRQ(ierr);
8045       ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr);
8046     }
8047     ierr = PetscObjectCompose((PetscObject) B, "TSMatFDColoring", (PetscObject) color);CHKERRQ(ierr);
8048     ierr = PetscObjectDereference((PetscObject) color);CHKERRQ(ierr);
8049   }
8050   ierr = TSGetSNES(ts, &snes);CHKERRQ(ierr);
8051   ierr = MatFDColoringApply(B, color, U, snes);CHKERRQ(ierr);
8052   if (J != B) {
8053     ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8054     ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8055   }
8056   PetscFunctionReturn(0);
8057 }
8058 
8059 /*@
8060     TSSetFunctionDomainError - Set the function testing if the current state vector is valid
8061 
8062     Input Parameters:
8063     ts - the TS context
8064     func - function called within TSFunctionDomainError
8065 
8066     Level: intermediate
8067 
8068 .keywords: TS, state, domain
8069 .seealso: TSAdaptCheckStage(), TSFunctionDomainError()
8070 @*/
8071 
8072 PetscErrorCode TSSetFunctionDomainError(TS ts, PetscErrorCode (*func)(TS,PetscReal,Vec,PetscBool*))
8073 {
8074   PetscFunctionBegin;
8075   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
8076   ts->functiondomainerror = func;
8077   PetscFunctionReturn(0);
8078 }
8079 
8080 /*@
8081     TSFunctionDomainError - Check if the current state is valid
8082 
8083     Input Parameters:
8084     ts - the TS context
8085     stagetime - time of the simulation
8086     Y - state vector to check.
8087 
8088     Output Parameter:
8089     accept - Set to PETSC_FALSE if the current state vector is valid.
8090 
8091     Note:
8092     This function should be used to ensure the state is in a valid part of the space.
8093     For example, one can ensure here all values are positive.
8094 
8095     Level: advanced
8096 @*/
8097 PetscErrorCode TSFunctionDomainError(TS ts,PetscReal stagetime,Vec Y,PetscBool* accept)
8098 {
8099   PetscErrorCode ierr;
8100 
8101   PetscFunctionBegin;
8102 
8103   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
8104   *accept = PETSC_TRUE;
8105   if (ts->functiondomainerror) {
8106     PetscStackCallStandard((*ts->functiondomainerror),(ts,stagetime,Y,accept));
8107   }
8108   PetscFunctionReturn(0);
8109 }
8110 
8111 /*@C
8112   TSClone - This function clones a time step object.
8113 
8114   Collective on MPI_Comm
8115 
8116   Input Parameter:
8117 . tsin    - The input TS
8118 
8119   Output Parameter:
8120 . tsout   - The output TS (cloned)
8121 
8122   Notes:
8123   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.
8124 
8125   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);
8126 
8127   Level: developer
8128 
8129 .keywords: TS, clone
8130 .seealso: TSCreate(), TSSetType(), TSSetUp(), TSDestroy(), TSSetProblemType()
8131 @*/
8132 PetscErrorCode  TSClone(TS tsin, TS *tsout)
8133 {
8134   TS             t;
8135   PetscErrorCode ierr;
8136   SNES           snes_start;
8137   DM             dm;
8138   TSType         type;
8139 
8140   PetscFunctionBegin;
8141   PetscValidPointer(tsin,1);
8142   *tsout = NULL;
8143 
8144   ierr = PetscHeaderCreate(t, TS_CLASSID, "TS", "Time stepping", "TS", PetscObjectComm((PetscObject)tsin), TSDestroy, TSView);CHKERRQ(ierr);
8145 
8146   /* General TS description */
8147   t->numbermonitors    = 0;
8148   t->setupcalled       = 0;
8149   t->ksp_its           = 0;
8150   t->snes_its          = 0;
8151   t->nwork             = 0;
8152   t->rhsjacobian.time  = -1e20;
8153   t->rhsjacobian.scale = 1.;
8154   t->ijacobian.shift   = 1.;
8155 
8156   ierr = TSGetSNES(tsin,&snes_start);CHKERRQ(ierr);
8157   ierr = TSSetSNES(t,snes_start);CHKERRQ(ierr);
8158 
8159   ierr = TSGetDM(tsin,&dm);CHKERRQ(ierr);
8160   ierr = TSSetDM(t,dm);CHKERRQ(ierr);
8161 
8162   t->adapt = tsin->adapt;
8163   ierr = PetscObjectReference((PetscObject)t->adapt);CHKERRQ(ierr);
8164 
8165   t->trajectory = tsin->trajectory;
8166   ierr = PetscObjectReference((PetscObject)t->trajectory);CHKERRQ(ierr);
8167 
8168   t->event = tsin->event;
8169   if (t->event) t->event->refct++;
8170 
8171   t->problem_type      = tsin->problem_type;
8172   t->ptime             = tsin->ptime;
8173   t->ptime_prev        = tsin->ptime_prev;
8174   t->time_step         = tsin->time_step;
8175   t->max_time          = tsin->max_time;
8176   t->steps             = tsin->steps;
8177   t->max_steps         = tsin->max_steps;
8178   t->equation_type     = tsin->equation_type;
8179   t->atol              = tsin->atol;
8180   t->rtol              = tsin->rtol;
8181   t->max_snes_failures = tsin->max_snes_failures;
8182   t->max_reject        = tsin->max_reject;
8183   t->errorifstepfailed = tsin->errorifstepfailed;
8184 
8185   ierr = TSGetType(tsin,&type);CHKERRQ(ierr);
8186   ierr = TSSetType(t,type);CHKERRQ(ierr);
8187 
8188   t->vec_sol           = NULL;
8189 
8190   t->cfltime          = tsin->cfltime;
8191   t->cfltime_local    = tsin->cfltime_local;
8192   t->exact_final_time = tsin->exact_final_time;
8193 
8194   ierr = PetscMemcpy(t->ops,tsin->ops,sizeof(struct _TSOps));CHKERRQ(ierr);
8195 
8196   if (((PetscObject)tsin)->fortran_func_pointers) {
8197     PetscInt i;
8198     ierr = PetscMalloc((10)*sizeof(void(*)(void)),&((PetscObject)t)->fortran_func_pointers);CHKERRQ(ierr);
8199     for (i=0; i<10; i++) {
8200       ((PetscObject)t)->fortran_func_pointers[i] = ((PetscObject)tsin)->fortran_func_pointers[i];
8201     }
8202   }
8203   *tsout = t;
8204   PetscFunctionReturn(0);
8205 }
8206 
8207 static PetscErrorCode RHSWrapperFunction_TSRHSJacobianTest(void* ctx,Vec x,Vec y)
8208 {
8209   PetscErrorCode ierr;
8210   TS             ts = (TS) ctx;
8211 
8212   PetscFunctionBegin;
8213   ierr = TSComputeRHSFunction(ts,0,x,y);CHKERRQ(ierr);
8214   PetscFunctionReturn(0);
8215 }
8216 
8217 /*@
8218     TSRHSJacobianTest - Compares the multiply routine provided to the MATSHELL with differencing on the TS given RHS function.
8219 
8220    Logically Collective on TS and Mat
8221 
8222     Input Parameters:
8223     TS - the time stepping routine
8224 
8225    Output Parameter:
8226 .   flg - PETSC_TRUE if the multiply is likely correct
8227 
8228    Options Database:
8229  .   -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view - run the test at each timestep of the integrator
8230 
8231    Level: advanced
8232 
8233    Notes: This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
8234 
8235 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellTestMultTranspose(), TSRHSJacobianTestTranspose()
8236 @*/
8237 PetscErrorCode  TSRHSJacobianTest(TS ts,PetscBool *flg)
8238 {
8239   Mat            J,B;
8240   PetscErrorCode ierr;
8241   TSRHSJacobian  func;
8242   void*          ctx;
8243 
8244   PetscFunctionBegin;
8245   ierr = TSGetRHSJacobian(ts,&J,&B,&func,&ctx);CHKERRQ(ierr);
8246   ierr = (*func)(ts,0.0,ts->vec_sol,J,B,ctx);CHKERRQ(ierr);
8247   ierr = MatShellTestMult(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg);CHKERRQ(ierr);
8248   PetscFunctionReturn(0);
8249 }
8250 
8251 /*@C
8252     TSRHSJacobianTestTranspose - Compares the multiply transpose routine provided to the MATSHELL with differencing on the TS given RHS function.
8253 
8254    Logically Collective on TS and Mat
8255 
8256     Input Parameters:
8257     TS - the time stepping routine
8258 
8259    Output Parameter:
8260 .   flg - PETSC_TRUE if the multiply is likely correct
8261 
8262    Options Database:
8263 .   -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view - run the test at each timestep of the integrator
8264 
8265    Notes: This only works for problems defined only the RHS function and Jacobian NOT IFunction and IJacobian
8266 
8267    Level: advanced
8268 
8269 .seealso: MatCreateShell(), MatShellGetContext(), MatShellGetOperation(), MatShellTestMultTranspose(), TSRHSJacobianTest()
8270 @*/
8271 PetscErrorCode  TSRHSJacobianTestTranspose(TS ts,PetscBool *flg)
8272 {
8273   Mat            J,B;
8274   PetscErrorCode ierr;
8275   void           *ctx;
8276   TSRHSJacobian  func;
8277 
8278   PetscFunctionBegin;
8279   ierr = TSGetRHSJacobian(ts,&J,&B,&func,&ctx);CHKERRQ(ierr);
8280   ierr = (*func)(ts,0.0,ts->vec_sol,J,B,ctx);CHKERRQ(ierr);
8281   ierr = MatShellTestMultTranspose(J,RHSWrapperFunction_TSRHSJacobianTest,ts->vec_sol,ts,flg);CHKERRQ(ierr);
8282   PetscFunctionReturn(0);
8283 }
8284