xref: /petsc/src/ts/interface/ts.c (revision 55849f575624b3890dfd9b38e2c3ba42c5d7d18f)
1 
2 #include <petsc-private/tsimpl.h>        /*I "petscts.h"  I*/
3 #include <petscdmshell.h>
4 
5 /* Logging support */
6 PetscClassId  TS_CLASSID;
7 PetscLogEvent  TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "TSSetTypeFromOptions"
11 /*
12   TSSetTypeFromOptions - Sets the type of ts from user options.
13 
14   Collective on TS
15 
16   Input Parameter:
17 . ts - The ts
18 
19   Level: intermediate
20 
21 .keywords: TS, set, options, database, type
22 .seealso: TSSetFromOptions(), TSSetType()
23 */
24 static PetscErrorCode TSSetTypeFromOptions(TS ts)
25 {
26   PetscBool      opt;
27   const char     *defaultType;
28   char           typeName[256];
29   PetscErrorCode ierr;
30 
31   PetscFunctionBegin;
32   if (((PetscObject)ts)->type_name) {
33     defaultType = ((PetscObject)ts)->type_name;
34   } else {
35     defaultType = TSEULER;
36   }
37 
38   if (!TSRegisterAllCalled) {ierr = TSRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
39   ierr = PetscOptionsList("-ts_type", "TS method"," TSSetType", TSList, defaultType, typeName, 256, &opt);CHKERRQ(ierr);
40   if (opt) {
41     ierr = TSSetType(ts, typeName);CHKERRQ(ierr);
42   } else {
43     ierr = TSSetType(ts, defaultType);CHKERRQ(ierr);
44   }
45   PetscFunctionReturn(0);
46 }
47 
48 #undef __FUNCT__
49 #define __FUNCT__ "TSSetFromOptions"
50 /*@
51    TSSetFromOptions - Sets various TS parameters from user options.
52 
53    Collective on TS
54 
55    Input Parameter:
56 .  ts - the TS context obtained from TSCreate()
57 
58    Options Database Keys:
59 +  -ts_type <type> - TSEULER, TSBEULER, TSSUNDIALS, TSPSEUDO, TSCN, TSRK, TSTHETA, TSGL, TSSSP
60 .  -ts_max_steps maxsteps - maximum number of time-steps to take
61 .  -ts_final_time time - maximum time to compute to
62 .  -ts_dt dt - initial time step
63 .  -ts_monitor - print information at each timestep
64 .  -ts_monitor_lg_timestep - Monitor timestep size graphically
65 .  -ts_monitor_lg_solution - Monitor solution graphically
66 .  -ts_monitor_lg_error - Monitor error graphically
67 .  -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically
68 .  -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically
69 .  -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically
70 .  -ts_monitor_draw_solution - Monitor solution graphically
71 .  -ts_monitor_draw_solution - Monitor solution graphically
72 .  -ts_monitor_draw_error - Monitor error graphically
73 .  -ts_monitor_draw_solution_binary <filename> - Save each solution to a binary file
74 -  -ts_monitor_draw_solution_vtk <filename.vts> - Save each time step to a binary file, use filename-%%03D.vts
75 
76    Level: beginner
77 
78 .keywords: TS, timestep, set, options, database
79 
80 .seealso: TSGetType()
81 @*/
82 PetscErrorCode  TSSetFromOptions(TS ts)
83 {
84   PetscBool      opt,flg;
85   PetscErrorCode ierr;
86   PetscViewer    monviewer;
87   char           monfilename[PETSC_MAX_PATH_LEN];
88   SNES           snes;
89   TSAdapt        adapt;
90   PetscReal      time_step;
91 
92   PetscFunctionBegin;
93   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
94   ierr = PetscObjectOptionsBegin((PetscObject)ts);CHKERRQ(ierr);
95     /* Handle TS type options */
96     ierr = TSSetTypeFromOptions(ts);CHKERRQ(ierr);
97 
98     /* Handle generic TS options */
99     ierr = PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetDuration",ts->max_steps,&ts->max_steps,PETSC_NULL);CHKERRQ(ierr);
100     ierr = PetscOptionsReal("-ts_final_time","Time to run to","TSSetDuration",ts->max_time,&ts->max_time,PETSC_NULL);CHKERRQ(ierr);
101     ierr = PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,PETSC_NULL);CHKERRQ(ierr);
102     ierr = PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&time_step,&flg);CHKERRQ(ierr);
103     if (flg) {
104       ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr);
105     }
106     opt = ts->exact_final_time == PETSC_DECIDE ? PETSC_FALSE : (PetscBool)ts->exact_final_time;
107     ierr = PetscOptionsBool("-ts_exact_final_time","Interpolate output to stop exactly at the final time","TSSetExactFinalTime",opt,&opt,&flg);CHKERRQ(ierr);
108     if (flg) {ierr = TSSetExactFinalTime(ts,opt);CHKERRQ(ierr);}
109     ierr = PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","TSSetMaxSNESFailures",ts->max_snes_failures,&ts->max_snes_failures,PETSC_NULL);CHKERRQ(ierr);
110     ierr = PetscOptionsInt("-ts_max_reject","Maximum number of step rejections before step fails","TSSetMaxStepRejections",ts->max_reject,&ts->max_reject,PETSC_NULL);CHKERRQ(ierr);
111     ierr = PetscOptionsBool("-ts_error_if_step_fails","Error if no step succeeds","TSSetErrorIfStepFails",ts->errorifstepfailed,&ts->errorifstepfailed,PETSC_NULL);CHKERRQ(ierr);
112     ierr = PetscOptionsReal("-ts_rtol","Relative tolerance for local truncation error","TSSetTolerances",ts->rtol,&ts->rtol,PETSC_NULL);CHKERRQ(ierr);
113     ierr = PetscOptionsReal("-ts_atol","Absolute tolerance for local truncation error","TSSetTolerances",ts->atol,&ts->atol,PETSC_NULL);CHKERRQ(ierr);
114 
115     /* Monitor options */
116     ierr = PetscOptionsString("-ts_monitor","Monitor timestep size","TSMonitorDefault","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
117     if (flg) {
118       ierr = PetscViewerASCIIOpen(((PetscObject)ts)->comm,monfilename,&monviewer);CHKERRQ(ierr);
119       ierr = TSMonitorSet(ts,TSMonitorDefault,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr);
120     }
121     ierr = PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
122     if (flg) {ierr = PetscPythonMonitorSet((PetscObject)ts,monfilename);CHKERRQ(ierr);}
123 
124     ierr = PetscOptionsName("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",&opt);CHKERRQ(ierr);
125     if (opt) {
126       TSMonitorLGCtx ctx;
127       PetscInt       howoften = 1;
128 
129       ierr = PetscOptionsInt("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,PETSC_NULL);CHKERRQ(ierr);
130       ierr = TSMonitorLGCtxCreate(((PetscObject)ts)->comm,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);CHKERRQ(ierr);
131       ierr = TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
132     }
133     ierr = PetscOptionsName("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",&opt);CHKERRQ(ierr);
134     if (opt) {
135       TSMonitorLGCtx ctx;
136       PetscInt       howoften = 1;
137 
138       ierr = PetscOptionsInt("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",howoften,&howoften,PETSC_NULL);CHKERRQ(ierr);
139       ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
140       ierr = TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
141     }
142     ierr = PetscOptionsName("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",&opt);CHKERRQ(ierr);
143     if (opt) {
144       TSMonitorLGCtx ctx;
145       PetscInt       howoften = 1;
146 
147       ierr = PetscOptionsInt("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",howoften,&howoften,PETSC_NULL);CHKERRQ(ierr);
148       ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
149       ierr = TSMonitorSet(ts,TSMonitorLGError,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
150     }
151     ierr = PetscOptionsName("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",&opt);CHKERRQ(ierr);
152     if (opt) {
153       TSMonitorLGCtx ctx;
154       PetscInt       howoften = 1;
155 
156       ierr = PetscOptionsInt("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",howoften,&howoften,PETSC_NULL);CHKERRQ(ierr);
157       ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);
158       ierr = TSMonitorSet(ts,TSMonitorLGSNESIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
159     }
160     ierr = PetscOptionsName("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",&opt);CHKERRQ(ierr);
161     if (opt) {
162       TSMonitorLGCtx ctx;
163       PetscInt       howoften = 1;
164 
165       ierr = PetscOptionsInt("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",howoften,&howoften,PETSC_NULL);CHKERRQ(ierr);
166       ierr = TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);
167       ierr = TSMonitorSet(ts,TSMonitorLGKSPIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);CHKERRQ(ierr);
168     }
169     ierr = PetscOptionsName("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",&opt);CHKERRQ(ierr);
170     if (opt) {
171       TSMonitorSPEigCtx ctx;
172       PetscInt          howoften = 1;
173 
174       ierr = PetscOptionsInt("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",howoften,&howoften,PETSC_NULL);CHKERRQ(ierr);
175       ierr = TSMonitorSPEigCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
176       ierr = TSMonitorSet(ts,TSMonitorSPEig,ctx,(PetscErrorCode (*)(void**))TSMonitorSPEigCtxDestroy);CHKERRQ(ierr);
177     }
178     opt  = PETSC_FALSE;
179     ierr = PetscOptionsName("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",&opt);CHKERRQ(ierr);
180     if (opt) {
181       TSMonitorDrawCtx ctx;
182       PetscInt         howoften = 1;
183 
184       ierr = PetscOptionsInt("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",howoften,&howoften,PETSC_NULL);CHKERRQ(ierr);
185       ierr = TSMonitorDrawCtxCreate(((PetscObject)ts)->comm,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
186       ierr = TSMonitorSet(ts,TSMonitorDrawSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
187     }
188     opt  = PETSC_FALSE;
189     ierr = PetscOptionsName("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",&opt);CHKERRQ(ierr);
190     if (opt) {
191       TSMonitorDrawCtx ctx;
192       PetscInt         howoften = 1;
193 
194       ierr = PetscOptionsInt("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",howoften,&howoften,PETSC_NULL);CHKERRQ(ierr);
195       ierr = TSMonitorDrawCtxCreate(((PetscObject)ts)->comm,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
196       ierr = TSMonitorSet(ts,TSMonitorDrawError,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);CHKERRQ(ierr);
197     }
198     opt  = PETSC_FALSE;
199     ierr = PetscOptionsString("-ts_monitor_draw_solution_binary","Save each solution to a binary file","TSMonitorSolutionBinary",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
200     if (flg) {
201       PetscViewer ctx;
202       if (monfilename[0]) {
203         ierr = PetscViewerBinaryOpen(((PetscObject)ts)->comm,monfilename,FILE_MODE_WRITE,&ctx);CHKERRQ(ierr);
204       } else {
205         ctx = PETSC_VIEWER_BINARY_(((PetscObject)ts)->comm);
206       }
207       ierr = TSMonitorSet(ts,TSMonitorSolutionBinary,ctx,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr);
208     }
209     opt  = PETSC_FALSE;
210     ierr = PetscOptionsString("-ts_monitor_draw_solution_vtk","Save each time step to a binary file, use filename-%%03D.vts","TSMonitorSolutionVTK",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
211     if (flg) {
212       const char *ptr,*ptr2;
213       char *filetemplate;
214       if (!monfilename[0]) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"-ts_monitor_draw_solution_vtk requires a file template, e.g. filename-%%03D.vts");
215       /* Do some cursory validation of the input. */
216       ierr = PetscStrstr(monfilename,"%",(char**)&ptr);CHKERRQ(ierr);
217       if (!ptr) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"-ts_monitor_draw_solution_vtk requires a file template, e.g. filename-%%03D.vts");
218       for (ptr++ ; ptr && *ptr; ptr++) {
219         ierr = PetscStrchr("DdiouxX",*ptr,(char**)&ptr2);CHKERRQ(ierr);
220         if (!ptr2 && (*ptr < '0' || '9' < *ptr)) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"Invalid file template argument to -ts_monitor_draw_solution_vtk, should look like filename-%%03D.vts");
221         if (ptr2) break;
222       }
223       ierr = PetscStrallocpy(monfilename,&filetemplate);CHKERRQ(ierr);
224       ierr = TSMonitorSet(ts,TSMonitorSolutionVTK,filetemplate,(PetscErrorCode (*)(void**))TSMonitorSolutionVTKDestroy);CHKERRQ(ierr);
225     }
226 
227     ierr = TSGetAdapt(ts,&adapt);CHKERRQ(ierr);
228     ierr = TSAdaptSetFromOptions(adapt);CHKERRQ(ierr);
229 
230     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
231     if (ts->problem_type == TS_LINEAR) {ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);}
232 
233     /* Handle specific TS options */
234     if (ts->ops->setfromoptions) {
235       ierr = (*ts->ops->setfromoptions)(ts);CHKERRQ(ierr);
236     }
237 
238     /* process any options handlers added with PetscObjectAddOptionsHandler() */
239     ierr = PetscObjectProcessOptionsHandlers((PetscObject)ts);CHKERRQ(ierr);
240   ierr = PetscOptionsEnd();CHKERRQ(ierr);
241   PetscFunctionReturn(0);
242 }
243 
244 #undef __FUNCT__
245 #undef __FUNCT__
246 #define __FUNCT__ "TSComputeRHSJacobian"
247 /*@
248    TSComputeRHSJacobian - Computes the Jacobian matrix that has been
249       set with TSSetRHSJacobian().
250 
251    Collective on TS and Vec
252 
253    Input Parameters:
254 +  ts - the TS context
255 .  t - current timestep
256 -  U - input vector
257 
258    Output Parameters:
259 +  A - Jacobian matrix
260 .  B - optional preconditioning matrix
261 -  flag - flag indicating matrix structure
262 
263    Notes:
264    Most users should not need to explicitly call this routine, as it
265    is used internally within the nonlinear solvers.
266 
267    See KSPSetOperators() for important information about setting the
268    flag parameter.
269 
270    Level: developer
271 
272 .keywords: SNES, compute, Jacobian, matrix
273 
274 .seealso:  TSSetRHSJacobian(), KSPSetOperators()
275 @*/
276 PetscErrorCode  TSComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat *A,Mat *B,MatStructure *flg)
277 {
278   PetscErrorCode ierr;
279   PetscInt       Ustate;
280   DM             dm;
281   TSDM           tsdm;
282   TSRHSJacobian  rhsjacobianfunc;
283   void           *ctx;
284   TSIJacobian    ijacobianfunc;
285 
286   PetscFunctionBegin;
287   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
288   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
289   PetscCheckSameComm(ts,1,U,3);
290   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
291   ierr = DMTSGetContext(dm,&tsdm);CHKERRQ(ierr);
292   ierr = DMTSGetRHSJacobian(dm,&rhsjacobianfunc,&ctx);CHKERRQ(ierr);
293   ierr = DMTSGetIJacobian(dm,&ijacobianfunc,PETSC_NULL);CHKERRQ(ierr);
294   ierr = PetscObjectStateQuery((PetscObject)U,&Ustate);CHKERRQ(ierr);
295   if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.X == U && ts->rhsjacobian.Xstate == Ustate))) {
296     *flg = ts->rhsjacobian.mstructure;
297     PetscFunctionReturn(0);
298   }
299 
300   if (!rhsjacobianfunc && !ijacobianfunc) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
301 
302   if (rhsjacobianfunc) {
303     ierr = PetscLogEventBegin(TS_JacobianEval,ts,U,*A,*B);CHKERRQ(ierr);
304     *flg = DIFFERENT_NONZERO_PATTERN;
305     PetscStackPush("TS user Jacobian function");
306     ierr = (*rhsjacobianfunc)(ts,t,U,A,B,flg,ctx);CHKERRQ(ierr);
307     PetscStackPop;
308     ierr = PetscLogEventEnd(TS_JacobianEval,ts,U,*A,*B);CHKERRQ(ierr);
309     /* make sure user returned a correct Jacobian and preconditioner */
310     PetscValidHeaderSpecific(*A,MAT_CLASSID,4);
311     PetscValidHeaderSpecific(*B,MAT_CLASSID,5);
312   } else {
313     ierr = MatZeroEntries(*A);CHKERRQ(ierr);
314     if (*A != *B) {ierr = MatZeroEntries(*B);CHKERRQ(ierr);}
315     *flg = SAME_NONZERO_PATTERN;
316   }
317   ts->rhsjacobian.time = t;
318   ts->rhsjacobian.X = U;
319   ierr = PetscObjectStateQuery((PetscObject)U,&ts->rhsjacobian.Xstate);CHKERRQ(ierr);
320   ts->rhsjacobian.mstructure = *flg;
321   PetscFunctionReturn(0);
322 }
323 
324 #undef __FUNCT__
325 #define __FUNCT__ "TSComputeRHSFunction"
326 /*@
327    TSComputeRHSFunction - Evaluates the right-hand-side function.
328 
329    Collective on TS and Vec
330 
331    Input Parameters:
332 +  ts - the TS context
333 .  t - current time
334 -  U - state vector
335 
336    Output Parameter:
337 .  y - right hand side
338 
339    Note:
340    Most users should not need to explicitly call this routine, as it
341    is used internally within the nonlinear solvers.
342 
343    Level: developer
344 
345 .keywords: TS, compute
346 
347 .seealso: TSSetRHSFunction(), TSComputeIFunction()
348 @*/
349 PetscErrorCode TSComputeRHSFunction(TS ts,PetscReal t,Vec U,Vec y)
350 {
351   PetscErrorCode ierr;
352   TSRHSFunction  rhsfunction;
353   TSIFunction    ifunction;
354   void           *ctx;
355   DM             dm;
356 
357   PetscFunctionBegin;
358   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
359   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
360   PetscValidHeaderSpecific(y,VEC_CLASSID,4);
361   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
362   ierr = DMTSGetRHSFunction(dm,&rhsfunction,&ctx);CHKERRQ(ierr);
363   ierr = DMTSGetIFunction(dm,&ifunction,PETSC_NULL);CHKERRQ(ierr);
364 
365   if (!rhsfunction && !ifunction) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
366 
367   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,y,0);CHKERRQ(ierr);
368   if (rhsfunction) {
369     PetscStackPush("TS user right-hand-side function");
370     ierr = (*rhsfunction)(ts,t,U,y,ctx);CHKERRQ(ierr);
371     PetscStackPop;
372   } else {
373     ierr = VecZeroEntries(y);CHKERRQ(ierr);
374   }
375 
376   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,y,0);CHKERRQ(ierr);
377   PetscFunctionReturn(0);
378 }
379 
380 #undef __FUNCT__
381 #define __FUNCT__ "TSComputeSolutionFunction"
382 /*@
383    TSComputeSolutionFunction - Evaluates the solution function.
384 
385    Collective on TS and Vec
386 
387    Input Parameters:
388 +  ts - the TS context
389 -  t - current time
390 
391    Output Parameter:
392 .  U - the solution
393 
394    Note:
395    Most users should not need to explicitly call this routine, as it
396    is used internally within the nonlinear solvers.
397 
398    Level: developer
399 
400 .keywords: TS, compute
401 
402 .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction()
403 @*/
404 PetscErrorCode TSComputeSolutionFunction(TS ts,PetscReal t,Vec U)
405 {
406   PetscErrorCode     ierr;
407   TSSolutionFunction solutionfunction;
408   void               *ctx;
409   DM                 dm;
410 
411   PetscFunctionBegin;
412   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
413   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
414   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
415   ierr = DMTSGetSolutionFunction(dm,&solutionfunction,&ctx);CHKERRQ(ierr);
416 
417   if (solutionfunction) {
418     PetscStackPush("TS user right-hand-side function");
419     ierr = (*solutionfunction)(ts,t,U,ctx);CHKERRQ(ierr);
420     PetscStackPop;
421   }
422   PetscFunctionReturn(0);
423 }
424 
425 #undef __FUNCT__
426 #define __FUNCT__ "TSGetRHSVec_Private"
427 static PetscErrorCode TSGetRHSVec_Private(TS ts,Vec *Frhs)
428 {
429   Vec            F;
430   PetscErrorCode ierr;
431 
432   PetscFunctionBegin;
433   *Frhs = PETSC_NULL;
434   ierr = TSGetIFunction(ts,&F,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
435   if (!ts->Frhs) {
436     ierr = VecDuplicate(F,&ts->Frhs);CHKERRQ(ierr);
437   }
438   *Frhs = ts->Frhs;
439   PetscFunctionReturn(0);
440 }
441 
442 #undef __FUNCT__
443 #define __FUNCT__ "TSGetRHSMats_Private"
444 static PetscErrorCode TSGetRHSMats_Private(TS ts,Mat *Arhs,Mat *Brhs)
445 {
446   Mat            A,B;
447   PetscErrorCode ierr;
448 
449   PetscFunctionBegin;
450   ierr = TSGetIJacobian(ts,&A,&B,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
451   if (Arhs) {
452     if (!ts->Arhs) {
453       ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&ts->Arhs);CHKERRQ(ierr);
454     }
455     *Arhs = ts->Arhs;
456   }
457   if (Brhs) {
458     if (!ts->Brhs) {
459       ierr = MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&ts->Brhs);CHKERRQ(ierr);
460     }
461     *Brhs = ts->Brhs;
462   }
463   PetscFunctionReturn(0);
464 }
465 
466 #undef __FUNCT__
467 #define __FUNCT__ "TSComputeIFunction"
468 /*@
469    TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,U,Udot)=0
470 
471    Collective on TS and Vec
472 
473    Input Parameters:
474 +  ts - the TS context
475 .  t - current time
476 .  U - state vector
477 .  Udot - time derivative of state vector
478 -  imex - flag indicates if the method is IMEX so that the RHSFunction should be kept separate
479 
480    Output Parameter:
481 .  Y - right hand side
482 
483    Note:
484    Most users should not need to explicitly call this routine, as it
485    is used internally within the nonlinear solvers.
486 
487    If the user did did not write their equations in implicit form, this
488    function recasts them in implicit form.
489 
490    Level: developer
491 
492 .keywords: TS, compute
493 
494 .seealso: TSSetIFunction(), TSComputeRHSFunction()
495 @*/
496 PetscErrorCode TSComputeIFunction(TS ts,PetscReal t,Vec U,Vec Udot,Vec Y,PetscBool imex)
497 {
498   PetscErrorCode ierr;
499   TSIFunction    ifunction;
500   TSRHSFunction  rhsfunction;
501   void           *ctx;
502   DM             dm;
503 
504   PetscFunctionBegin;
505   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
506   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
507   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
508   PetscValidHeaderSpecific(Y,VEC_CLASSID,5);
509 
510   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
511   ierr = DMTSGetIFunction(dm,&ifunction,&ctx);CHKERRQ(ierr);
512   ierr = DMTSGetRHSFunction(dm,&rhsfunction,PETSC_NULL);CHKERRQ(ierr);
513 
514   if (!rhsfunction && !ifunction) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
515 
516   ierr = PetscLogEventBegin(TS_FunctionEval,ts,U,Udot,Y);CHKERRQ(ierr);
517   if (ifunction) {
518     PetscStackPush("TS user implicit function");
519     ierr = (*ifunction)(ts,t,U,Udot,Y,ctx);CHKERRQ(ierr);
520     PetscStackPop;
521   }
522   if (imex) {
523     if (!ifunction) {
524       ierr = VecCopy(Udot,Y);CHKERRQ(ierr);
525     }
526   } else if (rhsfunction) {
527     if (ifunction) {
528       Vec Frhs;
529       ierr = TSGetRHSVec_Private(ts,&Frhs);CHKERRQ(ierr);
530       ierr = TSComputeRHSFunction(ts,t,U,Frhs);CHKERRQ(ierr);
531       ierr = VecAXPY(Y,-1,Frhs);CHKERRQ(ierr);
532     } else {
533       ierr = TSComputeRHSFunction(ts,t,U,Y);CHKERRQ(ierr);
534       ierr = VecAYPX(Y,-1,Udot);CHKERRQ(ierr);
535     }
536   }
537   ierr = PetscLogEventEnd(TS_FunctionEval,ts,U,Udot,Y);CHKERRQ(ierr);
538   PetscFunctionReturn(0);
539 }
540 
541 #undef __FUNCT__
542 #define __FUNCT__ "TSComputeIJacobian"
543 /*@
544    TSComputeIJacobian - Evaluates the Jacobian of the DAE
545 
546    Collective on TS and Vec
547 
548    Input
549       Input Parameters:
550 +  ts - the TS context
551 .  t - current timestep
552 .  U - state vector
553 .  Udot - time derivative of state vector
554 .  shift - shift to apply, see note below
555 -  imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate
556 
557    Output Parameters:
558 +  A - Jacobian matrix
559 .  B - optional preconditioning matrix
560 -  flag - flag indicating matrix structure
561 
562    Notes:
563    If F(t,U,Udot)=0 is the DAE, the required Jacobian is
564 
565    dF/dU + shift*dF/dUdot
566 
567    Most users should not need to explicitly call this routine, as it
568    is used internally within the nonlinear solvers.
569 
570    Level: developer
571 
572 .keywords: TS, compute, Jacobian, matrix
573 
574 .seealso:  TSSetIJacobian()
575 @*/
576 PetscErrorCode TSComputeIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat *A,Mat *B,MatStructure *flg,PetscBool imex)
577 {
578   PetscInt       Ustate, Udotstate;
579   PetscErrorCode ierr;
580   TSIJacobian    ijacobian;
581   TSRHSJacobian  rhsjacobian;
582   DM             dm;
583   void           *ctx;
584 
585   PetscFunctionBegin;
586 
587   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
588   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
589   PetscValidHeaderSpecific(Udot,VEC_CLASSID,4);
590   PetscValidPointer(A,6);
591   PetscValidHeaderSpecific(*A,MAT_CLASSID,6);
592   PetscValidPointer(B,7);
593   PetscValidHeaderSpecific(*B,MAT_CLASSID,7);
594   PetscValidPointer(flg,8);
595 
596   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
597   ierr = DMTSGetIJacobian(dm,&ijacobian,&ctx);CHKERRQ(ierr);
598   ierr = DMTSGetRHSJacobian(dm,&rhsjacobian,PETSC_NULL);CHKERRQ(ierr);
599 
600   ierr = PetscObjectStateQuery((PetscObject)U,&Ustate);CHKERRQ(ierr);
601   ierr = PetscObjectStateQuery((PetscObject)Udot,&Udotstate);CHKERRQ(ierr);
602   if (ts->ijacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->ijacobian.X == U && ts->ijacobian.Xstate == Ustate && ts->ijacobian.Xdot == Udot && ts->ijacobian.Xdotstate == Udotstate && ts->ijacobian.imex == imex))) {
603     *flg = ts->ijacobian.mstructure;
604     ierr = MatScale(*A, shift / ts->ijacobian.shift);CHKERRQ(ierr);
605     PetscFunctionReturn(0);
606   }
607 
608   if (!rhsjacobian && !ijacobian) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
609 
610   *flg = SAME_NONZERO_PATTERN;  /* In case we're solving a linear problem in which case it wouldn't get initialized below. */
611   ierr = PetscLogEventBegin(TS_JacobianEval,ts,U,*A,*B);CHKERRQ(ierr);
612   if (ijacobian) {
613     *flg = DIFFERENT_NONZERO_PATTERN;
614     PetscStackPush("TS user implicit Jacobian");
615     ierr = (*ijacobian)(ts,t,U,Udot,shift,A,B,flg,ctx);CHKERRQ(ierr);
616     PetscStackPop;
617     /* make sure user returned a correct Jacobian and preconditioner */
618     PetscValidHeaderSpecific(*A,MAT_CLASSID,4);
619     PetscValidHeaderSpecific(*B,MAT_CLASSID,5);
620   }
621   if (imex) {
622     if (!ijacobian) {  /* system was written as Udot = G(t,U) */
623       ierr = MatZeroEntries(*A);CHKERRQ(ierr);
624       ierr = MatShift(*A,shift);CHKERRQ(ierr);
625       if (*A != *B) {
626         ierr = MatZeroEntries(*B);CHKERRQ(ierr);
627         ierr = MatShift(*B,shift);CHKERRQ(ierr);
628       }
629       *flg = SAME_PRECONDITIONER;
630     }
631   } else {
632     if (!ijacobian) {
633       ierr = TSComputeRHSJacobian(ts,t,U,A,B,flg);CHKERRQ(ierr);
634       ierr = MatScale(*A,-1);CHKERRQ(ierr);
635       ierr = MatShift(*A,shift);CHKERRQ(ierr);
636       if (*A != *B) {
637         ierr = MatScale(*B,-1);CHKERRQ(ierr);
638         ierr = MatShift(*B,shift);CHKERRQ(ierr);
639       }
640     } else if (rhsjacobian) {
641       Mat Arhs,Brhs;
642       MatStructure axpy,flg2 = DIFFERENT_NONZERO_PATTERN;
643       ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
644       ierr = TSComputeRHSJacobian(ts,t,U,&Arhs,&Brhs,&flg2);CHKERRQ(ierr);
645       axpy = (*flg == flg2) ? SAME_NONZERO_PATTERN : DIFFERENT_NONZERO_PATTERN;
646       ierr = MatAXPY(*A,-1,Arhs,axpy);CHKERRQ(ierr);
647       if (*A != *B) {
648         ierr = MatAXPY(*B,-1,Brhs,axpy);CHKERRQ(ierr);
649       }
650       *flg = PetscMin(*flg,flg2);
651     }
652   }
653 
654   ts->ijacobian.time = t;
655   ts->ijacobian.X = U;
656   ts->ijacobian.Xdot = Udot;
657   ierr = PetscObjectStateQuery((PetscObject)U,&ts->ijacobian.Xstate);CHKERRQ(ierr);
658   ierr = PetscObjectStateQuery((PetscObject)Udot,&ts->ijacobian.Xdotstate);CHKERRQ(ierr);
659   ts->ijacobian.shift = shift;
660   ts->ijacobian.imex = imex;
661   ts->ijacobian.mstructure = *flg;
662   ierr = PetscLogEventEnd(TS_JacobianEval,ts,U,*A,*B);CHKERRQ(ierr);
663   PetscFunctionReturn(0);
664 }
665 
666 #undef __FUNCT__
667 #define __FUNCT__ "TSSetRHSFunction"
668 /*@C
669     TSSetRHSFunction - Sets the routine for evaluating the function,
670     where U_t = G(t,u).
671 
672     Logically Collective on TS
673 
674     Input Parameters:
675 +   ts - the TS context obtained from TSCreate()
676 .   r - vector to put the computed right hand side (or PETSC_NULL to have it created)
677 .   f - routine for evaluating the right-hand-side function
678 -   ctx - [optional] user-defined context for private data for the
679           function evaluation routine (may be PETSC_NULL)
680 
681     Calling sequence of func:
682 $     func (TS ts,PetscReal t,Vec u,Vec F,void *ctx);
683 
684 +   t - current timestep
685 .   u - input vector
686 .   F - function vector
687 -   ctx - [optional] user-defined function context
688 
689     Level: beginner
690 
691 .keywords: TS, timestep, set, right-hand-side, function
692 
693 .seealso: TSSetRHSJacobian(), TSSetIJacobian()
694 @*/
695 PetscErrorCode  TSSetRHSFunction(TS ts,Vec r,PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*),void *ctx)
696 {
697   PetscErrorCode ierr;
698   SNES           snes;
699   Vec            ralloc = PETSC_NULL;
700   DM             dm;
701 
702   PetscFunctionBegin;
703   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
704   if (r) PetscValidHeaderSpecific(r,VEC_CLASSID,2);
705 
706   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
707   ierr = DMTSSetRHSFunction(dm,f,ctx);CHKERRQ(ierr);
708   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
709   if (!r && !ts->dm && ts->vec_sol) {
710     ierr = VecDuplicate(ts->vec_sol,&ralloc);CHKERRQ(ierr);
711     r = ralloc;
712   }
713   ierr = SNESSetFunction(snes,r,SNESTSFormFunction,ts);CHKERRQ(ierr);
714   ierr = VecDestroy(&ralloc);CHKERRQ(ierr);
715   PetscFunctionReturn(0);
716 }
717 
718 #undef __FUNCT__
719 #define __FUNCT__ "TSSetSolutionFunction"
720 /*@C
721     TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE
722 
723     Logically Collective on TS
724 
725     Input Parameters:
726 +   ts - the TS context obtained from TSCreate()
727 .   f - routine for evaluating the solution
728 -   ctx - [optional] user-defined context for private data for the
729           function evaluation routine (may be PETSC_NULL)
730 
731     Calling sequence of func:
732 $     func (TS ts,PetscReal t,Vec u,void *ctx);
733 
734 +   t - current timestep
735 .   u - output vector
736 -   ctx - [optional] user-defined function context
737 
738     Notes:
739     This routine is used for testing accuracy of time integration schemes when you already know the solution.
740     If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to
741     create closed-form solutions with non-physical forcing terms.
742 
743     For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history.
744 
745     Level: beginner
746 
747 .keywords: TS, timestep, set, right-hand-side, function
748 
749 .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction()
750 @*/
751 PetscErrorCode  TSSetSolutionFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx)
752 {
753   PetscErrorCode ierr;
754   DM             dm;
755 
756   PetscFunctionBegin;
757   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
758   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
759   ierr = DMTSSetSolutionFunction(dm,f,ctx);CHKERRQ(ierr);
760   PetscFunctionReturn(0);
761 }
762 
763 #undef __FUNCT__
764 #define __FUNCT__ "TSSetRHSJacobian"
765 /*@C
766    TSSetRHSJacobian - Sets the function to compute the Jacobian of F,
767    where U_t = G(U,t), as well as the location to store the matrix.
768 
769    Logically Collective on TS
770 
771    Input Parameters:
772 +  ts  - the TS context obtained from TSCreate()
773 .  A   - Jacobian matrix
774 .  B   - preconditioner matrix (usually same as A)
775 .  f   - the Jacobian evaluation routine
776 -  ctx - [optional] user-defined context for private data for the
777          Jacobian evaluation routine (may be PETSC_NULL)
778 
779    Calling sequence of func:
780 $     func (TS ts,PetscReal t,Vec u,Mat *A,Mat *B,MatStructure *flag,void *ctx);
781 
782 +  t - current timestep
783 .  u - input vector
784 .  A - matrix A, where U_t = A(t)u
785 .  B - preconditioner matrix, usually the same as A
786 .  flag - flag indicating information about the preconditioner matrix
787           structure (same as flag in KSPSetOperators())
788 -  ctx - [optional] user-defined context for matrix evaluation routine
789 
790    Notes:
791    See KSPSetOperators() for important information about setting the flag
792    output parameter in the routine func().  Be sure to read this information!
793 
794    The routine func() takes Mat * as the matrix arguments rather than Mat.
795    This allows the matrix evaluation routine to replace A and/or B with a
796    completely new matrix structure (not just different matrix elements)
797    when appropriate, for instance, if the nonzero structure is changing
798    throughout the global iterations.
799 
800    Level: beginner
801 
802 .keywords: TS, timestep, set, right-hand-side, Jacobian
803 
804 .seealso: SNESDefaultComputeJacobianColor(), TSSetRHSFunction()
805 
806 @*/
807 PetscErrorCode  TSSetRHSJacobian(TS ts,Mat A,Mat B,TSRHSJacobian f,void *ctx)
808 {
809   PetscErrorCode ierr;
810   SNES           snes;
811   DM             dm;
812   TSIJacobian    ijacobian;
813 
814   PetscFunctionBegin;
815   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
816   if (A) PetscValidHeaderSpecific(A,MAT_CLASSID,2);
817   if (B) PetscValidHeaderSpecific(B,MAT_CLASSID,3);
818   if (A) PetscCheckSameComm(ts,1,A,2);
819   if (B) PetscCheckSameComm(ts,1,B,3);
820 
821   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
822   ierr = DMTSSetRHSJacobian(dm,f,ctx);CHKERRQ(ierr);
823   ierr = DMTSGetIJacobian(dm,&ijacobian,PETSC_NULL);CHKERRQ(ierr);
824 
825   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
826   if (!ijacobian) {
827     ierr = SNESSetJacobian(snes,A,B,SNESTSFormJacobian,ts);CHKERRQ(ierr);
828   }
829   if (A) {
830     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
831     ierr = MatDestroy(&ts->Arhs);CHKERRQ(ierr);
832     ts->Arhs = A;
833   }
834   if (B) {
835     ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
836     ierr = MatDestroy(&ts->Brhs);CHKERRQ(ierr);
837     ts->Brhs = B;
838   }
839   PetscFunctionReturn(0);
840 }
841 
842 
843 #undef __FUNCT__
844 #define __FUNCT__ "TSSetIFunction"
845 /*@C
846    TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved.
847 
848    Logically Collective on TS
849 
850    Input Parameters:
851 +  ts  - the TS context obtained from TSCreate()
852 .  r   - vector to hold the residual (or PETSC_NULL to have it created internally)
853 .  f   - the function evaluation routine
854 -  ctx - user-defined context for private data for the function evaluation routine (may be PETSC_NULL)
855 
856    Calling sequence of f:
857 $  f(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx);
858 
859 +  t   - time at step/stage being solved
860 .  u   - state vector
861 .  u_t - time derivative of state vector
862 .  F   - function vector
863 -  ctx - [optional] user-defined context for matrix evaluation routine
864 
865    Important:
866    The user MUST call either this routine, TSSetRHSFunction().  This routine must be used when not solving an ODE, for example a DAE.
867 
868    Level: beginner
869 
870 .keywords: TS, timestep, set, DAE, Jacobian
871 
872 .seealso: TSSetRHSJacobian(), TSSetRHSFunction(), TSSetIJacobian()
873 @*/
874 PetscErrorCode  TSSetIFunction(TS ts,Vec res,TSIFunction f,void *ctx)
875 {
876   PetscErrorCode ierr;
877   SNES           snes;
878   Vec            resalloc = PETSC_NULL;
879   DM             dm;
880 
881   PetscFunctionBegin;
882   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
883   if (res) PetscValidHeaderSpecific(res,VEC_CLASSID,2);
884 
885   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
886   ierr = DMTSSetIFunction(dm,f,ctx);CHKERRQ(ierr);
887 
888   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
889   if (!res && !ts->dm && ts->vec_sol) {
890     ierr = VecDuplicate(ts->vec_sol,&resalloc);CHKERRQ(ierr);
891     res = resalloc;
892   }
893   ierr = SNESSetFunction(snes,res,SNESTSFormFunction,ts);CHKERRQ(ierr);
894   ierr = VecDestroy(&resalloc);CHKERRQ(ierr);
895 
896   PetscFunctionReturn(0);
897 }
898 
899 #undef __FUNCT__
900 #define __FUNCT__ "TSGetIFunction"
901 /*@C
902    TSGetIFunction - Returns the vector where the implicit residual is stored and the function/contex to compute it.
903 
904    Not Collective
905 
906    Input Parameter:
907 .  ts - the TS context
908 
909    Output Parameter:
910 +  r - vector to hold residual (or PETSC_NULL)
911 .  func - the function to compute residual (or PETSC_NULL)
912 -  ctx - the function context (or PETSC_NULL)
913 
914    Level: advanced
915 
916 .keywords: TS, nonlinear, get, function
917 
918 .seealso: TSSetIFunction(), SNESGetFunction()
919 @*/
920 PetscErrorCode TSGetIFunction(TS ts,Vec *r,TSIFunction *func,void **ctx)
921 {
922   PetscErrorCode ierr;
923   SNES           snes;
924   DM             dm;
925 
926   PetscFunctionBegin;
927   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
928   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
929   ierr = SNESGetFunction(snes,r,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
930   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
931   ierr = DMTSGetIFunction(dm,func,ctx);CHKERRQ(ierr);
932   PetscFunctionReturn(0);
933 }
934 
935 #undef __FUNCT__
936 #define __FUNCT__ "TSGetRHSFunction"
937 /*@C
938    TSGetRHSFunction - Returns the vector where the right hand side is stored and the function/context to compute it.
939 
940    Not Collective
941 
942    Input Parameter:
943 .  ts - the TS context
944 
945    Output Parameter:
946 +  r - vector to hold computed right hand side (or PETSC_NULL)
947 .  func - the function to compute right hand side (or PETSC_NULL)
948 -  ctx - the function context (or PETSC_NULL)
949 
950    Level: advanced
951 
952 .keywords: TS, nonlinear, get, function
953 
954 .seealso: TSSetRhsfunction(), SNESGetFunction()
955 @*/
956 PetscErrorCode TSGetRHSFunction(TS ts,Vec *r,TSRHSFunction *func,void **ctx)
957 {
958   PetscErrorCode ierr;
959   SNES           snes;
960   DM             dm;
961 
962   PetscFunctionBegin;
963   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
964   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
965   ierr = SNESGetFunction(snes,r,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
966   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
967   ierr = DMTSGetRHSFunction(dm,func,ctx);CHKERRQ(ierr);
968   PetscFunctionReturn(0);
969 }
970 
971 #undef __FUNCT__
972 #define __FUNCT__ "TSSetIJacobian"
973 /*@C
974    TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function
975         you provided with TSSetIFunction().
976 
977    Logically Collective on TS
978 
979    Input Parameters:
980 +  ts  - the TS context obtained from TSCreate()
981 .  A   - Jacobian matrix
982 .  B   - preconditioning matrix for A (may be same as A)
983 .  f   - the Jacobian evaluation routine
984 -  ctx - user-defined context for private data for the Jacobian evaluation routine (may be PETSC_NULL)
985 
986    Calling sequence of f:
987 $  f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat *A,Mat *B,MatStructure *flag,void *ctx);
988 
989 +  t    - time at step/stage being solved
990 .  U    - state vector
991 .  U_t  - time derivative of state vector
992 .  a    - shift
993 .  A    - Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
994 .  B    - preconditioning matrix for A, may be same as A
995 .  flag - flag indicating information about the preconditioner matrix
996           structure (same as flag in KSPSetOperators())
997 -  ctx  - [optional] user-defined context for matrix evaluation routine
998 
999    Notes:
1000    The matrices A and B are exactly the matrices that are used by SNES for the nonlinear solve.
1001 
1002    The matrix dF/dU + a*dF/dU_t you provide turns out to be
1003    the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
1004    The time integrator internally approximates U_t by W+a*U where the positive "shift"
1005    a and vector W depend on the integration method, step size, and past states. For example with
1006    the backward Euler method a = 1/dt and W = -a*U(previous timestep) so
1007    W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt
1008 
1009    Level: beginner
1010 
1011 .keywords: TS, timestep, DAE, Jacobian
1012 
1013 .seealso: TSSetIFunction(), TSSetRHSJacobian(), SNESDefaultComputeJacobianColor(), SNESDefaultComputeJacobian()
1014 
1015 @*/
1016 PetscErrorCode  TSSetIJacobian(TS ts,Mat A,Mat B,TSIJacobian f,void *ctx)
1017 {
1018   PetscErrorCode ierr;
1019   SNES           snes;
1020   DM             dm;
1021 
1022   PetscFunctionBegin;
1023   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1024   if (A) PetscValidHeaderSpecific(A,MAT_CLASSID,2);
1025   if (B) PetscValidHeaderSpecific(B,MAT_CLASSID,3);
1026   if (A) PetscCheckSameComm(ts,1,A,2);
1027   if (B) PetscCheckSameComm(ts,1,B,3);
1028 
1029   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1030   ierr = DMTSSetIJacobian(dm,f,ctx);CHKERRQ(ierr);
1031 
1032   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1033   ierr = SNESSetJacobian(snes,A,B,SNESTSFormJacobian,ts);CHKERRQ(ierr);
1034   PetscFunctionReturn(0);
1035 }
1036 
1037 #undef __FUNCT__
1038 #define __FUNCT__ "TSLoad"
1039 /*@C
1040   TSLoad - Loads a KSP that has been stored in binary  with KSPView().
1041 
1042   Collective on PetscViewer
1043 
1044   Input Parameters:
1045 + newdm - the newly loaded TS, this needs to have been created with TSCreate() or
1046            some related function before a call to TSLoad().
1047 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen()
1048 
1049    Level: intermediate
1050 
1051   Notes:
1052    The type is determined by the data in the file, any type set into the TS before this call is ignored.
1053 
1054   Notes for advanced users:
1055   Most users should not need to know the details of the binary storage
1056   format, since TSLoad() and TSView() completely hide these details.
1057   But for anyone who's interested, the standard binary matrix storage
1058   format is
1059 .vb
1060      has not yet been determined
1061 .ve
1062 
1063 .seealso: PetscViewerBinaryOpen(), TSView(), MatLoad(), VecLoad()
1064 @*/
1065 PetscErrorCode  TSLoad(TS newdm, PetscViewer viewer)
1066 {
1067   PetscErrorCode ierr;
1068   PetscBool      isbinary;
1069   PetscInt       classid;
1070   char           type[256];
1071   SNES           snes;
1072 
1073   PetscFunctionBegin;
1074   PetscValidHeaderSpecific(newdm,TS_CLASSID,1);
1075   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1076   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1077   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
1078 
1079   ierr = PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);CHKERRQ(ierr);
1080   if (classid != TS_FILE_CLASSID) SETERRQ(((PetscObject)newdm)->comm,PETSC_ERR_ARG_WRONG,"Not TS next in file");
1081   ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr);
1082   ierr = TSSetType(newdm, type);CHKERRQ(ierr);
1083   ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);
1084   ierr = TSGetSNES(newdm,&snes);CHKERRQ(ierr);
1085   ierr = SNESLoad(snes,viewer);CHKERRQ(ierr);
1086   PetscFunctionReturn(0);
1087 }
1088 
1089 #undef __FUNCT__
1090 #define __FUNCT__ "TSView"
1091 /*@C
1092     TSView - Prints the TS data structure.
1093 
1094     Collective on TS
1095 
1096     Input Parameters:
1097 +   ts - the TS context obtained from TSCreate()
1098 -   viewer - visualization context
1099 
1100     Options Database Key:
1101 .   -ts_view - calls TSView() at end of TSStep()
1102 
1103     Notes:
1104     The available visualization contexts include
1105 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
1106 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1107          output where only the first processor opens
1108          the file.  All other processors send their
1109          data to the first processor to print.
1110 
1111     The user can open an alternative visualization context with
1112     PetscViewerASCIIOpen() - output to a specified file.
1113 
1114     Level: beginner
1115 
1116 .keywords: TS, timestep, view
1117 
1118 .seealso: PetscViewerASCIIOpen()
1119 @*/
1120 PetscErrorCode  TSView(TS ts,PetscViewer viewer)
1121 {
1122   PetscErrorCode ierr;
1123   TSType         type;
1124   PetscBool      iascii,isstring,isundials,isbinary;
1125 
1126   PetscFunctionBegin;
1127   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1128   if (!viewer) {
1129     ierr = PetscViewerASCIIGetStdout(((PetscObject)ts)->comm,&viewer);CHKERRQ(ierr);
1130   }
1131   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1132   PetscCheckSameComm(ts,1,viewer,2);
1133 
1134   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1135   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
1136   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1137   if (iascii) {
1138     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer,"TS Object");CHKERRQ(ierr);
1139     ierr = PetscViewerASCIIPrintf(viewer,"  maximum steps=%D\n",ts->max_steps);CHKERRQ(ierr);
1140     ierr = PetscViewerASCIIPrintf(viewer,"  maximum time=%G\n",ts->max_time);CHKERRQ(ierr);
1141     if (ts->problem_type == TS_NONLINEAR) {
1142       ierr = PetscViewerASCIIPrintf(viewer,"  total number of nonlinear solver iterations=%D\n",ts->snes_its);CHKERRQ(ierr);
1143       ierr = PetscViewerASCIIPrintf(viewer,"  total number of nonlinear solve failures=%D\n",ts->num_snes_failures);CHKERRQ(ierr);
1144     }
1145     ierr = PetscViewerASCIIPrintf(viewer,"  total number of linear solver iterations=%D\n",ts->ksp_its);CHKERRQ(ierr);
1146     ierr = PetscViewerASCIIPrintf(viewer,"  total number of rejected steps=%D\n",ts->reject);CHKERRQ(ierr);
1147     if (ts->ops->view) {
1148       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1149       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
1150       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1151     }
1152   } else if (isstring) {
1153     ierr = TSGetType(ts,&type);CHKERRQ(ierr);
1154     ierr = PetscViewerStringSPrintf(viewer," %-7.7s",type);CHKERRQ(ierr);
1155   } else if (isbinary) {
1156     PetscInt         classid = TS_FILE_CLASSID;
1157     MPI_Comm         comm;
1158     PetscMPIInt      rank;
1159     char             type[256];
1160 
1161     ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
1162     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1163     if (!rank) {
1164       ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
1165       ierr = PetscStrncpy(type,((PetscObject)ts)->type_name,256);CHKERRQ(ierr);
1166       ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
1167     }
1168     if (ts->ops->view) {
1169       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
1170     }
1171   }
1172   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1173   ierr = PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials);CHKERRQ(ierr);
1174   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1175   PetscFunctionReturn(0);
1176 }
1177 
1178 
1179 #undef __FUNCT__
1180 #define __FUNCT__ "TSSetApplicationContext"
1181 /*@
1182    TSSetApplicationContext - Sets an optional user-defined context for
1183    the timesteppers.
1184 
1185    Logically Collective on TS
1186 
1187    Input Parameters:
1188 +  ts - the TS context obtained from TSCreate()
1189 -  usrP - optional user context
1190 
1191    Level: intermediate
1192 
1193 .keywords: TS, timestep, set, application, context
1194 
1195 .seealso: TSGetApplicationContext()
1196 @*/
1197 PetscErrorCode  TSSetApplicationContext(TS ts,void *usrP)
1198 {
1199   PetscFunctionBegin;
1200   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1201   ts->user = usrP;
1202   PetscFunctionReturn(0);
1203 }
1204 
1205 #undef __FUNCT__
1206 #define __FUNCT__ "TSGetApplicationContext"
1207 /*@
1208     TSGetApplicationContext - Gets the user-defined context for the
1209     timestepper.
1210 
1211     Not Collective
1212 
1213     Input Parameter:
1214 .   ts - the TS context obtained from TSCreate()
1215 
1216     Output Parameter:
1217 .   usrP - user context
1218 
1219     Level: intermediate
1220 
1221 .keywords: TS, timestep, get, application, context
1222 
1223 .seealso: TSSetApplicationContext()
1224 @*/
1225 PetscErrorCode  TSGetApplicationContext(TS ts,void *usrP)
1226 {
1227   PetscFunctionBegin;
1228   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1229   *(void**)usrP = ts->user;
1230   PetscFunctionReturn(0);
1231 }
1232 
1233 #undef __FUNCT__
1234 #define __FUNCT__ "TSGetTimeStepNumber"
1235 /*@
1236    TSGetTimeStepNumber - Gets the number of time steps completed.
1237 
1238    Not Collective
1239 
1240    Input Parameter:
1241 .  ts - the TS context obtained from TSCreate()
1242 
1243    Output Parameter:
1244 .  iter - number of steps completed so far
1245 
1246    Level: intermediate
1247 
1248 .keywords: TS, timestep, get, iteration, number
1249 .seealso: TSGetTime(), TSGetTimeStep(), TSSetPreStep(), TSSetPreStage(), TSSetPostStep()
1250 @*/
1251 PetscErrorCode  TSGetTimeStepNumber(TS ts,PetscInt* iter)
1252 {
1253   PetscFunctionBegin;
1254   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1255   PetscValidIntPointer(iter,2);
1256   *iter = ts->steps;
1257   PetscFunctionReturn(0);
1258 }
1259 
1260 #undef __FUNCT__
1261 #define __FUNCT__ "TSSetInitialTimeStep"
1262 /*@
1263    TSSetInitialTimeStep - Sets the initial timestep to be used,
1264    as well as the initial time.
1265 
1266    Logically Collective on TS
1267 
1268    Input Parameters:
1269 +  ts - the TS context obtained from TSCreate()
1270 .  initial_time - the initial time
1271 -  time_step - the size of the timestep
1272 
1273    Level: intermediate
1274 
1275 .seealso: TSSetTimeStep(), TSGetTimeStep()
1276 
1277 .keywords: TS, set, initial, timestep
1278 @*/
1279 PetscErrorCode  TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step)
1280 {
1281   PetscErrorCode ierr;
1282 
1283   PetscFunctionBegin;
1284   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1285   ierr = TSSetTimeStep(ts,time_step);CHKERRQ(ierr);
1286   ierr = TSSetTime(ts,initial_time);CHKERRQ(ierr);
1287   PetscFunctionReturn(0);
1288 }
1289 
1290 #undef __FUNCT__
1291 #define __FUNCT__ "TSSetTimeStep"
1292 /*@
1293    TSSetTimeStep - Allows one to reset the timestep at any time,
1294    useful for simple pseudo-timestepping codes.
1295 
1296    Logically Collective on TS
1297 
1298    Input Parameters:
1299 +  ts - the TS context obtained from TSCreate()
1300 -  time_step - the size of the timestep
1301 
1302    Level: intermediate
1303 
1304 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1305 
1306 .keywords: TS, set, timestep
1307 @*/
1308 PetscErrorCode  TSSetTimeStep(TS ts,PetscReal time_step)
1309 {
1310   PetscFunctionBegin;
1311   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1312   PetscValidLogicalCollectiveReal(ts,time_step,2);
1313   ts->time_step = time_step;
1314   ts->time_step_orig = time_step;
1315   PetscFunctionReturn(0);
1316 }
1317 
1318 #undef __FUNCT__
1319 #define __FUNCT__ "TSSetExactFinalTime"
1320 /*@
1321    TSSetExactFinalTime - Determines whether to interpolate solution to the
1322       exact final time requested by the user or just returns it at the final time
1323       it computed.
1324 
1325   Logically Collective on TS
1326 
1327    Input Parameter:
1328 +   ts - the time-step context
1329 -   ft - PETSC_TRUE if interpolates, else PETSC_FALSE
1330 
1331    Level: beginner
1332 
1333 .seealso: TSSetDuration()
1334 @*/
1335 PetscErrorCode  TSSetExactFinalTime(TS ts,PetscBool flg)
1336 {
1337   PetscFunctionBegin;
1338   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1339   PetscValidLogicalCollectiveBool(ts,flg,2);
1340   ts->exact_final_time = flg;
1341   PetscFunctionReturn(0);
1342 }
1343 
1344 #undef __FUNCT__
1345 #define __FUNCT__ "TSGetTimeStep"
1346 /*@
1347    TSGetTimeStep - Gets the current timestep size.
1348 
1349    Not Collective
1350 
1351    Input Parameter:
1352 .  ts - the TS context obtained from TSCreate()
1353 
1354    Output Parameter:
1355 .  dt - the current timestep size
1356 
1357    Level: intermediate
1358 
1359 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1360 
1361 .keywords: TS, get, timestep
1362 @*/
1363 PetscErrorCode  TSGetTimeStep(TS ts,PetscReal* dt)
1364 {
1365   PetscFunctionBegin;
1366   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1367   PetscValidRealPointer(dt,2);
1368   *dt = ts->time_step;
1369   PetscFunctionReturn(0);
1370 }
1371 
1372 #undef __FUNCT__
1373 #define __FUNCT__ "TSGetSolution"
1374 /*@
1375    TSGetSolution - Returns the solution at the present timestep. It
1376    is valid to call this routine inside the function that you are evaluating
1377    in order to move to the new timestep. This vector not changed until
1378    the solution at the next timestep has been calculated.
1379 
1380    Not Collective, but Vec returned is parallel if TS is parallel
1381 
1382    Input Parameter:
1383 .  ts - the TS context obtained from TSCreate()
1384 
1385    Output Parameter:
1386 .  v - the vector containing the solution
1387 
1388    Level: intermediate
1389 
1390 .seealso: TSGetTimeStep()
1391 
1392 .keywords: TS, timestep, get, solution
1393 @*/
1394 PetscErrorCode  TSGetSolution(TS ts,Vec *v)
1395 {
1396   PetscFunctionBegin;
1397   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1398   PetscValidPointer(v,2);
1399   *v = ts->vec_sol;
1400   PetscFunctionReturn(0);
1401 }
1402 
1403 /* ----- Routines to initialize and destroy a timestepper ---- */
1404 #undef __FUNCT__
1405 #define __FUNCT__ "TSSetProblemType"
1406 /*@
1407   TSSetProblemType - Sets the type of problem to be solved.
1408 
1409   Not collective
1410 
1411   Input Parameters:
1412 + ts   - The TS
1413 - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1414 .vb
1415          U_t - A U = 0      (linear)
1416          U_t - A(t) U = 0   (linear)
1417          F(t,U,U_t) = 0     (nonlinear)
1418 .ve
1419 
1420    Level: beginner
1421 
1422 .keywords: TS, problem type
1423 .seealso: TSSetUp(), TSProblemType, TS
1424 @*/
1425 PetscErrorCode  TSSetProblemType(TS ts, TSProblemType type)
1426 {
1427   PetscErrorCode ierr;
1428 
1429   PetscFunctionBegin;
1430   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1431   ts->problem_type = type;
1432   if (type == TS_LINEAR) {
1433     SNES snes;
1434     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1435     ierr = SNESSetType(snes,SNESKSPONLY);CHKERRQ(ierr);
1436   }
1437   PetscFunctionReturn(0);
1438 }
1439 
1440 #undef __FUNCT__
1441 #define __FUNCT__ "TSGetProblemType"
1442 /*@C
1443   TSGetProblemType - Gets the type of problem to be solved.
1444 
1445   Not collective
1446 
1447   Input Parameter:
1448 . ts   - The TS
1449 
1450   Output Parameter:
1451 . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1452 .vb
1453          M U_t = A U
1454          M(t) U_t = A(t) U
1455          F(t,U,U_t)
1456 .ve
1457 
1458    Level: beginner
1459 
1460 .keywords: TS, problem type
1461 .seealso: TSSetUp(), TSProblemType, TS
1462 @*/
1463 PetscErrorCode  TSGetProblemType(TS ts, TSProblemType *type)
1464 {
1465   PetscFunctionBegin;
1466   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1467   PetscValidIntPointer(type,2);
1468   *type = ts->problem_type;
1469   PetscFunctionReturn(0);
1470 }
1471 
1472 #undef __FUNCT__
1473 #define __FUNCT__ "TSSetUp"
1474 /*@
1475    TSSetUp - Sets up the internal data structures for the later use
1476    of a timestepper.
1477 
1478    Collective on TS
1479 
1480    Input Parameter:
1481 .  ts - the TS context obtained from TSCreate()
1482 
1483    Notes:
1484    For basic use of the TS solvers the user need not explicitly call
1485    TSSetUp(), since these actions will automatically occur during
1486    the call to TSStep().  However, if one wishes to control this
1487    phase separately, TSSetUp() should be called after TSCreate()
1488    and optional routines of the form TSSetXXX(), but before TSStep().
1489 
1490    Level: advanced
1491 
1492 .keywords: TS, timestep, setup
1493 
1494 .seealso: TSCreate(), TSStep(), TSDestroy()
1495 @*/
1496 PetscErrorCode  TSSetUp(TS ts)
1497 {
1498   PetscErrorCode ierr;
1499   DM             dm;
1500   PetscErrorCode (*func)(SNES,Vec,Vec,void*);
1501   PetscErrorCode (*jac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
1502   TSIJacobian    ijac;
1503   TSRHSJacobian  rhsjac;
1504 
1505   PetscFunctionBegin;
1506   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1507   if (ts->setupcalled) PetscFunctionReturn(0);
1508 
1509   if (!((PetscObject)ts)->type_name) {
1510     ierr = TSSetType(ts,TSEULER);CHKERRQ(ierr);
1511   }
1512   if (ts->exact_final_time == PETSC_DECIDE) ts->exact_final_time = PETSC_FALSE;
1513 
1514   if (!ts->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first");
1515 
1516   ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr);
1517 
1518   if (ts->ops->setup) {
1519     ierr = (*ts->ops->setup)(ts);CHKERRQ(ierr);
1520   }
1521 
1522   /* in the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
1523    to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
1524    */
1525   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1526   ierr = DMSNESGetFunction(dm,&func,PETSC_NULL);CHKERRQ(ierr);
1527   if (!func) {
1528     ierr =DMSNESSetFunction(dm,SNESTSFormFunction,ts);CHKERRQ(ierr);
1529   }
1530   /* if the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
1531      Otherwise, the SNES will use coloring internally to form the Jacobian.
1532    */
1533   ierr = DMSNESGetJacobian(dm,&jac,PETSC_NULL);CHKERRQ(ierr);
1534   ierr = DMTSGetIJacobian(dm,&ijac,PETSC_NULL);CHKERRQ(ierr);
1535   ierr = DMTSGetRHSJacobian(dm,&rhsjac,PETSC_NULL);CHKERRQ(ierr);
1536   if (!jac && (ijac || rhsjac)) {
1537     ierr = DMSNESSetJacobian(dm,SNESTSFormJacobian,ts);CHKERRQ(ierr);
1538   }
1539   ts->setupcalled = PETSC_TRUE;
1540   PetscFunctionReturn(0);
1541 }
1542 
1543 #undef __FUNCT__
1544 #define __FUNCT__ "TSReset"
1545 /*@
1546    TSReset - Resets a TS context and removes any allocated Vecs and Mats.
1547 
1548    Collective on TS
1549 
1550    Input Parameter:
1551 .  ts - the TS context obtained from TSCreate()
1552 
1553    Level: beginner
1554 
1555 .keywords: TS, timestep, reset
1556 
1557 .seealso: TSCreate(), TSSetup(), TSDestroy()
1558 @*/
1559 PetscErrorCode  TSReset(TS ts)
1560 {
1561   PetscErrorCode ierr;
1562 
1563   PetscFunctionBegin;
1564   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1565   if (ts->ops->reset) {
1566     ierr = (*ts->ops->reset)(ts);CHKERRQ(ierr);
1567   }
1568   if (ts->snes) {ierr = SNESReset(ts->snes);CHKERRQ(ierr);}
1569   ierr = MatDestroy(&ts->Arhs);CHKERRQ(ierr);
1570   ierr = MatDestroy(&ts->Brhs);CHKERRQ(ierr);
1571   ierr = VecDestroy(&ts->Frhs);CHKERRQ(ierr);
1572   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
1573   ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
1574   ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
1575   ierr = VecDestroyVecs(ts->nwork,&ts->work);CHKERRQ(ierr);
1576   ts->setupcalled = PETSC_FALSE;
1577   PetscFunctionReturn(0);
1578 }
1579 
1580 #undef __FUNCT__
1581 #define __FUNCT__ "TSDestroy"
1582 /*@
1583    TSDestroy - Destroys the timestepper context that was created
1584    with TSCreate().
1585 
1586    Collective on TS
1587 
1588    Input Parameter:
1589 .  ts - the TS context obtained from TSCreate()
1590 
1591    Level: beginner
1592 
1593 .keywords: TS, timestepper, destroy
1594 
1595 .seealso: TSCreate(), TSSetUp(), TSSolve()
1596 @*/
1597 PetscErrorCode  TSDestroy(TS *ts)
1598 {
1599   PetscErrorCode ierr;
1600 
1601   PetscFunctionBegin;
1602   if (!*ts) PetscFunctionReturn(0);
1603   PetscValidHeaderSpecific((*ts),TS_CLASSID,1);
1604   if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; PetscFunctionReturn(0);}
1605 
1606   ierr = TSReset((*ts));CHKERRQ(ierr);
1607 
1608   /* if memory was published with AMS then destroy it */
1609   ierr = PetscObjectDepublish((*ts));CHKERRQ(ierr);
1610   if ((*ts)->ops->destroy) {ierr = (*(*ts)->ops->destroy)((*ts));CHKERRQ(ierr);}
1611 
1612   ierr = TSAdaptDestroy(&(*ts)->adapt);CHKERRQ(ierr);
1613   ierr = SNESDestroy(&(*ts)->snes);CHKERRQ(ierr);
1614   ierr = DMDestroy(&(*ts)->dm);CHKERRQ(ierr);
1615   ierr = TSMonitorCancel((*ts));CHKERRQ(ierr);
1616 
1617   ierr = PetscHeaderDestroy(ts);CHKERRQ(ierr);
1618   PetscFunctionReturn(0);
1619 }
1620 
1621 #undef __FUNCT__
1622 #define __FUNCT__ "TSGetSNES"
1623 /*@
1624    TSGetSNES - Returns the SNES (nonlinear solver) associated with
1625    a TS (timestepper) context. Valid only for nonlinear problems.
1626 
1627    Not Collective, but SNES is parallel if TS is parallel
1628 
1629    Input Parameter:
1630 .  ts - the TS context obtained from TSCreate()
1631 
1632    Output Parameter:
1633 .  snes - the nonlinear solver context
1634 
1635    Notes:
1636    The user can then directly manipulate the SNES context to set various
1637    options, etc.  Likewise, the user can then extract and manipulate the
1638    KSP, KSP, and PC contexts as well.
1639 
1640    TSGetSNES() does not work for integrators that do not use SNES; in
1641    this case TSGetSNES() returns PETSC_NULL in snes.
1642 
1643    Level: beginner
1644 
1645 .keywords: timestep, get, SNES
1646 @*/
1647 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
1648 {
1649   PetscErrorCode ierr;
1650 
1651   PetscFunctionBegin;
1652   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1653   PetscValidPointer(snes,2);
1654   if (!ts->snes) {
1655     ierr = SNESCreate(((PetscObject)ts)->comm,&ts->snes);CHKERRQ(ierr);
1656     ierr = SNESSetFunction(ts->snes,PETSC_NULL,SNESTSFormFunction,ts);CHKERRQ(ierr);
1657     ierr = PetscLogObjectParent(ts,ts->snes);CHKERRQ(ierr);
1658     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);CHKERRQ(ierr);
1659     if (ts->dm) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
1660     if (ts->problem_type == TS_LINEAR) {
1661       ierr = SNESSetType(ts->snes,SNESKSPONLY);CHKERRQ(ierr);
1662     }
1663   }
1664   *snes = ts->snes;
1665   PetscFunctionReturn(0);
1666 }
1667 
1668 #undef __FUNCT__
1669 #define __FUNCT__ "TSGetKSP"
1670 /*@
1671    TSGetKSP - Returns the KSP (linear solver) associated with
1672    a TS (timestepper) context.
1673 
1674    Not Collective, but KSP is parallel if TS is parallel
1675 
1676    Input Parameter:
1677 .  ts - the TS context obtained from TSCreate()
1678 
1679    Output Parameter:
1680 .  ksp - the nonlinear solver context
1681 
1682    Notes:
1683    The user can then directly manipulate the KSP context to set various
1684    options, etc.  Likewise, the user can then extract and manipulate the
1685    KSP and PC contexts as well.
1686 
1687    TSGetKSP() does not work for integrators that do not use KSP;
1688    in this case TSGetKSP() returns PETSC_NULL in ksp.
1689 
1690    Level: beginner
1691 
1692 .keywords: timestep, get, KSP
1693 @*/
1694 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
1695 {
1696   PetscErrorCode ierr;
1697   SNES           snes;
1698 
1699   PetscFunctionBegin;
1700   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1701   PetscValidPointer(ksp,2);
1702   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
1703   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
1704   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
1705   ierr = SNESGetKSP(snes,ksp);CHKERRQ(ierr);
1706   PetscFunctionReturn(0);
1707 }
1708 
1709 /* ----------- Routines to set solver parameters ---------- */
1710 
1711 #undef __FUNCT__
1712 #define __FUNCT__ "TSGetDuration"
1713 /*@
1714    TSGetDuration - Gets the maximum number of timesteps to use and
1715    maximum time for iteration.
1716 
1717    Not Collective
1718 
1719    Input Parameters:
1720 +  ts       - the TS context obtained from TSCreate()
1721 .  maxsteps - maximum number of iterations to use, or PETSC_NULL
1722 -  maxtime  - final time to iterate to, or PETSC_NULL
1723 
1724    Level: intermediate
1725 
1726 .keywords: TS, timestep, get, maximum, iterations, time
1727 @*/
1728 PetscErrorCode  TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
1729 {
1730   PetscFunctionBegin;
1731   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1732   if (maxsteps) {
1733     PetscValidIntPointer(maxsteps,2);
1734     *maxsteps = ts->max_steps;
1735   }
1736   if (maxtime) {
1737     PetscValidScalarPointer(maxtime,3);
1738     *maxtime  = ts->max_time;
1739   }
1740   PetscFunctionReturn(0);
1741 }
1742 
1743 #undef __FUNCT__
1744 #define __FUNCT__ "TSSetDuration"
1745 /*@
1746    TSSetDuration - Sets the maximum number of timesteps to use and
1747    maximum time for iteration.
1748 
1749    Logically Collective on TS
1750 
1751    Input Parameters:
1752 +  ts - the TS context obtained from TSCreate()
1753 .  maxsteps - maximum number of iterations to use
1754 -  maxtime - final time to iterate to
1755 
1756    Options Database Keys:
1757 .  -ts_max_steps <maxsteps> - Sets maxsteps
1758 .  -ts_final_time <maxtime> - Sets maxtime
1759 
1760    Notes:
1761    The default maximum number of iterations is 5000. Default time is 5.0
1762 
1763    Level: intermediate
1764 
1765 .keywords: TS, timestep, set, maximum, iterations
1766 
1767 .seealso: TSSetExactFinalTime()
1768 @*/
1769 PetscErrorCode  TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
1770 {
1771   PetscFunctionBegin;
1772   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1773   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
1774   PetscValidLogicalCollectiveReal(ts,maxtime,2);
1775   if (maxsteps >= 0) ts->max_steps = maxsteps;
1776   if (maxtime != PETSC_DEFAULT) ts->max_time  = maxtime;
1777   PetscFunctionReturn(0);
1778 }
1779 
1780 #undef __FUNCT__
1781 #define __FUNCT__ "TSSetSolution"
1782 /*@
1783    TSSetSolution - Sets the initial solution vector
1784    for use by the TS routines.
1785 
1786    Logically Collective on TS and Vec
1787 
1788    Input Parameters:
1789 +  ts - the TS context obtained from TSCreate()
1790 -  u - the solution vector
1791 
1792    Level: beginner
1793 
1794 .keywords: TS, timestep, set, solution, initial conditions
1795 @*/
1796 PetscErrorCode  TSSetSolution(TS ts,Vec u)
1797 {
1798   PetscErrorCode ierr;
1799   DM             dm;
1800 
1801   PetscFunctionBegin;
1802   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1803   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
1804   ierr = PetscObjectReference((PetscObject)u);CHKERRQ(ierr);
1805   ierr = VecDestroy(&ts->vec_sol);CHKERRQ(ierr);
1806   ts->vec_sol = u;
1807   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
1808   ierr = DMShellSetGlobalVector(dm,u);CHKERRQ(ierr);
1809   PetscFunctionReturn(0);
1810 }
1811 
1812 #undef __FUNCT__
1813 #define __FUNCT__ "TSSetPreStep"
1814 /*@C
1815   TSSetPreStep - Sets the general-purpose function
1816   called once at the beginning of each time step.
1817 
1818   Logically Collective on TS
1819 
1820   Input Parameters:
1821 + ts   - The TS context obtained from TSCreate()
1822 - func - The function
1823 
1824   Calling sequence of func:
1825 . func (TS ts);
1826 
1827   Level: intermediate
1828 
1829   Note:
1830   If a step is rejected, TSStep() will call this routine again before each attempt.
1831   The last completed time step number can be queried using TSGetTimeStepNumber(), the
1832   size of the step being attempted can be obtained using TSGetTimeStep().
1833 
1834 .keywords: TS, timestep
1835 .seealso: TSSetPreStage(), TSSetPostStep(), TSStep()
1836 @*/
1837 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
1838 {
1839   PetscFunctionBegin;
1840   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1841   ts->ops->prestep = func;
1842   PetscFunctionReturn(0);
1843 }
1844 
1845 #undef __FUNCT__
1846 #define __FUNCT__ "TSPreStep"
1847 /*@
1848   TSPreStep - Runs the user-defined pre-step function.
1849 
1850   Collective on TS
1851 
1852   Input Parameters:
1853 . ts   - The TS context obtained from TSCreate()
1854 
1855   Notes:
1856   TSPreStep() is typically used within time stepping implementations,
1857   so most users would not generally call this routine themselves.
1858 
1859   Level: developer
1860 
1861 .keywords: TS, timestep
1862 .seealso: TSSetPreStep(), TSPreStage(), TSPostStep()
1863 @*/
1864 PetscErrorCode  TSPreStep(TS ts)
1865 {
1866   PetscErrorCode ierr;
1867 
1868   PetscFunctionBegin;
1869   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1870   if (ts->ops->prestep) {
1871     PetscStackPush("TS PreStep function");
1872     ierr = (*ts->ops->prestep)(ts);CHKERRQ(ierr);
1873     PetscStackPop;
1874   }
1875   PetscFunctionReturn(0);
1876 }
1877 
1878 #undef __FUNCT__
1879 #define __FUNCT__ "TSSetPreStage"
1880 /*@C
1881   TSSetPreStage - Sets the general-purpose function
1882   called once at the beginning of each stage.
1883 
1884   Logically Collective on TS
1885 
1886   Input Parameters:
1887 + ts   - The TS context obtained from TSCreate()
1888 - func - The function
1889 
1890   Calling sequence of func:
1891 . PetscErrorCode func(TS ts, PetscReal stagetime);
1892 
1893   Level: intermediate
1894 
1895   Note:
1896   There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
1897   The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
1898   attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
1899 
1900 .keywords: TS, timestep
1901 .seealso: TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
1902 @*/
1903 PetscErrorCode  TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
1904 {
1905   PetscFunctionBegin;
1906   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1907   ts->ops->prestage = func;
1908   PetscFunctionReturn(0);
1909 }
1910 
1911 #undef __FUNCT__
1912 #define __FUNCT__ "TSPreStage"
1913 /*@
1914   TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
1915 
1916   Collective on TS
1917 
1918   Input Parameters:
1919 . ts   - The TS context obtained from TSCreate()
1920 
1921   Notes:
1922   TSPreStage() is typically used within time stepping implementations,
1923   most users would not generally call this routine themselves.
1924 
1925   Level: developer
1926 
1927 .keywords: TS, timestep
1928 .seealso: TSSetPreStep(), TSPreStep(), TSPostStep()
1929 @*/
1930 PetscErrorCode  TSPreStage(TS ts, PetscReal stagetime)
1931 {
1932   PetscErrorCode ierr;
1933 
1934   PetscFunctionBegin;
1935   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1936   if (ts->ops->prestage) {
1937     PetscStackPush("TS PreStage function");
1938     ierr = (*ts->ops->prestage)(ts,stagetime);CHKERRQ(ierr);
1939     PetscStackPop;
1940   }
1941   PetscFunctionReturn(0);
1942 }
1943 
1944 #undef __FUNCT__
1945 #define __FUNCT__ "TSSetPostStep"
1946 /*@C
1947   TSSetPostStep - Sets the general-purpose function
1948   called once at the end of each time step.
1949 
1950   Logically Collective on TS
1951 
1952   Input Parameters:
1953 + ts   - The TS context obtained from TSCreate()
1954 - func - The function
1955 
1956   Calling sequence of func:
1957 $ func (TS ts);
1958 
1959   Level: intermediate
1960 
1961 .keywords: TS, timestep
1962 .seealso: TSSetPreStep(), TSSetPreStage(), TSGetTimeStep(), TSGetTimeStepNumber(), TSGetTime()
1963 @*/
1964 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
1965 {
1966   PetscFunctionBegin;
1967   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1968   ts->ops->poststep = func;
1969   PetscFunctionReturn(0);
1970 }
1971 
1972 #undef __FUNCT__
1973 #define __FUNCT__ "TSPostStep"
1974 /*@
1975   TSPostStep - Runs the user-defined post-step function.
1976 
1977   Collective on TS
1978 
1979   Input Parameters:
1980 . ts   - The TS context obtained from TSCreate()
1981 
1982   Notes:
1983   TSPostStep() is typically used within time stepping implementations,
1984   so most users would not generally call this routine themselves.
1985 
1986   Level: developer
1987 
1988 .keywords: TS, timestep
1989 @*/
1990 PetscErrorCode  TSPostStep(TS ts)
1991 {
1992   PetscErrorCode ierr;
1993 
1994   PetscFunctionBegin;
1995   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1996   if (ts->ops->poststep) {
1997     PetscStackPush("TS PostStep function");
1998     ierr = (*ts->ops->poststep)(ts);CHKERRQ(ierr);
1999     PetscStackPop;
2000   }
2001   PetscFunctionReturn(0);
2002 }
2003 
2004 /* ------------ Routines to set performance monitoring options ----------- */
2005 
2006 #undef __FUNCT__
2007 #define __FUNCT__ "TSMonitorSet"
2008 /*@C
2009    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
2010    timestep to display the iteration's  progress.
2011 
2012    Logically Collective on TS
2013 
2014    Input Parameters:
2015 +  ts - the TS context obtained from TSCreate()
2016 .  monitor - monitoring routine
2017 .  mctx - [optional] user-defined context for private data for the
2018              monitor routine (use PETSC_NULL if no context is desired)
2019 -  monitordestroy - [optional] routine that frees monitor context
2020           (may be PETSC_NULL)
2021 
2022    Calling sequence of monitor:
2023 $    int monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
2024 
2025 +    ts - the TS context
2026 .    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
2027                                been interpolated to)
2028 .    time - current time
2029 .    u - current iterate
2030 -    mctx - [optional] monitoring context
2031 
2032    Notes:
2033    This routine adds an additional monitor to the list of monitors that
2034    already has been loaded.
2035 
2036    Fortran notes: Only a single monitor function can be set for each TS object
2037 
2038    Level: intermediate
2039 
2040 .keywords: TS, timestep, set, monitor
2041 
2042 .seealso: TSMonitorDefault(), TSMonitorCancel()
2043 @*/
2044 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
2045 {
2046   PetscFunctionBegin;
2047   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2048   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
2049   ts->monitor[ts->numbermonitors]           = monitor;
2050   ts->monitordestroy[ts->numbermonitors]    = mdestroy;
2051   ts->monitorcontext[ts->numbermonitors++]  = (void*)mctx;
2052   PetscFunctionReturn(0);
2053 }
2054 
2055 #undef __FUNCT__
2056 #define __FUNCT__ "TSMonitorCancel"
2057 /*@C
2058    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
2059 
2060    Logically Collective on TS
2061 
2062    Input Parameters:
2063 .  ts - the TS context obtained from TSCreate()
2064 
2065    Notes:
2066    There is no way to remove a single, specific monitor.
2067 
2068    Level: intermediate
2069 
2070 .keywords: TS, timestep, set, monitor
2071 
2072 .seealso: TSMonitorDefault(), TSMonitorSet()
2073 @*/
2074 PetscErrorCode  TSMonitorCancel(TS ts)
2075 {
2076   PetscErrorCode ierr;
2077   PetscInt       i;
2078 
2079   PetscFunctionBegin;
2080   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2081   for (i=0; i<ts->numbermonitors; i++) {
2082     if (ts->monitordestroy[i]) {
2083       ierr = (*ts->monitordestroy[i])(&ts->monitorcontext[i]);CHKERRQ(ierr);
2084     }
2085   }
2086   ts->numbermonitors = 0;
2087   PetscFunctionReturn(0);
2088 }
2089 
2090 #undef __FUNCT__
2091 #define __FUNCT__ "TSMonitorDefault"
2092 /*@
2093    TSMonitorDefault - Sets the Default monitor
2094 
2095    Level: intermediate
2096 
2097 .keywords: TS, set, monitor
2098 
2099 .seealso: TSMonitorDefault(), TSMonitorSet()
2100 @*/
2101 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *dummy)
2102 {
2103   PetscErrorCode ierr;
2104   PetscViewer    viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)ts)->comm);
2105 
2106   PetscFunctionBegin;
2107   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2108   ierr = PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g\n",step,(double)ts->time_step,(double)ptime);CHKERRQ(ierr);
2109   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);CHKERRQ(ierr);
2110   PetscFunctionReturn(0);
2111 }
2112 
2113 #undef __FUNCT__
2114 #define __FUNCT__ "TSSetRetainStages"
2115 /*@
2116    TSSetRetainStages - Request that all stages in the upcoming step be stored so that interpolation will be available.
2117 
2118    Logically Collective on TS
2119 
2120    Input Argument:
2121 .  ts - time stepping context
2122 
2123    Output Argument:
2124 .  flg - PETSC_TRUE or PETSC_FALSE
2125 
2126    Level: intermediate
2127 
2128 .keywords: TS, set
2129 
2130 .seealso: TSInterpolate(), TSSetPostStep()
2131 @*/
2132 PetscErrorCode TSSetRetainStages(TS ts,PetscBool flg)
2133 {
2134   PetscFunctionBegin;
2135   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2136   ts->retain_stages = flg;
2137   PetscFunctionReturn(0);
2138 }
2139 
2140 #undef __FUNCT__
2141 #define __FUNCT__ "TSInterpolate"
2142 /*@
2143    TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
2144 
2145    Collective on TS
2146 
2147    Input Argument:
2148 +  ts - time stepping context
2149 -  t - time to interpolate to
2150 
2151    Output Argument:
2152 .  U - state at given time
2153 
2154    Notes:
2155    The user should call TSSetRetainStages() before taking a step in which interpolation will be requested.
2156 
2157    Level: intermediate
2158 
2159    Developer Notes:
2160    TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
2161 
2162 .keywords: TS, set
2163 
2164 .seealso: TSSetRetainStages(), TSSetPostStep()
2165 @*/
2166 PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
2167 {
2168   PetscErrorCode ierr;
2169 
2170   PetscFunctionBegin;
2171   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2172   if (t < ts->ptime - ts->time_step_prev || t > ts->ptime) SETERRQ3(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Requested time %G not in last time steps [%G,%G]",t,ts->ptime-ts->time_step_prev,ts->ptime);
2173   if (!ts->ops->interpolate) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
2174   ierr = (*ts->ops->interpolate)(ts,t,U);CHKERRQ(ierr);
2175   PetscFunctionReturn(0);
2176 }
2177 
2178 #undef __FUNCT__
2179 #define __FUNCT__ "TSStep"
2180 /*@
2181    TSStep - Steps one time step
2182 
2183    Collective on TS
2184 
2185    Input Parameter:
2186 .  ts - the TS context obtained from TSCreate()
2187 
2188    Level: intermediate
2189 
2190    Notes:
2191    The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
2192    be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
2193 
2194    This may over-step the final time provided in TSSetDuration() depending on the time-step used. TSSolve() interpolates to exactly the
2195    time provided in TSSetDuration(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
2196 
2197 .keywords: TS, timestep, solve
2198 
2199 .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
2200 @*/
2201 PetscErrorCode  TSStep(TS ts)
2202 {
2203   PetscReal      ptime_prev;
2204   PetscErrorCode ierr;
2205 
2206   PetscFunctionBegin;
2207   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
2208   ierr = TSSetUp(ts);CHKERRQ(ierr);
2209 
2210   ts->reason = TS_CONVERGED_ITERATING;
2211 
2212   ptime_prev = ts->ptime;
2213   ierr = PetscLogEventBegin(TS_Step,ts,0,0,0);CHKERRQ(ierr);
2214   ierr = (*ts->ops->step)(ts);CHKERRQ(ierr);
2215   ierr = PetscLogEventEnd(TS_Step,ts,0,0,0);CHKERRQ(ierr);
2216   ts->time_step_prev = ts->ptime - ptime_prev;
2217 
2218   if (ts->reason < 0) {
2219     if (ts->errorifstepfailed) {
2220       if (ts->reason == TS_DIVERGED_NONLINEAR_SOLVE) {
2221         SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s, increase -ts_max_snes_failures or make negative to attempt recovery",TSConvergedReasons[ts->reason]);
2222       } else SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
2223     }
2224   } else if (!ts->reason) {
2225     if (ts->steps >= ts->max_steps)
2226       ts->reason = TS_CONVERGED_ITS;
2227     else if (ts->ptime >= ts->max_time)
2228       ts->reason = TS_CONVERGED_TIME;
2229   }
2230 
2231   PetscFunctionReturn(0);
2232 }
2233 
2234 #undef __FUNCT__
2235 #define __FUNCT__ "TSEvaluateStep"
2236 /*@
2237    TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
2238 
2239    Collective on TS
2240 
2241    Input Arguments:
2242 +  ts - time stepping context
2243 .  order - desired order of accuracy
2244 -  done - whether the step was evaluated at this order (pass PETSC_NULL to generate an error if not available)
2245 
2246    Output Arguments:
2247 .  U - state at the end of the current step
2248 
2249    Level: advanced
2250 
2251    Notes:
2252    This function cannot be called until all stages have been evaluated.
2253    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.
2254 
2255 .seealso: TSStep(), TSAdapt
2256 @*/
2257 PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
2258 {
2259   PetscErrorCode ierr;
2260 
2261   PetscFunctionBegin;
2262   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2263   PetscValidType(ts,1);
2264   PetscValidHeaderSpecific(U,VEC_CLASSID,3);
2265   if (!ts->ops->evaluatestep) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
2266   ierr = (*ts->ops->evaluatestep)(ts,order,U,done);CHKERRQ(ierr);
2267   PetscFunctionReturn(0);
2268 }
2269 
2270 #undef __FUNCT__
2271 #define __FUNCT__ "TSSolve"
2272 /*@
2273    TSSolve - Steps the requested number of timesteps.
2274 
2275    Collective on TS
2276 
2277    Input Parameter:
2278 +  ts - the TS context obtained from TSCreate()
2279 -  u - the solution vector  (can be null if TSSetSolution() was used, otherwise must contain the initial conditions)
2280 
2281    Level: beginner
2282 
2283    Notes:
2284    The final time returned by this function may be different from the time of the internally
2285    held state accessible by TSGetSolution() and TSGetTime() because the method may have
2286    stepped over the final time.
2287 
2288 .keywords: TS, timestep, solve
2289 
2290 .seealso: TSCreate(), TSSetSolution(), TSStep()
2291 @*/
2292 PetscErrorCode TSSolve(TS ts,Vec u)
2293 {
2294   PetscBool      flg;
2295   char           filename[PETSC_MAX_PATH_LEN];
2296   PetscViewer    viewer;
2297   PetscErrorCode ierr;
2298 
2299   PetscFunctionBegin;
2300   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2301   PetscValidHeaderSpecific(u,VEC_CLASSID,2);
2302   if (ts->exact_final_time) {   /* Need ts->vec_sol to be distinct so it is not overwritten when we interpolate at the end */
2303     if (!ts->vec_sol || u == ts->vec_sol) {
2304       Vec y;
2305       ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
2306       ierr = TSSetSolution(ts,y);CHKERRQ(ierr);
2307       ierr = VecDestroy(&y);CHKERRQ(ierr); /* grant ownership */
2308     }
2309     ierr = VecCopy(u,ts->vec_sol);CHKERRQ(ierr);
2310   } else {
2311     ierr = TSSetSolution(ts,u);CHKERRQ(ierr);
2312   }
2313   ierr = TSSetUp(ts);CHKERRQ(ierr);
2314   /* reset time step and iteration counters */
2315   ts->steps = 0;
2316   ts->ksp_its = 0;
2317   ts->snes_its = 0;
2318   ts->num_snes_failures = 0;
2319   ts->reject = 0;
2320   ts->reason = TS_CONVERGED_ITERATING;
2321 
2322   if (ts->ops->solve) {         /* This private interface is transitional and should be removed when all implementations are updated. */
2323     ierr = (*ts->ops->solve)(ts);CHKERRQ(ierr);
2324     ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);
2325     ts->solvetime = ts->ptime;
2326   } else {
2327     /* steps the requested number of timesteps. */
2328     ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
2329     if (ts->steps >= ts->max_steps)
2330       ts->reason = TS_CONVERGED_ITS;
2331     else if (ts->ptime >= ts->max_time)
2332       ts->reason = TS_CONVERGED_TIME;
2333     while (!ts->reason) {
2334       ierr = TSStep(ts);CHKERRQ(ierr);
2335       ierr = TSPostStep(ts);CHKERRQ(ierr);
2336       ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
2337     }
2338     if (ts->exact_final_time && ts->ptime > ts->max_time) {
2339       ierr = TSInterpolate(ts,ts->max_time,u);CHKERRQ(ierr);
2340       ts->solvetime = ts->max_time;
2341     } else {
2342       ierr = VecCopy(ts->vec_sol,u);CHKERRQ(ierr);
2343       ts->solvetime = ts->ptime;
2344     }
2345   }
2346   ierr = TSMonitor(ts,-1,ts->ptime,ts->vec_sol);CHKERRQ(ierr);
2347   ierr = PetscOptionsGetString(((PetscObject)ts)->prefix,"-ts_view",filename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
2348   if (flg && !PetscPreLoadingOn) {
2349     ierr = PetscViewerASCIIOpen(((PetscObject)ts)->comm,filename,&viewer);CHKERRQ(ierr);
2350     ierr = TSView(ts,viewer);CHKERRQ(ierr);
2351     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2352   }
2353   PetscFunctionReturn(0);
2354 }
2355 
2356 #undef __FUNCT__
2357 #define __FUNCT__ "TSMonitor"
2358 /*@
2359    TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
2360 
2361    Collective on TS
2362 
2363    Input Parameters:
2364 +  ts - time stepping context obtained from TSCreate()
2365 .  step - step number that has just completed
2366 .  ptime - model time of the state
2367 -  u - state at the current model time
2368 
2369    Notes:
2370    TSMonitor() is typically used within the time stepping implementations.
2371    Users might call this function when using the TSStep() interface instead of TSSolve().
2372 
2373    Level: advanced
2374 
2375 .keywords: TS, timestep
2376 @*/
2377 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
2378 {
2379   PetscErrorCode ierr;
2380   PetscInt       i,n = ts->numbermonitors;
2381 
2382   PetscFunctionBegin;
2383   for (i=0; i<n; i++) {
2384     ierr = (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);CHKERRQ(ierr);
2385   }
2386   PetscFunctionReturn(0);
2387 }
2388 
2389 /* ------------------------------------------------------------------------*/
2390 struct _n_TSMonitorLGCtx {
2391   PetscDrawLG lg;
2392   PetscInt    howoften;  /* when > 0 uses step % howoften, when negative only final solution plotted */
2393   PetscInt    ksp_its,snes_its;
2394 };
2395 
2396 
2397 #undef __FUNCT__
2398 #define __FUNCT__ "TSMonitorLGCtxCreate"
2399 /*@C
2400    TSMonitorLGCtxCreate - Creates a line graph context for use with
2401    TS to monitor the solution process graphically in various ways
2402 
2403    Collective on TS
2404 
2405    Input Parameters:
2406 +  host - the X display to open, or null for the local machine
2407 .  label - the title to put in the title bar
2408 .  x, y - the screen coordinates of the upper left coordinate of the window
2409 .  m, n - the screen width and height in pixels
2410 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
2411 
2412    Output Parameter:
2413 .  ctx - the context
2414 
2415    Options Database Key:
2416 +  -ts_monitor_lg_timestep - automatically sets line graph monitor
2417 .  -ts_monitor_lg_solution -
2418 .  -ts_monitor_lg_error -
2419 .  -ts_monitor_lg_ksp_iterations -
2420 .  -ts_monitor_lg_snes_iterations -
2421 -  -lg_indicate_data_points <true,false> - indicate the data points (at each time step) on the plot; default is true
2422 
2423    Notes:
2424    Use TSMonitorLGCtxDestroy() to destroy.
2425 
2426    Level: intermediate
2427 
2428 .keywords: TS, monitor, line graph, residual, seealso
2429 
2430 .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
2431 
2432 @*/
2433 PetscErrorCode  TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
2434 {
2435   PetscDraw      win;
2436   PetscErrorCode ierr;
2437   PetscBool      flg = PETSC_TRUE;
2438 
2439   PetscFunctionBegin;
2440   ierr = PetscNew(struct _n_TSMonitorLGCtx,ctx);CHKERRQ(ierr);
2441   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&win);CHKERRQ(ierr);
2442   ierr = PetscDrawSetFromOptions(win);CHKERRQ(ierr);
2443   ierr = PetscDrawLGCreate(win,1,&(*ctx)->lg);CHKERRQ(ierr);
2444   ierr = PetscOptionsGetBool(PETSC_NULL,"-lg_indicate_data_points",&flg,PETSC_NULL);CHKERRQ(ierr);
2445   if (flg) {
2446     ierr = PetscDrawLGIndicateDataPoints((*ctx)->lg);CHKERRQ(ierr);
2447   }
2448   ierr = PetscLogObjectParent((*ctx)->lg,win);CHKERRQ(ierr);
2449   (*ctx)->howoften = howoften;
2450   PetscFunctionReturn(0);
2451 }
2452 
2453 #undef __FUNCT__
2454 #define __FUNCT__ "TSMonitorLGTimeStep"
2455 PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
2456 {
2457   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
2458   PetscReal      x = ptime,y;
2459   PetscErrorCode ierr;
2460 
2461   PetscFunctionBegin;
2462   if (!n) {
2463     PetscDrawAxis  axis;
2464     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
2465     ierr = PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time","Time step");CHKERRQ(ierr);
2466     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
2467   }
2468   ierr = TSGetTimeStep(ts,&y);CHKERRQ(ierr);
2469   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
2470   if (((ctx->howoften > 0) && (!(n % ctx->howoften))) || ((ctx->howoften == -1) && (n == -1))){
2471     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
2472   }
2473   PetscFunctionReturn(0);
2474 }
2475 
2476 #undef __FUNCT__
2477 #define __FUNCT__ "TSMonitorLGCtxDestroy"
2478 /*@C
2479    TSMonitorLGCtxDestroy - Destroys a line graph context that was created
2480    with TSMonitorLGCtxCreate().
2481 
2482    Collective on TSMonitorLGCtx
2483 
2484    Input Parameter:
2485 .  ctx - the monitor context
2486 
2487    Level: intermediate
2488 
2489 .keywords: TS, monitor, line graph, destroy
2490 
2491 .seealso: TSMonitorLGCtxCreate(),  TSMonitorSet(), TSMonitorLGTimeStep();
2492 @*/
2493 PetscErrorCode  TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
2494 {
2495   PetscDraw      draw;
2496   PetscErrorCode ierr;
2497 
2498   PetscFunctionBegin;
2499   ierr = PetscDrawLGGetDraw((*ctx)->lg,&draw);CHKERRQ(ierr);
2500   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
2501   ierr = PetscDrawLGDestroy(&(*ctx)->lg);CHKERRQ(ierr);
2502   ierr = PetscFree(*ctx);CHKERRQ(ierr);
2503   PetscFunctionReturn(0);
2504 }
2505 
2506 #undef __FUNCT__
2507 #define __FUNCT__ "TSGetTime"
2508 /*@
2509    TSGetTime - Gets the time of the most recently completed step.
2510 
2511    Not Collective
2512 
2513    Input Parameter:
2514 .  ts - the TS context obtained from TSCreate()
2515 
2516    Output Parameter:
2517 .  t  - the current time
2518 
2519    Level: beginner
2520 
2521    Note:
2522    When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
2523    TSSetPreStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
2524 
2525 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
2526 
2527 .keywords: TS, get, time
2528 @*/
2529 PetscErrorCode  TSGetTime(TS ts,PetscReal* t)
2530 {
2531   PetscFunctionBegin;
2532   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2533   PetscValidRealPointer(t,2);
2534   *t = ts->ptime;
2535   PetscFunctionReturn(0);
2536 }
2537 
2538 #undef __FUNCT__
2539 #define __FUNCT__ "TSSetTime"
2540 /*@
2541    TSSetTime - Allows one to reset the time.
2542 
2543    Logically Collective on TS
2544 
2545    Input Parameters:
2546 +  ts - the TS context obtained from TSCreate()
2547 -  time - the time
2548 
2549    Level: intermediate
2550 
2551 .seealso: TSGetTime(), TSSetDuration()
2552 
2553 .keywords: TS, set, time
2554 @*/
2555 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
2556 {
2557   PetscFunctionBegin;
2558   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2559   PetscValidLogicalCollectiveReal(ts,t,2);
2560   ts->ptime = t;
2561   PetscFunctionReturn(0);
2562 }
2563 
2564 #undef __FUNCT__
2565 #define __FUNCT__ "TSSetOptionsPrefix"
2566 /*@C
2567    TSSetOptionsPrefix - Sets the prefix used for searching for all
2568    TS options in the database.
2569 
2570    Logically Collective on TS
2571 
2572    Input Parameter:
2573 +  ts     - The TS context
2574 -  prefix - The prefix to prepend to all option names
2575 
2576    Notes:
2577    A hyphen (-) must NOT be given at the beginning of the prefix name.
2578    The first character of all runtime options is AUTOMATICALLY the
2579    hyphen.
2580 
2581    Level: advanced
2582 
2583 .keywords: TS, set, options, prefix, database
2584 
2585 .seealso: TSSetFromOptions()
2586 
2587 @*/
2588 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
2589 {
2590   PetscErrorCode ierr;
2591   SNES           snes;
2592 
2593   PetscFunctionBegin;
2594   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2595   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2596   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2597   ierr = SNESSetOptionsPrefix(snes,prefix);CHKERRQ(ierr);
2598   PetscFunctionReturn(0);
2599 }
2600 
2601 
2602 #undef __FUNCT__
2603 #define __FUNCT__ "TSAppendOptionsPrefix"
2604 /*@C
2605    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
2606    TS options in the database.
2607 
2608    Logically Collective on TS
2609 
2610    Input Parameter:
2611 +  ts     - The TS context
2612 -  prefix - The prefix to prepend to all option names
2613 
2614    Notes:
2615    A hyphen (-) must NOT be given at the beginning of the prefix name.
2616    The first character of all runtime options is AUTOMATICALLY the
2617    hyphen.
2618 
2619    Level: advanced
2620 
2621 .keywords: TS, append, options, prefix, database
2622 
2623 .seealso: TSGetOptionsPrefix()
2624 
2625 @*/
2626 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
2627 {
2628   PetscErrorCode ierr;
2629   SNES           snes;
2630 
2631   PetscFunctionBegin;
2632   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2633   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2634   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2635   ierr = SNESAppendOptionsPrefix(snes,prefix);CHKERRQ(ierr);
2636   PetscFunctionReturn(0);
2637 }
2638 
2639 #undef __FUNCT__
2640 #define __FUNCT__ "TSGetOptionsPrefix"
2641 /*@C
2642    TSGetOptionsPrefix - Sets the prefix used for searching for all
2643    TS options in the database.
2644 
2645    Not Collective
2646 
2647    Input Parameter:
2648 .  ts - The TS context
2649 
2650    Output Parameter:
2651 .  prefix - A pointer to the prefix string used
2652 
2653    Notes: On the fortran side, the user should pass in a string 'prifix' of
2654    sufficient length to hold the prefix.
2655 
2656    Level: intermediate
2657 
2658 .keywords: TS, get, options, prefix, database
2659 
2660 .seealso: TSAppendOptionsPrefix()
2661 @*/
2662 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
2663 {
2664   PetscErrorCode ierr;
2665 
2666   PetscFunctionBegin;
2667   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2668   PetscValidPointer(prefix,2);
2669   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2670   PetscFunctionReturn(0);
2671 }
2672 
2673 #undef __FUNCT__
2674 #define __FUNCT__ "TSGetRHSJacobian"
2675 /*@C
2676    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
2677 
2678    Not Collective, but parallel objects are returned if TS is parallel
2679 
2680    Input Parameter:
2681 .  ts  - The TS context obtained from TSCreate()
2682 
2683    Output Parameters:
2684 +  J   - The Jacobian J of F, where U_t = G(U,t)
2685 .  M   - The preconditioner matrix, usually the same as J
2686 .  func - Function to compute the Jacobian of the RHS
2687 -  ctx - User-defined context for Jacobian evaluation routine
2688 
2689    Notes: You can pass in PETSC_NULL for any return argument you do not need.
2690 
2691    Level: intermediate
2692 
2693 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
2694 
2695 .keywords: TS, timestep, get, matrix, Jacobian
2696 @*/
2697 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *J,Mat *M,TSRHSJacobian *func,void **ctx)
2698 {
2699   PetscErrorCode ierr;
2700   SNES           snes;
2701   DM             dm;
2702 
2703   PetscFunctionBegin;
2704   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2705   ierr = SNESGetJacobian(snes,J,M,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
2706   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2707   ierr = DMTSGetRHSJacobian(dm,func,ctx);CHKERRQ(ierr);
2708   PetscFunctionReturn(0);
2709 }
2710 
2711 #undef __FUNCT__
2712 #define __FUNCT__ "TSGetIJacobian"
2713 /*@C
2714    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
2715 
2716    Not Collective, but parallel objects are returned if TS is parallel
2717 
2718    Input Parameter:
2719 .  ts  - The TS context obtained from TSCreate()
2720 
2721    Output Parameters:
2722 +  A   - The Jacobian of F(t,U,U_t)
2723 .  B   - The preconditioner matrix, often the same as A
2724 .  f   - The function to compute the matrices
2725 - ctx - User-defined context for Jacobian evaluation routine
2726 
2727    Notes: You can pass in PETSC_NULL for any return argument you do not need.
2728 
2729    Level: advanced
2730 
2731 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
2732 
2733 .keywords: TS, timestep, get, matrix, Jacobian
2734 @*/
2735 PetscErrorCode  TSGetIJacobian(TS ts,Mat *A,Mat *B,TSIJacobian *f,void **ctx)
2736 {
2737   PetscErrorCode ierr;
2738   SNES           snes;
2739   DM             dm;
2740 
2741   PetscFunctionBegin;
2742   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2743   ierr = SNESGetJacobian(snes,A,B,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
2744   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
2745   ierr = DMTSGetIJacobian(dm,f,ctx);CHKERRQ(ierr);
2746   PetscFunctionReturn(0);
2747 }
2748 
2749 struct _n_TSMonitorDrawCtx {
2750   PetscViewer viewer;
2751   Vec         initialsolution;
2752   PetscBool   showinitial;
2753   PetscInt    howoften;  /* when > 0 uses step % howoften, when negative only final solution plotted */
2754 };
2755 
2756 #undef __FUNCT__
2757 #define __FUNCT__ "TSMonitorDrawSolution"
2758 /*@C
2759    TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
2760    VecView() for the solution at each timestep
2761 
2762    Collective on TS
2763 
2764    Input Parameters:
2765 +  ts - the TS context
2766 .  step - current time-step
2767 .  ptime - current time
2768 -  dummy - either a viewer or PETSC_NULL
2769 
2770    Options Database:
2771 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
2772 
2773    Notes: the initial solution and current solution are not displayed with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
2774        will look bad
2775 
2776    Level: intermediate
2777 
2778 .keywords: TS,  vector, monitor, view
2779 
2780 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
2781 @*/
2782 PetscErrorCode  TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
2783 {
2784   PetscErrorCode   ierr;
2785   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
2786 
2787   PetscFunctionBegin;
2788   if (!step && ictx->showinitial) {
2789     if (!ictx->initialsolution) {
2790       ierr = VecDuplicate(u,&ictx->initialsolution);CHKERRQ(ierr);
2791     }
2792     ierr = VecCopy(u,ictx->initialsolution);CHKERRQ(ierr);
2793   }
2794   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften)) && (step > -1)) || ((ictx->howoften == -1) && (step == -1)))) PetscFunctionReturn(0);
2795 
2796   if (ictx->showinitial) {
2797     PetscReal pause;
2798     ierr = PetscViewerDrawGetPause(ictx->viewer,&pause);CHKERRQ(ierr);
2799     ierr = PetscViewerDrawSetPause(ictx->viewer,0.0);CHKERRQ(ierr);
2800     ierr = VecView(ictx->initialsolution,ictx->viewer);CHKERRQ(ierr);
2801     ierr = PetscViewerDrawSetPause(ictx->viewer,pause);CHKERRQ(ierr);
2802     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);CHKERRQ(ierr);
2803   }
2804   ierr = VecView(u,ictx->viewer);CHKERRQ(ierr);
2805   if (ictx->showinitial) {
2806     ierr = PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);CHKERRQ(ierr);
2807   }
2808   PetscFunctionReturn(0);
2809 }
2810 
2811 
2812 #undef __FUNCT__
2813 #define __FUNCT__ "TSMonitorDrawCtxDestroy"
2814 /*@C
2815    TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
2816 
2817    Collective on TS
2818 
2819    Input Parameters:
2820 .    ctx - the monitor context
2821 
2822    Level: intermediate
2823 
2824 .keywords: TS,  vector, monitor, view
2825 
2826 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
2827 @*/
2828 PetscErrorCode  TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
2829 {
2830   PetscErrorCode       ierr;
2831 
2832   PetscFunctionBegin;
2833   ierr = PetscViewerDestroy(&(*ictx)->viewer);CHKERRQ(ierr);
2834   ierr = VecDestroy(&(*ictx)->initialsolution);CHKERRQ(ierr);
2835   ierr = PetscFree(*ictx);CHKERRQ(ierr);
2836   PetscFunctionReturn(0);
2837 }
2838 
2839 #undef __FUNCT__
2840 #define __FUNCT__ "TSMonitorDrawCtxCreate"
2841 /*@C
2842    TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
2843 
2844    Collective on TS
2845 
2846    Input Parameter:
2847 .    ts - time-step context
2848 
2849    Output Patameter:
2850 .    ctx - the monitor context
2851 
2852    Options Database:
2853 .   -ts_monitor_draw_solution_initial - show initial solution as well as current solution
2854 
2855    Level: intermediate
2856 
2857 .keywords: TS,  vector, monitor, view
2858 
2859 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
2860 @*/
2861 PetscErrorCode  TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
2862 {
2863   PetscErrorCode   ierr;
2864 
2865   PetscFunctionBegin;
2866   ierr = PetscNew(struct _n_TSMonitorDrawCtx,ctx);CHKERRQ(ierr);
2867   ierr = PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);CHKERRQ(ierr);
2868   (*ctx)->showinitial = PETSC_FALSE;
2869   (*ctx)->howoften    = howoften;
2870   ierr = PetscOptionsGetBool(PETSC_NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,PETSC_NULL);CHKERRQ(ierr);
2871   PetscFunctionReturn(0);
2872 }
2873 
2874 #undef __FUNCT__
2875 #define __FUNCT__ "TSMonitorDrawError"
2876 /*@C
2877    TSMonitorDrawError - Monitors progress of the TS solvers by calling
2878    VecView() for the error at each timestep
2879 
2880    Collective on TS
2881 
2882    Input Parameters:
2883 +  ts - the TS context
2884 .  step - current time-step
2885 .  ptime - current time
2886 -  dummy - either a viewer or PETSC_NULL
2887 
2888    Level: intermediate
2889 
2890 .keywords: TS,  vector, monitor, view
2891 
2892 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
2893 @*/
2894 PetscErrorCode  TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
2895 {
2896   PetscErrorCode   ierr;
2897   TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)dummy;
2898   PetscViewer      viewer = ctx->viewer;
2899   Vec              work;
2900 
2901   PetscFunctionBegin;
2902   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften)) && (step > -1)) || ((ctx->howoften == -1) && (step == -1)))) PetscFunctionReturn(0);
2903   ierr = VecDuplicate(u,&work);CHKERRQ(ierr);
2904   ierr = TSComputeSolutionFunction(ts,ptime,work);CHKERRQ(ierr);
2905   ierr = VecAXPY(work,-1.0,u);CHKERRQ(ierr);
2906   ierr = VecView(work,viewer);CHKERRQ(ierr);
2907   ierr = VecDestroy(&work);CHKERRQ(ierr);
2908   PetscFunctionReturn(0);
2909 }
2910 
2911 #undef __FUNCT__
2912 #define __FUNCT__ "TSSetDM"
2913 /*@
2914    TSSetDM - Sets the DM that may be used by some preconditioners
2915 
2916    Logically Collective on TS and DM
2917 
2918    Input Parameters:
2919 +  ts - the preconditioner context
2920 -  dm - the dm
2921 
2922    Level: intermediate
2923 
2924 
2925 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
2926 @*/
2927 PetscErrorCode  TSSetDM(TS ts,DM dm)
2928 {
2929   PetscErrorCode ierr;
2930   SNES           snes;
2931   TSDM           tsdm;
2932 
2933   PetscFunctionBegin;
2934   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2935   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
2936   if (ts->dm) {               /* Move the TSDM context over to the new DM unless the new DM already has one */
2937     PetscContainer oldcontainer,container;
2938     ierr = PetscObjectQuery((PetscObject)ts->dm,"TSDM",(PetscObject*)&oldcontainer);CHKERRQ(ierr);
2939     ierr = PetscObjectQuery((PetscObject)dm,"TSDM",(PetscObject*)&container);CHKERRQ(ierr);
2940     if (oldcontainer && !container) {
2941       ierr = DMTSCopyContext(ts->dm,dm);CHKERRQ(ierr);
2942       ierr = DMTSGetContext(ts->dm,&tsdm);CHKERRQ(ierr);
2943       if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
2944         tsdm->originaldm = dm;
2945       }
2946     }
2947     ierr = DMDestroy(&ts->dm);CHKERRQ(ierr);
2948   }
2949   ts->dm = dm;
2950   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
2951   ierr = SNESSetDM(snes,dm);CHKERRQ(ierr);
2952   PetscFunctionReturn(0);
2953 }
2954 
2955 #undef __FUNCT__
2956 #define __FUNCT__ "TSGetDM"
2957 /*@
2958    TSGetDM - Gets the DM that may be used by some preconditioners
2959 
2960    Not Collective
2961 
2962    Input Parameter:
2963 . ts - the preconditioner context
2964 
2965    Output Parameter:
2966 .  dm - the dm
2967 
2968    Level: intermediate
2969 
2970 
2971 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
2972 @*/
2973 PetscErrorCode  TSGetDM(TS ts,DM *dm)
2974 {
2975   PetscErrorCode ierr;
2976 
2977   PetscFunctionBegin;
2978   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2979   if (!ts->dm) {
2980     ierr = DMShellCreate(((PetscObject)ts)->comm,&ts->dm);CHKERRQ(ierr);
2981     if (ts->snes) {ierr = SNESSetDM(ts->snes,ts->dm);CHKERRQ(ierr);}
2982   }
2983   *dm = ts->dm;
2984   PetscFunctionReturn(0);
2985 }
2986 
2987 #undef __FUNCT__
2988 #define __FUNCT__ "SNESTSFormFunction"
2989 /*@
2990    SNESTSFormFunction - Function to evaluate nonlinear residual
2991 
2992    Logically Collective on SNES
2993 
2994    Input Parameter:
2995 + snes - nonlinear solver
2996 . U - the current state at which to evaluate the residual
2997 - ctx - user context, must be a TS
2998 
2999    Output Parameter:
3000 . F - the nonlinear residual
3001 
3002    Notes:
3003    This function is not normally called by users and is automatically registered with the SNES used by TS.
3004    It is most frequently passed to MatFDColoringSetFunction().
3005 
3006    Level: advanced
3007 
3008 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
3009 @*/
3010 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
3011 {
3012   TS             ts = (TS)ctx;
3013   PetscErrorCode ierr;
3014 
3015   PetscFunctionBegin;
3016   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3017   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
3018   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
3019   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
3020   ierr = (ts->ops->snesfunction)(snes,U,F,ts);CHKERRQ(ierr);
3021   PetscFunctionReturn(0);
3022 }
3023 
3024 #undef __FUNCT__
3025 #define __FUNCT__ "SNESTSFormJacobian"
3026 /*@
3027    SNESTSFormJacobian - Function to evaluate the Jacobian
3028 
3029    Collective on SNES
3030 
3031    Input Parameter:
3032 + snes - nonlinear solver
3033 . U - the current state at which to evaluate the residual
3034 - ctx - user context, must be a TS
3035 
3036    Output Parameter:
3037 + A - the Jacobian
3038 . B - the preconditioning matrix (may be the same as A)
3039 - flag - indicates any structure change in the matrix
3040 
3041    Notes:
3042    This function is not normally called by users and is automatically registered with the SNES used by TS.
3043 
3044    Level: developer
3045 
3046 .seealso: SNESSetJacobian()
3047 @*/
3048 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec U,Mat *A,Mat *B,MatStructure *flag,void *ctx)
3049 {
3050   TS             ts = (TS)ctx;
3051   PetscErrorCode ierr;
3052 
3053   PetscFunctionBegin;
3054   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3055   PetscValidHeaderSpecific(U,VEC_CLASSID,2);
3056   PetscValidPointer(A,3);
3057   PetscValidHeaderSpecific(*A,MAT_CLASSID,3);
3058   PetscValidPointer(B,4);
3059   PetscValidHeaderSpecific(*B,MAT_CLASSID,4);
3060   PetscValidPointer(flag,5);
3061   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
3062   ierr = (ts->ops->snesjacobian)(snes,U,A,B,flag,ts);CHKERRQ(ierr);
3063   PetscFunctionReturn(0);
3064 }
3065 
3066 #undef __FUNCT__
3067 #define __FUNCT__ "TSComputeRHSFunctionLinear"
3068 /*@C
3069    TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems only
3070 
3071    Collective on TS
3072 
3073    Input Arguments:
3074 +  ts - time stepping context
3075 .  t - time at which to evaluate
3076 .  U - state at which to evaluate
3077 -  ctx - context
3078 
3079    Output Arguments:
3080 .  F - right hand side
3081 
3082    Level: intermediate
3083 
3084    Notes:
3085    This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
3086    The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
3087 
3088 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
3089 @*/
3090 PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
3091 {
3092   PetscErrorCode ierr;
3093   Mat            Arhs,Brhs;
3094   MatStructure   flg2;
3095 
3096   PetscFunctionBegin;
3097   ierr = TSGetRHSMats_Private(ts,&Arhs,&Brhs);CHKERRQ(ierr);
3098   ierr = TSComputeRHSJacobian(ts,t,U,&Arhs,&Brhs,&flg2);CHKERRQ(ierr);
3099   ierr = MatMult(Arhs,U,F);CHKERRQ(ierr);
3100   PetscFunctionReturn(0);
3101 }
3102 
3103 #undef __FUNCT__
3104 #define __FUNCT__ "TSComputeRHSJacobianConstant"
3105 /*@C
3106    TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
3107 
3108    Collective on TS
3109 
3110    Input Arguments:
3111 +  ts - time stepping context
3112 .  t - time at which to evaluate
3113 .  U - state at which to evaluate
3114 -  ctx - context
3115 
3116    Output Arguments:
3117 +  A - pointer to operator
3118 .  B - pointer to preconditioning matrix
3119 -  flg - matrix structure flag
3120 
3121    Level: intermediate
3122 
3123    Notes:
3124    This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
3125 
3126 .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
3127 @*/
3128 PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat *A,Mat *B,MatStructure *flg,void *ctx)
3129 {
3130   PetscFunctionBegin;
3131   *flg = SAME_PRECONDITIONER;
3132   PetscFunctionReturn(0);
3133 }
3134 
3135 #undef __FUNCT__
3136 #define __FUNCT__ "TSComputeIFunctionLinear"
3137 /*@C
3138    TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
3139 
3140    Collective on TS
3141 
3142    Input Arguments:
3143 +  ts - time stepping context
3144 .  t - time at which to evaluate
3145 .  U - state at which to evaluate
3146 .  Udot - time derivative of state vector
3147 -  ctx - context
3148 
3149    Output Arguments:
3150 .  F - left hand side
3151 
3152    Level: intermediate
3153 
3154    Notes:
3155    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
3156    user is required to write their own TSComputeIFunction.
3157    This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
3158    The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
3159 
3160 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant()
3161 @*/
3162 PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
3163 {
3164   PetscErrorCode ierr;
3165   Mat            A,B;
3166   MatStructure   flg2;
3167 
3168   PetscFunctionBegin;
3169   ierr = TSGetIJacobian(ts,&A,&B,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
3170   ierr = TSComputeIJacobian(ts,t,U,Udot,1.0,&A,&B,&flg2,PETSC_TRUE);CHKERRQ(ierr);
3171   ierr = MatMult(A,Udot,F);CHKERRQ(ierr);
3172   PetscFunctionReturn(0);
3173 }
3174 
3175 #undef __FUNCT__
3176 #define __FUNCT__ "TSComputeIJacobianConstant"
3177 /*@C
3178    TSComputeIJacobianConstant - Reuses a Jacobian that is time-independent.
3179 
3180    Collective on TS
3181 
3182    Input Arguments:
3183 +  ts - time stepping context
3184 .  t - time at which to evaluate
3185 .  U - state at which to evaluate
3186 .  Udot - time derivative of state vector
3187 .  shift - shift to apply
3188 -  ctx - context
3189 
3190    Output Arguments:
3191 +  A - pointer to operator
3192 .  B - pointer to preconditioning matrix
3193 -  flg - matrix structure flag
3194 
3195    Level: intermediate
3196 
3197    Notes:
3198    This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
3199 
3200 .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
3201 @*/
3202 PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat *A,Mat *B,MatStructure *flg,void *ctx)
3203 {
3204   PetscFunctionBegin;
3205   *flg = SAME_PRECONDITIONER;
3206   PetscFunctionReturn(0);
3207 }
3208 
3209 #undef __FUNCT__
3210 #define __FUNCT__ "TSGetConvergedReason"
3211 /*@
3212    TSGetConvergedReason - Gets the reason the TS iteration was stopped.
3213 
3214    Not Collective
3215 
3216    Input Parameter:
3217 .  ts - the TS context
3218 
3219    Output Parameter:
3220 .  reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
3221             manual pages for the individual convergence tests for complete lists
3222 
3223    Level: beginner
3224 
3225    Notes:
3226    Can only be called after the call to TSSolve() is complete.
3227 
3228 .keywords: TS, nonlinear, set, convergence, test
3229 
3230 .seealso: TSSetConvergenceTest(), TSConvergedReason
3231 @*/
3232 PetscErrorCode  TSGetConvergedReason(TS ts,TSConvergedReason *reason)
3233 {
3234   PetscFunctionBegin;
3235   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3236   PetscValidPointer(reason,2);
3237   *reason = ts->reason;
3238   PetscFunctionReturn(0);
3239 }
3240 
3241 #undef __FUNCT__
3242 #define __FUNCT__ "TSGetSolveTime"
3243 /*@
3244    TSGetSolveTime - Gets the time after a call to TSSolve()
3245 
3246    Not Collective
3247 
3248    Input Parameter:
3249 .  ts - the TS context
3250 
3251    Output Parameter:
3252 .  ftime - the final time. This time should correspond to the final time set with TSSetDuration()
3253 
3254    Level: beginner
3255 
3256    Notes:
3257    Can only be called after the call to TSSolve() is complete.
3258 
3259 .keywords: TS, nonlinear, set, convergence, test
3260 
3261 .seealso: TSSetConvergenceTest(), TSConvergedReason
3262 @*/
3263 PetscErrorCode  TSGetSolveTime(TS ts,PetscReal *ftime)
3264 {
3265   PetscFunctionBegin;
3266   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3267   PetscValidPointer(ftime,2);
3268   *ftime = ts->solvetime;
3269   PetscFunctionReturn(0);
3270 }
3271 
3272 #undef __FUNCT__
3273 #define __FUNCT__ "TSGetSNESIterations"
3274 /*@
3275    TSGetSNESIterations - Gets the total number of nonlinear iterations
3276    used by the time integrator.
3277 
3278    Not Collective
3279 
3280    Input Parameter:
3281 .  ts - TS context
3282 
3283    Output Parameter:
3284 .  nits - number of nonlinear iterations
3285 
3286    Notes:
3287    This counter is reset to zero for each successive call to TSSolve().
3288 
3289    Level: intermediate
3290 
3291 .keywords: TS, get, number, nonlinear, iterations
3292 
3293 .seealso:  TSGetKSPIterations()
3294 @*/
3295 PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
3296 {
3297   PetscFunctionBegin;
3298   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3299   PetscValidIntPointer(nits,2);
3300   *nits = ts->snes_its;
3301   PetscFunctionReturn(0);
3302 }
3303 
3304 #undef __FUNCT__
3305 #define __FUNCT__ "TSGetKSPIterations"
3306 /*@
3307    TSGetKSPIterations - Gets the total number of linear iterations
3308    used by the time integrator.
3309 
3310    Not Collective
3311 
3312    Input Parameter:
3313 .  ts - TS context
3314 
3315    Output Parameter:
3316 .  lits - number of linear iterations
3317 
3318    Notes:
3319    This counter is reset to zero for each successive call to TSSolve().
3320 
3321    Level: intermediate
3322 
3323 .keywords: TS, get, number, linear, iterations
3324 
3325 .seealso:  TSGetSNESIterations(), SNESGetKSPIterations()
3326 @*/
3327 PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
3328 {
3329   PetscFunctionBegin;
3330   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3331   PetscValidIntPointer(lits,2);
3332   *lits = ts->ksp_its;
3333   PetscFunctionReturn(0);
3334 }
3335 
3336 #undef __FUNCT__
3337 #define __FUNCT__ "TSGetStepRejections"
3338 /*@
3339    TSGetStepRejections - Gets the total number of rejected steps.
3340 
3341    Not Collective
3342 
3343    Input Parameter:
3344 .  ts - TS context
3345 
3346    Output Parameter:
3347 .  rejects - number of steps rejected
3348 
3349    Notes:
3350    This counter is reset to zero for each successive call to TSSolve().
3351 
3352    Level: intermediate
3353 
3354 .keywords: TS, get, number
3355 
3356 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
3357 @*/
3358 PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
3359 {
3360   PetscFunctionBegin;
3361   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3362   PetscValidIntPointer(rejects,2);
3363   *rejects = ts->reject;
3364   PetscFunctionReturn(0);
3365 }
3366 
3367 #undef __FUNCT__
3368 #define __FUNCT__ "TSGetSNESFailures"
3369 /*@
3370    TSGetSNESFailures - Gets the total number of failed SNES solves
3371 
3372    Not Collective
3373 
3374    Input Parameter:
3375 .  ts - TS context
3376 
3377    Output Parameter:
3378 .  fails - number of failed nonlinear solves
3379 
3380    Notes:
3381    This counter is reset to zero for each successive call to TSSolve().
3382 
3383    Level: intermediate
3384 
3385 .keywords: TS, get, number
3386 
3387 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
3388 @*/
3389 PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
3390 {
3391   PetscFunctionBegin;
3392   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3393   PetscValidIntPointer(fails,2);
3394   *fails = ts->num_snes_failures;
3395   PetscFunctionReturn(0);
3396 }
3397 
3398 #undef __FUNCT__
3399 #define __FUNCT__ "TSSetMaxStepRejections"
3400 /*@
3401    TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
3402 
3403    Not Collective
3404 
3405    Input Parameter:
3406 +  ts - TS context
3407 -  rejects - maximum number of rejected steps, pass -1 for unlimited
3408 
3409    Notes:
3410    The counter is reset to zero for each step
3411 
3412    Options Database Key:
3413  .  -ts_max_reject - Maximum number of step rejections before a step fails
3414 
3415    Level: intermediate
3416 
3417 .keywords: TS, set, maximum, number
3418 
3419 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
3420 @*/
3421 PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
3422 {
3423   PetscFunctionBegin;
3424   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3425   ts->max_reject = rejects;
3426   PetscFunctionReturn(0);
3427 }
3428 
3429 #undef __FUNCT__
3430 #define __FUNCT__ "TSSetMaxSNESFailures"
3431 /*@
3432    TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
3433 
3434    Not Collective
3435 
3436    Input Parameter:
3437 +  ts - TS context
3438 -  fails - maximum number of failed nonlinear solves, pass -1 for unlimited
3439 
3440    Notes:
3441    The counter is reset to zero for each successive call to TSSolve().
3442 
3443    Options Database Key:
3444  .  -ts_max_snes_failures - Maximum number of nonlinear solve failures
3445 
3446    Level: intermediate
3447 
3448 .keywords: TS, set, maximum, number
3449 
3450 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
3451 @*/
3452 PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
3453 {
3454   PetscFunctionBegin;
3455   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3456   ts->max_snes_failures = fails;
3457   PetscFunctionReturn(0);
3458 }
3459 
3460 #undef __FUNCT__
3461 #define __FUNCT__ "TSSetErrorIfStepFails()"
3462 /*@
3463    TSSetErrorIfStepFails - Error if no step succeeds
3464 
3465    Not Collective
3466 
3467    Input Parameter:
3468 +  ts - TS context
3469 -  err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
3470 
3471    Options Database Key:
3472  .  -ts_error_if_step_fails - Error if no step succeeds
3473 
3474    Level: intermediate
3475 
3476 .keywords: TS, set, error
3477 
3478 .seealso:  TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
3479 @*/
3480 PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
3481 {
3482   PetscFunctionBegin;
3483   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3484   ts->errorifstepfailed = err;
3485   PetscFunctionReturn(0);
3486 }
3487 
3488 #undef __FUNCT__
3489 #define __FUNCT__ "TSMonitorSolutionBinary"
3490 /*@C
3491    TSMonitorSolutionBinary - Monitors progress of the TS solvers by VecView() for the solution at each timestep. Normally the viewer is a binary file
3492 
3493    Collective on TS
3494 
3495    Input Parameters:
3496 +  ts - the TS context
3497 .  step - current time-step
3498 .  ptime - current time
3499 .  u - current state
3500 -  viewer - binary viewer
3501 
3502    Level: intermediate
3503 
3504 .keywords: TS,  vector, monitor, view
3505 
3506 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3507 @*/
3508 PetscErrorCode  TSMonitorSolutionBinary(TS ts,PetscInt step,PetscReal ptime,Vec u,void *viewer)
3509 {
3510   PetscErrorCode ierr;
3511   PetscViewer    v = (PetscViewer)viewer;
3512 
3513   PetscFunctionBegin;
3514   ierr = VecView(u,v);CHKERRQ(ierr);
3515   PetscFunctionReturn(0);
3516 }
3517 
3518 #undef __FUNCT__
3519 #define __FUNCT__ "TSMonitorSolutionVTK"
3520 /*@C
3521    TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
3522 
3523    Collective on TS
3524 
3525    Input Parameters:
3526 +  ts - the TS context
3527 .  step - current time-step
3528 .  ptime - current time
3529 .  u - current state
3530 -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
3531 
3532    Level: intermediate
3533 
3534    Notes:
3535    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.
3536    These are named according to the file name template.
3537 
3538    This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
3539 
3540 .keywords: TS,  vector, monitor, view
3541 
3542 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3543 @*/
3544 PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
3545 {
3546   PetscErrorCode ierr;
3547   char           filename[PETSC_MAX_PATH_LEN];
3548   PetscViewer    viewer;
3549 
3550   PetscFunctionBegin;
3551   ierr = PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);CHKERRQ(ierr);
3552   ierr = PetscViewerVTKOpen(((PetscObject)ts)->comm,filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr);
3553   ierr = VecView(u,viewer);CHKERRQ(ierr);
3554   ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3555   PetscFunctionReturn(0);
3556 }
3557 
3558 #undef __FUNCT__
3559 #define __FUNCT__ "TSMonitorSolutionVTKDestroy"
3560 /*@C
3561    TSMonitorSolutionVTKDestroy - Destroy context for monitoring
3562 
3563    Collective on TS
3564 
3565    Input Parameters:
3566 .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
3567 
3568    Level: intermediate
3569 
3570    Note:
3571    This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
3572 
3573 .keywords: TS,  vector, monitor, view
3574 
3575 .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
3576 @*/
3577 PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
3578 {
3579   PetscErrorCode ierr;
3580 
3581   PetscFunctionBegin;
3582   ierr = PetscFree(*(char**)filenametemplate);CHKERRQ(ierr);
3583   PetscFunctionReturn(0);
3584 }
3585 
3586 #undef __FUNCT__
3587 #define __FUNCT__ "TSGetAdapt"
3588 /*@
3589    TSGetAdapt - Get the adaptive controller context for the current method
3590 
3591    Collective on TS if controller has not been created yet
3592 
3593    Input Arguments:
3594 .  ts - time stepping context
3595 
3596    Output Arguments:
3597 .  adapt - adaptive controller
3598 
3599    Level: intermediate
3600 
3601 .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
3602 @*/
3603 PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
3604 {
3605   PetscErrorCode ierr;
3606 
3607   PetscFunctionBegin;
3608   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3609   PetscValidPointer(adapt,2);
3610   if (!ts->adapt) {
3611     ierr = TSAdaptCreate(((PetscObject)ts)->comm,&ts->adapt);CHKERRQ(ierr);
3612     ierr = PetscLogObjectParent(ts,ts->adapt);CHKERRQ(ierr);
3613     ierr = PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);CHKERRQ(ierr);
3614   }
3615   *adapt = ts->adapt;
3616   PetscFunctionReturn(0);
3617 }
3618 
3619 #undef __FUNCT__
3620 #define __FUNCT__ "TSSetTolerances"
3621 /*@
3622    TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
3623 
3624    Logically Collective
3625 
3626    Input Arguments:
3627 +  ts - time integration context
3628 .  atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
3629 .  vatol - vector of absolute tolerances or PETSC_NULL, used in preference to atol if present
3630 .  rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
3631 -  vrtol - vector of relative tolerances or PETSC_NULL, used in preference to atol if present
3632 
3633    Level: beginner
3634 
3635 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
3636 @*/
3637 PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
3638 {
3639   PetscErrorCode ierr;
3640 
3641   PetscFunctionBegin;
3642   if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
3643   if (vatol) {
3644     ierr = PetscObjectReference((PetscObject)vatol);CHKERRQ(ierr);
3645     ierr = VecDestroy(&ts->vatol);CHKERRQ(ierr);
3646     ts->vatol = vatol;
3647   }
3648   if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
3649   if (vrtol) {
3650     ierr = PetscObjectReference((PetscObject)vrtol);CHKERRQ(ierr);
3651     ierr = VecDestroy(&ts->vrtol);CHKERRQ(ierr);
3652     ts->vrtol = vrtol;
3653   }
3654   PetscFunctionReturn(0);
3655 }
3656 
3657 #undef __FUNCT__
3658 #define __FUNCT__ "TSGetTolerances"
3659 /*@
3660    TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
3661 
3662    Logically Collective
3663 
3664    Input Arguments:
3665 .  ts - time integration context
3666 
3667    Output Arguments:
3668 +  atol - scalar absolute tolerances, PETSC_NULL to ignore
3669 .  vatol - vector of absolute tolerances, PETSC_NULL to ignore
3670 .  rtol - scalar relative tolerances, PETSC_NULL to ignore
3671 -  vrtol - vector of relative tolerances, PETSC_NULL to ignore
3672 
3673    Level: beginner
3674 
3675 .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
3676 @*/
3677 PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
3678 {
3679   PetscFunctionBegin;
3680   if (atol)  *atol  = ts->atol;
3681   if (vatol) *vatol = ts->vatol;
3682   if (rtol)  *rtol  = ts->rtol;
3683   if (vrtol) *vrtol = ts->vrtol;
3684   PetscFunctionReturn(0);
3685 }
3686 
3687 #undef __FUNCT__
3688 #define __FUNCT__ "TSErrorNormWRMS"
3689 /*@
3690    TSErrorNormWRMS - compute a weighted norm of the difference between a vector and the current state
3691 
3692    Collective on TS
3693 
3694    Input Arguments:
3695 +  ts - time stepping context
3696 -  Y - state vector to be compared to ts->vec_sol
3697 
3698    Output Arguments:
3699 .  norm - weighted norm, a value of 1.0 is considered small
3700 
3701    Level: developer
3702 
3703 .seealso: TSSetTolerances()
3704 @*/
3705 PetscErrorCode TSErrorNormWRMS(TS ts,Vec Y,PetscReal *norm)
3706 {
3707   PetscErrorCode    ierr;
3708   PetscInt          i,n,N;
3709   const PetscScalar *u,*y;
3710   Vec               U;
3711   PetscReal         sum,gsum;
3712 
3713   PetscFunctionBegin;
3714   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3715   PetscValidHeaderSpecific(Y,VEC_CLASSID,2);
3716   PetscValidPointer(norm,3);
3717   U = ts->vec_sol;
3718   PetscCheckSameTypeAndComm(U,1,Y,2);
3719   if (U == Y) SETERRQ(((PetscObject)U)->comm,PETSC_ERR_ARG_IDN,"Y cannot be the TS solution vector");
3720 
3721   ierr = VecGetSize(U,&N);CHKERRQ(ierr);
3722   ierr = VecGetLocalSize(U,&n);CHKERRQ(ierr);
3723   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
3724   ierr = VecGetArrayRead(Y,&y);CHKERRQ(ierr);
3725   sum = 0.;
3726   if (ts->vatol && ts->vrtol) {
3727     const PetscScalar *atol,*rtol;
3728     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
3729     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
3730     for (i=0; i<n; i++) {
3731       PetscReal tol = PetscRealPart(atol[i]) + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
3732       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
3733     }
3734     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
3735     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
3736   } else if (ts->vatol) {       /* vector atol, scalar rtol */
3737     const PetscScalar *atol;
3738     ierr = VecGetArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
3739     for (i=0; i<n; i++) {
3740       PetscReal tol = PetscRealPart(atol[i]) + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
3741       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
3742     }
3743     ierr = VecRestoreArrayRead(ts->vatol,&atol);CHKERRQ(ierr);
3744   } else if (ts->vrtol) {       /* scalar atol, vector rtol */
3745     const PetscScalar *rtol;
3746     ierr = VecGetArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
3747     for (i=0; i<n; i++) {
3748       PetscReal tol = ts->atol + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
3749       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
3750     }
3751     ierr = VecRestoreArrayRead(ts->vrtol,&rtol);CHKERRQ(ierr);
3752   } else {                      /* scalar atol, scalar rtol */
3753     for (i=0; i<n; i++) {
3754       PetscReal tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
3755       sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
3756     }
3757   }
3758   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
3759   ierr = VecRestoreArrayRead(Y,&y);CHKERRQ(ierr);
3760 
3761   ierr = MPI_Allreduce(&sum,&gsum,1,MPIU_REAL,MPIU_SUM,((PetscObject)ts)->comm);CHKERRQ(ierr);
3762   *norm = PetscSqrtReal(gsum / N);
3763   if (PetscIsInfOrNanScalar(*norm)) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
3764   PetscFunctionReturn(0);
3765 }
3766 
3767 #undef __FUNCT__
3768 #define __FUNCT__ "TSSetCFLTimeLocal"
3769 /*@
3770    TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
3771 
3772    Logically Collective on TS
3773 
3774    Input Arguments:
3775 +  ts - time stepping context
3776 -  cfltime - maximum stable time step if using forward Euler (value can be different on each process)
3777 
3778    Note:
3779    After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
3780 
3781    Level: intermediate
3782 
3783 .seealso: TSGetCFLTime(), TSADAPTCFL
3784 @*/
3785 PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
3786 {
3787   PetscFunctionBegin;
3788   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3789   ts->cfltime_local = cfltime;
3790   ts->cfltime = -1.;
3791   PetscFunctionReturn(0);
3792 }
3793 
3794 #undef __FUNCT__
3795 #define __FUNCT__ "TSGetCFLTime"
3796 /*@
3797    TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
3798 
3799    Collective on TS
3800 
3801    Input Arguments:
3802 .  ts - time stepping context
3803 
3804    Output Arguments:
3805 .  cfltime - maximum stable time step for forward Euler
3806 
3807    Level: advanced
3808 
3809 .seealso: TSSetCFLTimeLocal()
3810 @*/
3811 PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
3812 {
3813   PetscErrorCode ierr;
3814 
3815   PetscFunctionBegin;
3816   if (ts->cfltime < 0) {
3817     ierr = MPI_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,((PetscObject)ts)->comm);CHKERRQ(ierr);
3818   }
3819   *cfltime = ts->cfltime;
3820   PetscFunctionReturn(0);
3821 }
3822 
3823 #undef __FUNCT__
3824 #define __FUNCT__ "TSVISetVariableBounds"
3825 /*@
3826    TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
3827 
3828    Input Parameters:
3829 .  ts   - the TS context.
3830 .  xl   - lower bound.
3831 .  xu   - upper bound.
3832 
3833    Notes:
3834    If this routine is not called then the lower and upper bounds are set to
3835    SNES_VI_NINF and SNES_VI_INF respectively during SNESSetUp().
3836 
3837    Level: advanced
3838 
3839 @*/
3840 PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
3841 {
3842   PetscErrorCode ierr;
3843   SNES           snes;
3844 
3845   PetscFunctionBegin;
3846   ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
3847   ierr = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(ierr);
3848   PetscFunctionReturn(0);
3849 }
3850 
3851 #if defined(PETSC_HAVE_MATLAB_ENGINE)
3852 #include <mex.h>
3853 
3854 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
3855 
3856 #undef __FUNCT__
3857 #define __FUNCT__ "TSComputeFunction_Matlab"
3858 /*
3859    TSComputeFunction_Matlab - Calls the function that has been set with
3860                          TSSetFunctionMatlab().
3861 
3862    Collective on TS
3863 
3864    Input Parameters:
3865 +  snes - the TS context
3866 -  u - input vector
3867 
3868    Output Parameter:
3869 .  y - function vector, as set by TSSetFunction()
3870 
3871    Notes:
3872    TSComputeFunction() is typically used within nonlinear solvers
3873    implementations, so most users would not generally call this routine
3874    themselves.
3875 
3876    Level: developer
3877 
3878 .keywords: TS, nonlinear, compute, function
3879 
3880 .seealso: TSSetFunction(), TSGetFunction()
3881 */
3882 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
3883 {
3884   PetscErrorCode   ierr;
3885   TSMatlabContext *sctx = (TSMatlabContext *)ctx;
3886   int              nlhs = 1,nrhs = 7;
3887   mxArray          *plhs[1],*prhs[7];
3888   long long int    lx = 0,lxdot = 0,ly = 0,ls = 0;
3889 
3890   PetscFunctionBegin;
3891   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
3892   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
3893   PetscValidHeaderSpecific(udot,VEC_CLASSID,4);
3894   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
3895   PetscCheckSameComm(snes,1,u,3);
3896   PetscCheckSameComm(snes,1,y,5);
3897 
3898   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
3899   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
3900   ierr = PetscMemcpy(&lxdot,&udot,sizeof(udot));CHKERRQ(ierr);
3901   ierr = PetscMemcpy(&ly,&y,sizeof(u));CHKERRQ(ierr);
3902   prhs[0] =  mxCreateDoubleScalar((double)ls);
3903   prhs[1] =  mxCreateDoubleScalar(time);
3904   prhs[2] =  mxCreateDoubleScalar((double)lx);
3905   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
3906   prhs[4] =  mxCreateDoubleScalar((double)ly);
3907   prhs[5] =  mxCreateString(sctx->funcname);
3908   prhs[6] =  sctx->ctx;
3909   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
3910   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
3911   mxDestroyArray(prhs[0]);
3912   mxDestroyArray(prhs[1]);
3913   mxDestroyArray(prhs[2]);
3914   mxDestroyArray(prhs[3]);
3915   mxDestroyArray(prhs[4]);
3916   mxDestroyArray(prhs[5]);
3917   mxDestroyArray(plhs[0]);
3918   PetscFunctionReturn(0);
3919 }
3920 
3921 
3922 #undef __FUNCT__
3923 #define __FUNCT__ "TSSetFunctionMatlab"
3924 /*
3925    TSSetFunctionMatlab - Sets the function evaluation routine and function
3926    vector for use by the TS routines in solving ODEs
3927    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
3928 
3929    Logically Collective on TS
3930 
3931    Input Parameters:
3932 +  ts - the TS context
3933 -  func - function evaluation routine
3934 
3935    Calling sequence of func:
3936 $    func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
3937 
3938    Level: beginner
3939 
3940 .keywords: TS, nonlinear, set, function
3941 
3942 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
3943 */
3944 PetscErrorCode  TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
3945 {
3946   PetscErrorCode  ierr;
3947   TSMatlabContext *sctx;
3948 
3949   PetscFunctionBegin;
3950   /* currently sctx is memory bleed */
3951   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
3952   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
3953   /*
3954      This should work, but it doesn't
3955   sctx->ctx = ctx;
3956   mexMakeArrayPersistent(sctx->ctx);
3957   */
3958   sctx->ctx = mxDuplicateArray(ctx);
3959   ierr = TSSetIFunction(ts,PETSC_NULL,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
3960   PetscFunctionReturn(0);
3961 }
3962 
3963 #undef __FUNCT__
3964 #define __FUNCT__ "TSComputeJacobian_Matlab"
3965 /*
3966    TSComputeJacobian_Matlab - Calls the function that has been set with
3967                          TSSetJacobianMatlab().
3968 
3969    Collective on TS
3970 
3971    Input Parameters:
3972 +  ts - the TS context
3973 .  u - input vector
3974 .  A, B - the matrices
3975 -  ctx - user context
3976 
3977    Output Parameter:
3978 .  flag - structure of the matrix
3979 
3980    Level: developer
3981 
3982 .keywords: TS, nonlinear, compute, function
3983 
3984 .seealso: TSSetFunction(), TSGetFunction()
3985 @*/
3986 PetscErrorCode  TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat *A,Mat *B,MatStructure *flag, void *ctx)
3987 {
3988   PetscErrorCode  ierr;
3989   TSMatlabContext *sctx = (TSMatlabContext *)ctx;
3990   int             nlhs = 2,nrhs = 9;
3991   mxArray         *plhs[2],*prhs[9];
3992   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
3993 
3994   PetscFunctionBegin;
3995   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
3996   PetscValidHeaderSpecific(u,VEC_CLASSID,3);
3997 
3998   /* call Matlab function in ctx with arguments u and y */
3999 
4000   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
4001   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4002   ierr = PetscMemcpy(&lxdot,&udot,sizeof(u));CHKERRQ(ierr);
4003   ierr = PetscMemcpy(&lA,A,sizeof(u));CHKERRQ(ierr);
4004   ierr = PetscMemcpy(&lB,B,sizeof(u));CHKERRQ(ierr);
4005   prhs[0] =  mxCreateDoubleScalar((double)ls);
4006   prhs[1] =  mxCreateDoubleScalar((double)time);
4007   prhs[2] =  mxCreateDoubleScalar((double)lx);
4008   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
4009   prhs[4] =  mxCreateDoubleScalar((double)shift);
4010   prhs[5] =  mxCreateDoubleScalar((double)lA);
4011   prhs[6] =  mxCreateDoubleScalar((double)lB);
4012   prhs[7] =  mxCreateString(sctx->funcname);
4013   prhs[8] =  sctx->ctx;
4014   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
4015   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4016   *flag   =  (MatStructure) mxGetScalar(plhs[1]);CHKERRQ(ierr);
4017   mxDestroyArray(prhs[0]);
4018   mxDestroyArray(prhs[1]);
4019   mxDestroyArray(prhs[2]);
4020   mxDestroyArray(prhs[3]);
4021   mxDestroyArray(prhs[4]);
4022   mxDestroyArray(prhs[5]);
4023   mxDestroyArray(prhs[6]);
4024   mxDestroyArray(prhs[7]);
4025   mxDestroyArray(plhs[0]);
4026   mxDestroyArray(plhs[1]);
4027   PetscFunctionReturn(0);
4028 }
4029 
4030 
4031 #undef __FUNCT__
4032 #define __FUNCT__ "TSSetJacobianMatlab"
4033 /*
4034    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
4035    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
4036 
4037    Logically Collective on TS
4038 
4039    Input Parameters:
4040 +  ts - the TS context
4041 .  A,B - Jacobian matrices
4042 .  func - function evaluation routine
4043 -  ctx - user context
4044 
4045    Calling sequence of func:
4046 $    flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
4047 
4048 
4049    Level: developer
4050 
4051 .keywords: TS, nonlinear, set, function
4052 
4053 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4054 */
4055 PetscErrorCode  TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
4056 {
4057   PetscErrorCode    ierr;
4058   TSMatlabContext *sctx;
4059 
4060   PetscFunctionBegin;
4061   /* currently sctx is memory bleed */
4062   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
4063   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
4064   /*
4065      This should work, but it doesn't
4066   sctx->ctx = ctx;
4067   mexMakeArrayPersistent(sctx->ctx);
4068   */
4069   sctx->ctx = mxDuplicateArray(ctx);
4070   ierr = TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
4071   PetscFunctionReturn(0);
4072 }
4073 
4074 #undef __FUNCT__
4075 #define __FUNCT__ "TSMonitor_Matlab"
4076 /*
4077    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
4078 
4079    Collective on TS
4080 
4081 .seealso: TSSetFunction(), TSGetFunction()
4082 @*/
4083 PetscErrorCode  TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
4084 {
4085   PetscErrorCode  ierr;
4086   TSMatlabContext *sctx = (TSMatlabContext *)ctx;
4087   int             nlhs = 1,nrhs = 6;
4088   mxArray         *plhs[1],*prhs[6];
4089   long long int   lx = 0,ls = 0;
4090 
4091   PetscFunctionBegin;
4092   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4093   PetscValidHeaderSpecific(u,VEC_CLASSID,4);
4094 
4095   ierr = PetscMemcpy(&ls,&ts,sizeof(ts));CHKERRQ(ierr);
4096   ierr = PetscMemcpy(&lx,&u,sizeof(u));CHKERRQ(ierr);
4097   prhs[0] =  mxCreateDoubleScalar((double)ls);
4098   prhs[1] =  mxCreateDoubleScalar((double)it);
4099   prhs[2] =  mxCreateDoubleScalar((double)time);
4100   prhs[3] =  mxCreateDoubleScalar((double)lx);
4101   prhs[4] =  mxCreateString(sctx->funcname);
4102   prhs[5] =  sctx->ctx;
4103   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
4104   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
4105   mxDestroyArray(prhs[0]);
4106   mxDestroyArray(prhs[1]);
4107   mxDestroyArray(prhs[2]);
4108   mxDestroyArray(prhs[3]);
4109   mxDestroyArray(prhs[4]);
4110   mxDestroyArray(plhs[0]);
4111   PetscFunctionReturn(0);
4112 }
4113 
4114 
4115 #undef __FUNCT__
4116 #define __FUNCT__ "TSMonitorSetMatlab"
4117 /*
4118    TSMonitorSetMatlab - Sets the monitor function from Matlab
4119 
4120    Level: developer
4121 
4122 .keywords: TS, nonlinear, set, function
4123 
4124 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4125 */
4126 PetscErrorCode  TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
4127 {
4128   PetscErrorCode    ierr;
4129   TSMatlabContext *sctx;
4130 
4131   PetscFunctionBegin;
4132   /* currently sctx is memory bleed */
4133   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
4134   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
4135   /*
4136      This should work, but it doesn't
4137   sctx->ctx = ctx;
4138   mexMakeArrayPersistent(sctx->ctx);
4139   */
4140   sctx->ctx = mxDuplicateArray(ctx);
4141   ierr = TSMonitorSet(ts,TSMonitor_Matlab,sctx,PETSC_NULL);CHKERRQ(ierr);
4142   PetscFunctionReturn(0);
4143 }
4144 #endif
4145 
4146 
4147 
4148 #undef __FUNCT__
4149 #define __FUNCT__ "TSMonitorLGSolution"
4150 /*@C
4151    TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
4152        in a time based line graph
4153 
4154    Collective on TS
4155 
4156    Input Parameters:
4157 +  ts - the TS context
4158 .  step - current time-step
4159 .  ptime - current time
4160 -  lg - a line graph object
4161 
4162    Level: intermediate
4163 
4164     Notes: each process in a parallel run displays its component solutions in a separate window
4165 
4166 .keywords: TS,  vector, monitor, view
4167 
4168 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4169 @*/
4170 PetscErrorCode  TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4171 {
4172   PetscErrorCode    ierr;
4173   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
4174   const PetscScalar *yy;
4175   PetscInt          dim;
4176 
4177   PetscFunctionBegin;
4178   if (!step) {
4179     PetscDrawAxis  axis;
4180     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4181     ierr = PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");CHKERRQ(ierr);
4182     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
4183     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
4184     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4185   }
4186   ierr = VecGetArrayRead(u,&yy);CHKERRQ(ierr);
4187 #if defined(PETSC_USE_COMPLEX)
4188   {
4189     PetscReal *yreal;
4190     PetscInt i,n;
4191     ierr = VecGetLocalSize(u,&n);CHKERRQ(ierr);
4192     ierr = PetscMalloc(n*sizeof(PetscReal),&yreal);CHKERRQ(ierr);
4193     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
4194     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
4195     ierr = PetscFree(yreal);CHKERRQ(ierr);
4196   }
4197 #else
4198   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
4199 #endif
4200   ierr = VecRestoreArrayRead(u,&yy);CHKERRQ(ierr);
4201   if (((ctx->howoften > 0) && (!(step % ctx->howoften)) && (step > -1)) || ((ctx->howoften == -1) && (step == -1))){
4202     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4203   }
4204   PetscFunctionReturn(0);
4205 }
4206 
4207 #undef __FUNCT__
4208 #define __FUNCT__ "TSMonitorLGError"
4209 /*@C
4210    TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the solution vector
4211        in a time based line graph
4212 
4213    Collective on TS
4214 
4215    Input Parameters:
4216 +  ts - the TS context
4217 .  step - current time-step
4218 .  ptime - current time
4219 -  lg - a line graph object
4220 
4221    Level: intermediate
4222 
4223    Notes:
4224    Only for sequential solves.
4225 
4226    The user must provide the solution using TSSetSolutionFunction() to use this monitor.
4227 
4228    Options Database Keys:
4229 .  -ts_monitor_lg_error - create a graphical monitor of error history
4230 
4231 .keywords: TS,  vector, monitor, view
4232 
4233 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4234 @*/
4235 PetscErrorCode  TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4236 {
4237   PetscErrorCode    ierr;
4238   TSMonitorLGCtx    ctx = (TSMonitorLGCtx)dummy;
4239   const PetscScalar *yy;
4240   Vec               y;
4241   PetscInt          dim;
4242 
4243   PetscFunctionBegin;
4244   if (!step) {
4245     PetscDrawAxis  axis;
4246     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4247     ierr = PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Solution");CHKERRQ(ierr);
4248     ierr = VecGetLocalSize(u,&dim);CHKERRQ(ierr);
4249     ierr = PetscDrawLGSetDimension(ctx->lg,dim);CHKERRQ(ierr);
4250     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4251   }
4252   ierr = VecDuplicate(u,&y);CHKERRQ(ierr);
4253   ierr = TSComputeSolutionFunction(ts,ptime,y);CHKERRQ(ierr);
4254   ierr = VecAXPY(y,-1.0,u);CHKERRQ(ierr);
4255   ierr = VecGetArrayRead(y,&yy);CHKERRQ(ierr);
4256 #if defined(PETSC_USE_COMPLEX)
4257   {
4258     PetscReal *yreal;
4259     PetscInt  i,n;
4260     ierr = VecGetLocalSize(y,&n);CHKERRQ(ierr);
4261     ierr = PetscMalloc(n*sizeof(PetscReal),&yreal);CHKERRQ(ierr);
4262     for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
4263     ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);CHKERRQ(ierr);
4264     ierr = PetscFree(yreal);CHKERRQ(ierr);
4265   }
4266 #else
4267   ierr = PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);CHKERRQ(ierr);
4268 #endif
4269   ierr = VecRestoreArrayRead(y,&yy);CHKERRQ(ierr);
4270   ierr = VecDestroy(&y);CHKERRQ(ierr);
4271   if (((ctx->howoften > 0) && (!(step % ctx->howoften)) && (step > -1)) || ((ctx->howoften == -1) && (step == -1))){
4272     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4273   }
4274   PetscFunctionReturn(0);
4275 }
4276 
4277 #undef __FUNCT__
4278 #define __FUNCT__ "TSMonitorLGSNESIterations"
4279 PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
4280 {
4281   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4282   PetscReal      x = ptime,y;
4283   PetscErrorCode ierr;
4284   PetscInt       its;
4285 
4286   PetscFunctionBegin;
4287   if (!n) {
4288     PetscDrawAxis  axis;
4289     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4290     ierr = PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");CHKERRQ(ierr);
4291     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4292     ctx->snes_its  = 0;
4293   }
4294   ierr = TSGetSNESIterations(ts,&its);CHKERRQ(ierr);
4295   y    = its - ctx->snes_its;
4296   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4297   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))){
4298     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4299   }
4300   ctx->snes_its = its;
4301   PetscFunctionReturn(0);
4302 }
4303 
4304 #undef __FUNCT__
4305 #define __FUNCT__ "TSMonitorLGKSPIterations"
4306 PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
4307 {
4308   TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4309   PetscReal      x = ptime,y;
4310   PetscErrorCode ierr;
4311   PetscInt       its;
4312 
4313   PetscFunctionBegin;
4314   if (!n) {
4315     PetscDrawAxis  axis;
4316     ierr = PetscDrawLGGetAxis(ctx->lg,&axis);CHKERRQ(ierr);
4317     ierr = PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");CHKERRQ(ierr);
4318     ierr = PetscDrawLGReset(ctx->lg);CHKERRQ(ierr);
4319     ctx->ksp_its = 0;
4320   }
4321   ierr = TSGetKSPIterations(ts,&its);CHKERRQ(ierr);
4322   y    = its - ctx->ksp_its;
4323   ierr = PetscDrawLGAddPoint(ctx->lg,&x,&y);CHKERRQ(ierr);
4324   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))){
4325     ierr = PetscDrawLGDraw(ctx->lg);CHKERRQ(ierr);
4326   }
4327   ctx->ksp_its = its;
4328   PetscFunctionReturn(0);
4329 }
4330 
4331 #undef __FUNCT__
4332 #define __FUNCT__ "TSComputeLinearStability"
4333 /*@
4334    TSComputeLinearStability - computes the linear stability function at a point
4335 
4336    Collective on TS and Vec
4337 
4338    Input Parameters:
4339 +  ts - the TS context
4340 -  xr,xi - real and imaginary part of input arguments
4341 
4342    Output Parameters:
4343 .  yr,yi - real and imaginary part of function value
4344 
4345    Level: developer
4346 
4347 .keywords: TS, compute
4348 
4349 .seealso: TSSetRHSFunction(), TSComputeIFunction()
4350 @*/
4351 PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
4352 {
4353   PetscErrorCode ierr;
4354 
4355   PetscFunctionBegin;
4356   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
4357   if (!ts->ops->linearstability) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_SUP,"Linearized stability function not provided for this method");
4358   ierr = (*ts->ops->linearstability)(ts,xr,xi,yr,yi);CHKERRQ(ierr);
4359   PetscFunctionReturn(0);
4360 }
4361