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