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