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