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