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