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