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