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