xref: /petsc/src/ts/interface/ts.c (revision f7028cc39fa62f8f9099e341fdd44c322be48b46) !
1 #define PETSCTS_DLL
2 
3 #include "private/tsimpl.h"        /*I "petscts.h"  I*/
4 
5 /* Logging support */
6 PetscClassId  TS_CLASSID;
7 PetscLogEvent  TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "TSSetTypeFromOptions"
11 /*
12   TSSetTypeFromOptions - Sets the type of ts from user options.
13 
14   Collective on TS
15 
16   Input Parameter:
17 . ts - The ts
18 
19   Level: intermediate
20 
21 .keywords: TS, set, options, database, type
22 .seealso: TSSetFromOptions(), TSSetType()
23 */
24 static PetscErrorCode TSSetTypeFromOptions(TS ts)
25 {
26   PetscBool      opt;
27   const char     *defaultType;
28   char           typeName[256];
29   PetscErrorCode ierr;
30 
31   PetscFunctionBegin;
32   if (((PetscObject)ts)->type_name) {
33     defaultType = ((PetscObject)ts)->type_name;
34   } else {
35     defaultType = TSEULER;
36   }
37 
38   if (!TSRegisterAllCalled) {ierr = TSRegisterAll(PETSC_NULL);CHKERRQ(ierr);}
39   ierr = PetscOptionsList("-ts_type", "TS method"," TSSetType", TSList, defaultType, typeName, 256, &opt);CHKERRQ(ierr);
40   if (opt) {
41     ierr = TSSetType(ts, typeName);CHKERRQ(ierr);
42   } else {
43     ierr = TSSetType(ts, defaultType);CHKERRQ(ierr);
44   }
45   PetscFunctionReturn(0);
46 }
47 
48 #undef __FUNCT__
49 #define __FUNCT__ "TSSetFromOptions"
50 /*@
51    TSSetFromOptions - Sets various TS parameters from user options.
52 
53    Collective on TS
54 
55    Input Parameter:
56 .  ts - the TS context obtained from TSCreate()
57 
58    Options Database Keys:
59 +  -ts_type <type> - TSEULER, TSBEULER, TSSUNDIALS, TSPSEUDO, TSCN, TSRK, TSTHETA, TSGL, TSSSP
60 .  -ts_max_steps maxsteps - maximum number of time-steps to take
61 .  -ts_max_time time - maximum time to compute to
62 .  -ts_dt dt - initial time step
63 .  -ts_monitor - print information at each timestep
64 -  -ts_monitor_draw - plot information at each timestep
65 
66    Level: beginner
67 
68 .keywords: TS, timestep, set, options, database
69 
70 .seealso: TSGetType()
71 @*/
72 PetscErrorCode  TSSetFromOptions(TS ts)
73 {
74   PetscReal               dt;
75   PetscBool               opt,flg;
76   PetscErrorCode          ierr;
77   PetscViewerASCIIMonitor monviewer;
78   char                    monfilename[PETSC_MAX_PATH_LEN];
79 
80   PetscFunctionBegin;
81   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
82   ierr = PetscOptionsBegin(((PetscObject)ts)->comm, ((PetscObject)ts)->prefix, "Time step options", "TS");CHKERRQ(ierr);
83 
84     /* Handle generic TS options */
85     ierr = PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetDuration",ts->max_steps,&ts->max_steps,PETSC_NULL);CHKERRQ(ierr);
86     ierr = PetscOptionsReal("-ts_max_time","Time to run to","TSSetDuration",ts->max_time,&ts->max_time,PETSC_NULL);CHKERRQ(ierr);
87     ierr = PetscOptionsReal("-ts_init_time","Initial time","TSSetInitialTime", ts->ptime, &ts->ptime, PETSC_NULL);CHKERRQ(ierr);
88     ierr = PetscOptionsReal("-ts_dt","Initial time step","TSSetInitialTimeStep",ts->initial_time_step,&dt,&opt);CHKERRQ(ierr);
89     if (opt) {
90       ts->initial_time_step = ts->time_step = dt;
91     }
92 
93     /* Monitor options */
94     ierr = PetscOptionsString("-ts_monitor","Monitor timestep size","TSMonitorDefault","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
95     if (flg) {
96       ierr = PetscViewerASCIIMonitorCreate(((PetscObject)ts)->comm,monfilename,((PetscObject)ts)->tablevel,&monviewer);CHKERRQ(ierr);
97       ierr = TSMonitorSet(ts,TSMonitorDefault,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr);
98     }
99     opt  = PETSC_FALSE;
100     ierr = PetscOptionsBool("-ts_monitor_draw","Monitor timestep size graphically","TSMonitorLG",opt,&opt,PETSC_NULL);CHKERRQ(ierr);
101     if (opt) {
102       ierr = TSMonitorSet(ts,TSMonitorLG,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
103     }
104     opt  = PETSC_FALSE;
105     ierr = PetscOptionsBool("-ts_monitor_solution","Monitor solution graphically","TSMonitorSolution",opt,&opt,PETSC_NULL);CHKERRQ(ierr);
106     if (opt) {
107       ierr = TSMonitorSet(ts,TSMonitorSolution,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
108     }
109 
110     /* Handle TS type options */
111     ierr = TSSetTypeFromOptions(ts);CHKERRQ(ierr);
112 
113     /* Handle specific TS options */
114     if (ts->ops->setfromoptions) {
115       ierr = (*ts->ops->setfromoptions)(ts);CHKERRQ(ierr);
116     }
117 
118     /* process any options handlers added with PetscObjectAddOptionsHandler() */
119     ierr = PetscObjectProcessOptionsHandlers((PetscObject)ts);CHKERRQ(ierr);
120   ierr = PetscOptionsEnd();CHKERRQ(ierr);
121 
122   /* Handle subobject options */
123   switch(ts->problem_type) {
124     /* Should check for implicit/explicit */
125   case TS_LINEAR:
126     if (ts->ksp) {
127       ierr = KSPSetOperators(ts->ksp,ts->Arhs,ts->B,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
128       ierr = KSPSetFromOptions(ts->ksp);CHKERRQ(ierr);
129     }
130     break;
131   case TS_NONLINEAR:
132     if (ts->snes) {
133       /* this is a bit of a hack, but it gets the matrix information into SNES earlier
134          so that SNES and KSP have more information to pick reasonable defaults
135          before they allow users to set options
136        * If ts->A has been set at this point, we are probably using the implicit form
137          and Arhs will never be used. */
138       ierr = SNESSetJacobian(ts->snes,ts->A?ts->A:ts->Arhs,ts->B,0,ts);CHKERRQ(ierr);
139       ierr = SNESSetFromOptions(ts->snes);CHKERRQ(ierr);
140     }
141     break;
142   default:
143     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid problem type: %d", (int)ts->problem_type);
144   }
145 
146   PetscFunctionReturn(0);
147 }
148 
149 #undef  __FUNCT__
150 #define __FUNCT__ "TSViewFromOptions"
151 /*@
152   TSViewFromOptions - This function visualizes the ts based upon user options.
153 
154   Collective on TS
155 
156   Input Parameter:
157 . ts - The ts
158 
159   Level: intermediate
160 
161 .keywords: TS, view, options, database
162 .seealso: TSSetFromOptions(), TSView()
163 @*/
164 PetscErrorCode  TSViewFromOptions(TS ts,const char title[])
165 {
166   PetscViewer    viewer;
167   PetscDraw      draw;
168   PetscBool      opt = PETSC_FALSE;
169   char           fileName[PETSC_MAX_PATH_LEN];
170   PetscErrorCode ierr;
171 
172   PetscFunctionBegin;
173   ierr = PetscOptionsGetString(((PetscObject)ts)->prefix, "-ts_view", fileName, PETSC_MAX_PATH_LEN, &opt);CHKERRQ(ierr);
174   if (opt && !PetscPreLoadingOn) {
175     ierr = PetscViewerASCIIOpen(((PetscObject)ts)->comm,fileName,&viewer);CHKERRQ(ierr);
176     ierr = TSView(ts, viewer);CHKERRQ(ierr);
177     ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
178   }
179   opt = PETSC_FALSE;
180   ierr = PetscOptionsGetBool(((PetscObject)ts)->prefix, "-ts_view_draw", &opt,PETSC_NULL);CHKERRQ(ierr);
181   if (opt) {
182     ierr = PetscViewerDrawOpen(((PetscObject)ts)->comm, 0, 0, 0, 0, 300, 300, &viewer);CHKERRQ(ierr);
183     ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
184     if (title) {
185       ierr = PetscDrawSetTitle(draw, (char *)title);CHKERRQ(ierr);
186     } else {
187       ierr = PetscObjectName((PetscObject)ts);CHKERRQ(ierr);
188       ierr = PetscDrawSetTitle(draw, ((PetscObject)ts)->name);CHKERRQ(ierr);
189     }
190     ierr = TSView(ts, viewer);CHKERRQ(ierr);
191     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
192     ierr = PetscDrawPause(draw);CHKERRQ(ierr);
193     ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
194   }
195   PetscFunctionReturn(0);
196 }
197 
198 #undef __FUNCT__
199 #define __FUNCT__ "TSComputeRHSJacobian"
200 /*@
201    TSComputeRHSJacobian - Computes the Jacobian matrix that has been
202       set with TSSetRHSJacobian().
203 
204    Collective on TS and Vec
205 
206    Input Parameters:
207 +  ts - the TS context
208 .  t - current timestep
209 -  x - input vector
210 
211    Output Parameters:
212 +  A - Jacobian matrix
213 .  B - optional preconditioning matrix
214 -  flag - flag indicating matrix structure
215 
216    Notes:
217    Most users should not need to explicitly call this routine, as it
218    is used internally within the nonlinear solvers.
219 
220    See KSPSetOperators() for important information about setting the
221    flag parameter.
222 
223    TSComputeJacobian() is valid only for TS_NONLINEAR
224 
225    Level: developer
226 
227 .keywords: SNES, compute, Jacobian, matrix
228 
229 .seealso:  TSSetRHSJacobian(), KSPSetOperators()
230 @*/
231 PetscErrorCode  TSComputeRHSJacobian(TS ts,PetscReal t,Vec X,Mat *A,Mat *B,MatStructure *flg)
232 {
233   PetscErrorCode ierr;
234 
235   PetscFunctionBegin;
236   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
237   PetscValidHeaderSpecific(X,VEC_CLASSID,3);
238   PetscCheckSameComm(ts,1,X,3);
239   if (ts->problem_type != TS_NONLINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"For TS_NONLINEAR only");
240   if (ts->ops->rhsjacobian) {
241     ierr = PetscLogEventBegin(TS_JacobianEval,ts,X,*A,*B);CHKERRQ(ierr);
242     *flg = DIFFERENT_NONZERO_PATTERN;
243     PetscStackPush("TS user Jacobian function");
244     ierr = (*ts->ops->rhsjacobian)(ts,t,X,A,B,flg,ts->jacP);CHKERRQ(ierr);
245     PetscStackPop;
246     ierr = PetscLogEventEnd(TS_JacobianEval,ts,X,*A,*B);CHKERRQ(ierr);
247     /* make sure user returned a correct Jacobian and preconditioner */
248     PetscValidHeaderSpecific(*A,MAT_CLASSID,4);
249     PetscValidHeaderSpecific(*B,MAT_CLASSID,5);
250   } else {
251     ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
252     ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
253     if (*A != *B) {
254       ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
255       ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
256     }
257   }
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "TSComputeRHSFunction"
263 /*@
264    TSComputeRHSFunction - Evaluates the right-hand-side function.
265 
266    Collective on TS and Vec
267 
268    Input Parameters:
269 +  ts - the TS context
270 .  t - current time
271 -  x - state vector
272 
273    Output Parameter:
274 .  y - right hand side
275 
276    Note:
277    Most users should not need to explicitly call this routine, as it
278    is used internally within the nonlinear solvers.
279 
280    If the user did not provide a function but merely a matrix,
281    this routine applies the matrix.
282 
283    Level: developer
284 
285 .keywords: TS, compute
286 
287 .seealso: TSSetRHSFunction(), TSComputeIFunction()
288 @*/
289 PetscErrorCode TSComputeRHSFunction(TS ts,PetscReal t,Vec x,Vec y)
290 {
291   PetscErrorCode ierr;
292 
293   PetscFunctionBegin;
294   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
295   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
296   PetscValidHeaderSpecific(y,VEC_CLASSID,4);
297 
298   ierr = PetscLogEventBegin(TS_FunctionEval,ts,x,y,0);CHKERRQ(ierr);
299   if (ts->ops->rhsfunction) {
300     PetscStackPush("TS user right-hand-side function");
301     ierr = (*ts->ops->rhsfunction)(ts,t,x,y,ts->funP);CHKERRQ(ierr);
302     PetscStackPop;
303   } else if (ts->Arhs) {
304     if (ts->ops->rhsmatrix) { /* assemble matrix for this timestep */
305       MatStructure flg;
306       PetscStackPush("TS user right-hand-side matrix function");
307       ierr = (*ts->ops->rhsmatrix)(ts,t,&ts->Arhs,&ts->B,&flg,ts->jacP);CHKERRQ(ierr);
308       PetscStackPop;
309     }
310     ierr = MatMult(ts->Arhs,x,y);CHKERRQ(ierr);
311   } else SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"No RHS provided, must call TSSetRHSFunction() or TSSetMatrices()");
312 
313   ierr = PetscLogEventEnd(TS_FunctionEval,ts,x,y,0);CHKERRQ(ierr);
314 
315   PetscFunctionReturn(0);
316 }
317 
318 #undef __FUNCT__
319 #define __FUNCT__ "TSComputeIFunction"
320 /*@
321    TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,X,Xdot)=0
322 
323    Collective on TS and Vec
324 
325    Input Parameters:
326 +  ts - the TS context
327 .  t - current time
328 .  X - state vector
329 -  Xdot - time derivative of state vector
330 
331    Output Parameter:
332 .  Y - right hand side
333 
334    Note:
335    Most users should not need to explicitly call this routine, as it
336    is used internally within the nonlinear solvers.
337 
338    If the user did did not write their equations in implicit form, this
339    function recasts them in implicit form.
340 
341    Level: developer
342 
343 .keywords: TS, compute
344 
345 .seealso: TSSetIFunction(), TSComputeRHSFunction()
346 @*/
347 PetscErrorCode TSComputeIFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec Y)
348 {
349   PetscErrorCode ierr;
350 
351   PetscFunctionBegin;
352   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
353   PetscValidHeaderSpecific(X,VEC_CLASSID,3);
354   PetscValidHeaderSpecific(Xdot,VEC_CLASSID,4);
355   PetscValidHeaderSpecific(Y,VEC_CLASSID,5);
356 
357   ierr = PetscLogEventBegin(TS_FunctionEval,ts,X,Xdot,Y);CHKERRQ(ierr);
358   if (ts->ops->ifunction) {
359     PetscStackPush("TS user implicit function");
360     ierr = (*ts->ops->ifunction)(ts,t,X,Xdot,Y,ts->funP);CHKERRQ(ierr);
361     PetscStackPop;
362   } else {
363     if (ts->ops->rhsfunction) {
364       PetscStackPush("TS user right-hand-side function");
365       ierr = (*ts->ops->rhsfunction)(ts,t,X,Y,ts->funP);CHKERRQ(ierr);
366       PetscStackPop;
367     } else {
368       if (ts->ops->rhsmatrix) { /* assemble matrix for this timestep */
369         MatStructure flg;
370         /* Note: flg is not being used.
371            For it to be useful, we'd have to cache it and then apply it in TSComputeIJacobian.
372         */
373         PetscStackPush("TS user right-hand-side matrix function");
374         ierr = (*ts->ops->rhsmatrix)(ts,t,&ts->Arhs,&ts->B,&flg,ts->jacP);CHKERRQ(ierr);
375         PetscStackPop;
376       }
377       ierr = MatMult(ts->Arhs,X,Y);CHKERRQ(ierr);
378     }
379 
380     /* Convert to implicit form: F(X,Xdot) = Alhs * Xdot - Frhs(X) */
381     if (ts->Alhs) {
382       if (ts->ops->lhsmatrix) {
383         MatStructure flg;
384         PetscStackPush("TS user left-hand-side matrix function");
385         ierr = (*ts->ops->lhsmatrix)(ts,t,&ts->Alhs,PETSC_NULL,&flg,ts->jacP);CHKERRQ(ierr);
386         PetscStackPop;
387       }
388       ierr = VecScale(Y,-1.);CHKERRQ(ierr);
389       ierr = MatMultAdd(ts->Alhs,Xdot,Y,Y);CHKERRQ(ierr);
390     } else {
391       ierr = VecAYPX(Y,-1,Xdot);CHKERRQ(ierr);
392     }
393   }
394   ierr = PetscLogEventEnd(TS_FunctionEval,ts,X,Xdot,Y);CHKERRQ(ierr);
395   PetscFunctionReturn(0);
396 }
397 
398 #undef __FUNCT__
399 #define __FUNCT__ "TSComputeIJacobian"
400 /*@
401    TSComputeIJacobian - Evaluates the Jacobian of the DAE
402 
403    Collective on TS and Vec
404 
405    Input
406       Input Parameters:
407 +  ts - the TS context
408 .  t - current timestep
409 .  X - state vector
410 .  Xdot - time derivative of state vector
411 -  shift - shift to apply, see note below
412 
413    Output Parameters:
414 +  A - Jacobian matrix
415 .  B - optional preconditioning matrix
416 -  flag - flag indicating matrix structure
417 
418    Notes:
419    If F(t,X,Xdot)=0 is the DAE, the required Jacobian is
420 
421    dF/dX + shift*dF/dXdot
422 
423    Most users should not need to explicitly call this routine, as it
424    is used internally within the nonlinear solvers.
425 
426    TSComputeIJacobian() is valid only for TS_NONLINEAR
427 
428    Level: developer
429 
430 .keywords: TS, compute, Jacobian, matrix
431 
432 .seealso:  TSSetIJacobian()
433 @*/
434 PetscErrorCode  TSComputeIJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal shift,Mat *A,Mat *B,MatStructure *flg)
435 {
436   PetscErrorCode ierr;
437 
438   PetscFunctionBegin;
439   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
440   PetscValidHeaderSpecific(X,VEC_CLASSID,3);
441   PetscValidHeaderSpecific(Xdot,VEC_CLASSID,4);
442   PetscValidPointer(A,6);
443   PetscValidHeaderSpecific(*A,MAT_CLASSID,6);
444   PetscValidPointer(B,7);
445   PetscValidHeaderSpecific(*B,MAT_CLASSID,7);
446   PetscValidPointer(flg,8);
447 
448   *flg = SAME_NONZERO_PATTERN;  /* In case it we're solving a linear problem in which case it wouldn't get initialized below. */
449   ierr = PetscLogEventBegin(TS_JacobianEval,ts,X,*A,*B);CHKERRQ(ierr);
450   if (ts->ops->ijacobian) {
451     PetscStackPush("TS user implicit Jacobian");
452     ierr = (*ts->ops->ijacobian)(ts,t,X,Xdot,shift,A,B,flg,ts->jacP);CHKERRQ(ierr);
453     PetscStackPop;
454   } else {
455     if (ts->ops->rhsjacobian) {
456       PetscStackPush("TS user right-hand-side Jacobian");
457       ierr = (*ts->ops->rhsjacobian)(ts,t,X,A,B,flg,ts->jacP);CHKERRQ(ierr);
458       PetscStackPop;
459     } else {
460       ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
461       ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
462       if (*A != *B) {
463         ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
464         ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
465       }
466     }
467 
468     /* Convert to implicit form */
469     /* inefficient because these operations will normally traverse all matrix elements twice */
470     ierr = MatScale(*A,-1);CHKERRQ(ierr);
471     if (ts->Alhs) {
472       ierr = MatAXPY(*A,shift,ts->Alhs,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
473     } else {
474       ierr = MatShift(*A,shift);CHKERRQ(ierr);
475     }
476     if (*A != *B) {
477       ierr = MatScale(*B,-1);CHKERRQ(ierr);
478       ierr = MatShift(*B,shift);CHKERRQ(ierr);
479     }
480   }
481   ierr = PetscLogEventEnd(TS_JacobianEval,ts,X,*A,*B);CHKERRQ(ierr);
482   PetscFunctionReturn(0);
483 }
484 
485 #undef __FUNCT__
486 #define __FUNCT__ "TSSetRHSFunction"
487 /*@C
488     TSSetRHSFunction - Sets the routine for evaluating the function,
489     F(t,u), where U_t = F(t,u).
490 
491     Logically Collective on TS
492 
493     Input Parameters:
494 +   ts - the TS context obtained from TSCreate()
495 .   f - routine for evaluating the right-hand-side function
496 -   ctx - [optional] user-defined context for private data for the
497           function evaluation routine (may be PETSC_NULL)
498 
499     Calling sequence of func:
500 $     func (TS ts,PetscReal t,Vec u,Vec F,void *ctx);
501 
502 +   t - current timestep
503 .   u - input vector
504 .   F - function vector
505 -   ctx - [optional] user-defined function context
506 
507     Important:
508     The user MUST call either this routine or TSSetMatrices().
509 
510     Level: beginner
511 
512 .keywords: TS, timestep, set, right-hand-side, function
513 
514 .seealso: TSSetMatrices()
515 @*/
516 PetscErrorCode  TSSetRHSFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*),void *ctx)
517 {
518   PetscFunctionBegin;
519 
520   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
521   if (ts->problem_type == TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot set function for linear problem");
522   ts->ops->rhsfunction = f;
523   ts->funP             = ctx;
524   PetscFunctionReturn(0);
525 }
526 
527 #undef __FUNCT__
528 #define __FUNCT__ "TSSetMatrices"
529 /*@C
530    TSSetMatrices - Sets the functions to compute the matrices Alhs and Arhs,
531    where Alhs(t) U_t = Arhs(t) U.
532 
533    Logically Collective on TS
534 
535    Input Parameters:
536 +  ts   - the TS context obtained from TSCreate()
537 .  Arhs - matrix
538 .  frhs - the matrix evaluation routine for Arhs; use PETSC_NULL (PETSC_NULL_FUNCTION in fortran)
539           if Arhs is not a function of t.
540 .  Alhs - matrix or PETSC_NULL if Alhs is an indentity matrix.
541 .  flhs - the matrix evaluation routine for Alhs; use PETSC_NULL (PETSC_NULL_FUNCTION in fortran)
542           if Alhs is not a function of t.
543 .  flag - flag indicating information about the matrix structure of Arhs and Alhs.
544           The available options are
545             SAME_NONZERO_PATTERN - Alhs has the same nonzero structure as Arhs
546             DIFFERENT_NONZERO_PATTERN - Alhs has different nonzero structure as Arhs
547 -  ctx  - [optional] user-defined context for private data for the
548           matrix evaluation routine (may be PETSC_NULL)
549 
550    Calling sequence of func:
551 $     func(TS ts,PetscReal t,Mat *A,Mat *B,PetscInt *flag,void *ctx);
552 
553 +  t - current timestep
554 .  A - matrix A, where U_t = A(t) U
555 .  B - preconditioner matrix, usually the same as A
556 .  flag - flag indicating information about the preconditioner matrix
557           structure (same as flag in KSPSetOperators())
558 -  ctx - [optional] user-defined context for matrix evaluation routine
559 
560    Notes:
561    The routine func() takes Mat* as the matrix arguments rather than Mat.
562    This allows the matrix evaluation routine to replace Arhs or Alhs with a
563    completely new new matrix structure (not just different matrix elements)
564    when appropriate, for instance, if the nonzero structure is changing
565    throughout the global iterations.
566 
567    Important:
568    The user MUST call either this routine or TSSetRHSFunction().
569 
570    Level: beginner
571 
572 .keywords: TS, timestep, set, matrix
573 
574 .seealso: TSSetRHSFunction()
575 @*/
576 PetscErrorCode  TSSetMatrices(TS ts,Mat Arhs,PetscErrorCode (*frhs)(TS,PetscReal,Mat*,Mat*,MatStructure*,void*),Mat Alhs,PetscErrorCode (*flhs)(TS,PetscReal,Mat*,Mat*,MatStructure*,void*),MatStructure flag,void *ctx)
577 {
578   PetscFunctionBegin;
579   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
580   if (Arhs){
581     PetscValidHeaderSpecific(Arhs,MAT_CLASSID,2);
582     PetscCheckSameComm(ts,1,Arhs,2);
583     ts->Arhs           = Arhs;
584     ts->ops->rhsmatrix = frhs;
585   }
586   if (Alhs){
587     PetscValidHeaderSpecific(Alhs,MAT_CLASSID,4);
588     PetscCheckSameComm(ts,1,Alhs,4);
589     ts->Alhs           = Alhs;
590     ts->ops->lhsmatrix = flhs;
591   }
592 
593   ts->jacP           = ctx;
594   ts->matflg         = flag;
595   PetscFunctionReturn(0);
596 }
597 
598 #undef __FUNCT__
599 #define __FUNCT__ "TSGetMatrices"
600 /*@C
601    TSGetMatrices - Returns the matrices Arhs and Alhs at the present timestep,
602    where Alhs(t) U_t = Arhs(t) U.
603 
604    Not Collective, but parallel objects are returned if TS is parallel
605 
606    Input Parameter:
607 .  ts  - The TS context obtained from TSCreate()
608 
609    Output Parameters:
610 +  Arhs - The right-hand side matrix
611 .  Alhs - The left-hand side matrix
612 -  ctx - User-defined context for matrix evaluation routine
613 
614    Notes: You can pass in PETSC_NULL for any return argument you do not need.
615 
616    Level: intermediate
617 
618 .seealso: TSSetMatrices(), TSGetTimeStep(), TSGetTime(), TSGetTimeStepNumber(), TSGetRHSJacobian()
619 
620 .keywords: TS, timestep, get, matrix
621 
622 @*/
623 PetscErrorCode  TSGetMatrices(TS ts,Mat *Arhs,Mat *Alhs,void **ctx)
624 {
625   PetscFunctionBegin;
626   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
627   if (Arhs) *Arhs = ts->Arhs;
628   if (Alhs) *Alhs = ts->Alhs;
629   if (ctx)  *ctx = ts->jacP;
630   PetscFunctionReturn(0);
631 }
632 
633 #undef __FUNCT__
634 #define __FUNCT__ "TSSetRHSJacobian"
635 /*@C
636    TSSetRHSJacobian - Sets the function to compute the Jacobian of F,
637    where U_t = F(U,t), as well as the location to store the matrix.
638    Use TSSetMatrices() for linear problems.
639 
640    Logically Collective on TS
641 
642    Input Parameters:
643 +  ts  - the TS context obtained from TSCreate()
644 .  A   - Jacobian matrix
645 .  B   - preconditioner matrix (usually same as A)
646 .  f   - the Jacobian evaluation routine
647 -  ctx - [optional] user-defined context for private data for the
648          Jacobian evaluation routine (may be PETSC_NULL)
649 
650    Calling sequence of func:
651 $     func (TS ts,PetscReal t,Vec u,Mat *A,Mat *B,MatStructure *flag,void *ctx);
652 
653 +  t - current timestep
654 .  u - input vector
655 .  A - matrix A, where U_t = A(t)u
656 .  B - preconditioner matrix, usually the same as A
657 .  flag - flag indicating information about the preconditioner matrix
658           structure (same as flag in KSPSetOperators())
659 -  ctx - [optional] user-defined context for matrix evaluation routine
660 
661    Notes:
662    See KSPSetOperators() for important information about setting the flag
663    output parameter in the routine func().  Be sure to read this information!
664 
665    The routine func() takes Mat * as the matrix arguments rather than Mat.
666    This allows the matrix evaluation routine to replace A and/or B with a
667    completely new matrix structure (not just different matrix elements)
668    when appropriate, for instance, if the nonzero structure is changing
669    throughout the global iterations.
670 
671    Level: beginner
672 
673 .keywords: TS, timestep, set, right-hand-side, Jacobian
674 
675 .seealso: TSDefaultComputeJacobianColor(),
676           SNESDefaultComputeJacobianColor(), TSSetRHSFunction(), TSSetMatrices()
677 
678 @*/
679 PetscErrorCode  TSSetRHSJacobian(TS ts,Mat A,Mat B,PetscErrorCode (*f)(TS,PetscReal,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
680 {
681   PetscFunctionBegin;
682   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
683   PetscValidHeaderSpecific(A,MAT_CLASSID,2);
684   PetscValidHeaderSpecific(B,MAT_CLASSID,3);
685   PetscCheckSameComm(ts,1,A,2);
686   PetscCheckSameComm(ts,1,B,3);
687   if (ts->problem_type != TS_NONLINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not for linear problems; use TSSetMatrices()");
688 
689   ts->ops->rhsjacobian = f;
690   ts->jacP             = ctx;
691   ts->Arhs             = A;
692   ts->B                = B;
693   PetscFunctionReturn(0);
694 }
695 
696 
697 #undef __FUNCT__
698 #define __FUNCT__ "TSSetIFunction"
699 /*@C
700    TSSetIFunction - Set the function to compute F(t,U,U_t) where F = 0 is the DAE to be solved.
701 
702    Logically Collective on TS
703 
704    Input Parameters:
705 +  ts  - the TS context obtained from TSCreate()
706 .  f   - the function evaluation routine
707 -  ctx - user-defined context for private data for the function evaluation routine (may be PETSC_NULL)
708 
709    Calling sequence of f:
710 $  f(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx);
711 
712 +  t   - time at step/stage being solved
713 .  u   - state vector
714 .  u_t - time derivative of state vector
715 .  F   - function vector
716 -  ctx - [optional] user-defined context for matrix evaluation routine
717 
718    Important:
719    The user MUST call either this routine, TSSetRHSFunction(), or TSSetMatrices().  This routine must be used when not solving an ODE.
720 
721    Level: beginner
722 
723 .keywords: TS, timestep, set, DAE, Jacobian
724 
725 .seealso: TSSetMatrices(), TSSetRHSFunction(), TSSetIJacobian()
726 @*/
727 PetscErrorCode  TSSetIFunction(TS ts,TSIFunction f,void *ctx)
728 {
729 
730   PetscFunctionBegin;
731   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
732   ts->ops->ifunction = f;
733   ts->funP           = ctx;
734   PetscFunctionReturn(0);
735 }
736 
737 #undef __FUNCT__
738 #define __FUNCT__ "TSSetIJacobian"
739 /*@C
740    TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t which is
741    the Jacobian of G(U) = F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
742    The time integrator internally approximates U_t by W+a*U where the positive "shift"
743    a and vector W depend on the integration method, step size, and past states.
744 
745    Logically Collective on TS
746 
747    Input Parameters:
748 +  ts  - the TS context obtained from TSCreate()
749 .  A   - Jacobian matrix
750 .  B   - preconditioning matrix for A (may be same as A)
751 .  f   - the Jacobian evaluation routine
752 -  ctx - user-defined context for private data for the Jacobian evaluation routine (may be PETSC_NULL)
753 
754    Calling sequence of f:
755 $  f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat *A,Mat *B,MatStructure *flag,void *ctx);
756 
757 +  t    - time at step/stage being solved
758 .  U    - state vector
759 .  U_t  - time derivative of state vector
760 .  a    - shift
761 .  A    - Jacobian of G(U) = F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
762 .  B    - preconditioning matrix for A, may be same as A
763 .  flag - flag indicating information about the preconditioner matrix
764           structure (same as flag in KSPSetOperators())
765 -  ctx  - [optional] user-defined context for matrix evaluation routine
766 
767    Notes:
768    The matrices A and B are exactly the matrices that are used by SNES for the nonlinear solve.
769 
770    Level: beginner
771 
772 .keywords: TS, timestep, DAE, Jacobian
773 
774 .seealso: TSSetIFunction(), TSSetRHSJacobian()
775 
776 @*/
777 PetscErrorCode  TSSetIJacobian(TS ts,Mat A,Mat B,TSIJacobian f,void *ctx)
778 {
779   PetscErrorCode ierr;
780 
781   PetscFunctionBegin;
782   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
783   if (A) PetscValidHeaderSpecific(A,MAT_CLASSID,2);
784   if (B) PetscValidHeaderSpecific(B,MAT_CLASSID,3);
785   if (A) PetscCheckSameComm(ts,1,A,2);
786   if (B) PetscCheckSameComm(ts,1,B,3);
787   if (f)   ts->ops->ijacobian = f;
788   if (ctx) ts->jacP             = ctx;
789   if (A) {
790     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
791     if (ts->A) {ierr = MatDestroy(ts->A);CHKERRQ(ierr);}
792     ts->A = A;
793   }
794 #if 0
795   /* The sane and consistent alternative */
796   if (B) {
797     ierr = PetscObjectReference((PetscObject)B);CHKERRQ(ierr);
798     if (ts->B) {ierr = MatDestroy(ts->B);CHKERRQ(ierr);}
799     ts->B = B;
800   }
801 #else
802   /* Don't reference B because TSDestroy() doesn't destroy it.  These ownership semantics are awkward and inconsistent. */
803   if (B) ts->B = B;
804 #endif
805   PetscFunctionReturn(0);
806 }
807 
808 #undef __FUNCT__
809 #define __FUNCT__ "TSView"
810 /*@C
811     TSView - Prints the TS data structure.
812 
813     Collective on TS
814 
815     Input Parameters:
816 +   ts - the TS context obtained from TSCreate()
817 -   viewer - visualization context
818 
819     Options Database Key:
820 .   -ts_view - calls TSView() at end of TSStep()
821 
822     Notes:
823     The available visualization contexts include
824 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
825 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
826          output where only the first processor opens
827          the file.  All other processors send their
828          data to the first processor to print.
829 
830     The user can open an alternative visualization context with
831     PetscViewerASCIIOpen() - output to a specified file.
832 
833     Level: beginner
834 
835 .keywords: TS, timestep, view
836 
837 .seealso: PetscViewerASCIIOpen()
838 @*/
839 PetscErrorCode  TSView(TS ts,PetscViewer viewer)
840 {
841   PetscErrorCode ierr;
842   const TSType   type;
843   PetscBool      iascii,isstring;
844 
845   PetscFunctionBegin;
846   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
847   if (!viewer) {
848     ierr = PetscViewerASCIIGetStdout(((PetscObject)ts)->comm,&viewer);CHKERRQ(ierr);
849   }
850   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
851   PetscCheckSameComm(ts,1,viewer,2);
852 
853   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
854   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
855   if (iascii) {
856     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer,"TS Object");CHKERRQ(ierr);
857     if (ts->ops->view) {
858       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
859       ierr = (*ts->ops->view)(ts,viewer);CHKERRQ(ierr);
860       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
861     }
862     ierr = PetscViewerASCIIPrintf(viewer,"  maximum steps=%D\n",ts->max_steps);CHKERRQ(ierr);
863     ierr = PetscViewerASCIIPrintf(viewer,"  maximum time=%G\n",ts->max_time);CHKERRQ(ierr);
864     if (ts->problem_type == TS_NONLINEAR) {
865       ierr = PetscViewerASCIIPrintf(viewer,"  total number of nonlinear solver iterations=%D\n",ts->nonlinear_its);CHKERRQ(ierr);
866     }
867     ierr = PetscViewerASCIIPrintf(viewer,"  total number of linear solver iterations=%D\n",ts->linear_its);CHKERRQ(ierr);
868   } else if (isstring) {
869     ierr = TSGetType(ts,&type);CHKERRQ(ierr);
870     ierr = PetscViewerStringSPrintf(viewer," %-7.7s",type);CHKERRQ(ierr);
871   }
872   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
873   if (ts->ksp) {ierr = KSPView(ts->ksp,viewer);CHKERRQ(ierr);}
874   if (ts->snes) {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);}
875   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
876   PetscFunctionReturn(0);
877 }
878 
879 
880 #undef __FUNCT__
881 #define __FUNCT__ "TSSetApplicationContext"
882 /*@C
883    TSSetApplicationContext - Sets an optional user-defined context for
884    the timesteppers.
885 
886    Logically Collective on TS
887 
888    Input Parameters:
889 +  ts - the TS context obtained from TSCreate()
890 -  usrP - optional user context
891 
892    Level: intermediate
893 
894 .keywords: TS, timestep, set, application, context
895 
896 .seealso: TSGetApplicationContext()
897 @*/
898 PetscErrorCode  TSSetApplicationContext(TS ts,void *usrP)
899 {
900   PetscFunctionBegin;
901   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
902   ts->user = usrP;
903   PetscFunctionReturn(0);
904 }
905 
906 #undef __FUNCT__
907 #define __FUNCT__ "TSGetApplicationContext"
908 /*@C
909     TSGetApplicationContext - Gets the user-defined context for the
910     timestepper.
911 
912     Not Collective
913 
914     Input Parameter:
915 .   ts - the TS context obtained from TSCreate()
916 
917     Output Parameter:
918 .   usrP - user context
919 
920     Level: intermediate
921 
922 .keywords: TS, timestep, get, application, context
923 
924 .seealso: TSSetApplicationContext()
925 @*/
926 PetscErrorCode  TSGetApplicationContext(TS ts,void **usrP)
927 {
928   PetscFunctionBegin;
929   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
930   *usrP = ts->user;
931   PetscFunctionReturn(0);
932 }
933 
934 #undef __FUNCT__
935 #define __FUNCT__ "TSGetTimeStepNumber"
936 /*@
937    TSGetTimeStepNumber - Gets the current number of timesteps.
938 
939    Not Collective
940 
941    Input Parameter:
942 .  ts - the TS context obtained from TSCreate()
943 
944    Output Parameter:
945 .  iter - number steps so far
946 
947    Level: intermediate
948 
949 .keywords: TS, timestep, get, iteration, number
950 @*/
951 PetscErrorCode  TSGetTimeStepNumber(TS ts,PetscInt* iter)
952 {
953   PetscFunctionBegin;
954   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
955   PetscValidIntPointer(iter,2);
956   *iter = ts->steps;
957   PetscFunctionReturn(0);
958 }
959 
960 #undef __FUNCT__
961 #define __FUNCT__ "TSSetInitialTimeStep"
962 /*@
963    TSSetInitialTimeStep - Sets the initial timestep to be used,
964    as well as the initial time.
965 
966    Logically Collective on TS
967 
968    Input Parameters:
969 +  ts - the TS context obtained from TSCreate()
970 .  initial_time - the initial time
971 -  time_step - the size of the timestep
972 
973    Level: intermediate
974 
975 .seealso: TSSetTimeStep(), TSGetTimeStep()
976 
977 .keywords: TS, set, initial, timestep
978 @*/
979 PetscErrorCode  TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step)
980 {
981   PetscFunctionBegin;
982   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
983   ts->time_step         = time_step;
984   ts->initial_time_step = time_step;
985   ts->ptime             = initial_time;
986   PetscFunctionReturn(0);
987 }
988 
989 #undef __FUNCT__
990 #define __FUNCT__ "TSSetTimeStep"
991 /*@
992    TSSetTimeStep - Allows one to reset the timestep at any time,
993    useful for simple pseudo-timestepping codes.
994 
995    Logically Collective on TS
996 
997    Input Parameters:
998 +  ts - the TS context obtained from TSCreate()
999 -  time_step - the size of the timestep
1000 
1001    Level: intermediate
1002 
1003 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1004 
1005 .keywords: TS, set, timestep
1006 @*/
1007 PetscErrorCode  TSSetTimeStep(TS ts,PetscReal time_step)
1008 {
1009   PetscFunctionBegin;
1010   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1011   PetscValidLogicalCollectiveReal(ts,time_step,2);
1012   ts->time_step = time_step;
1013   PetscFunctionReturn(0);
1014 }
1015 
1016 #undef __FUNCT__
1017 #define __FUNCT__ "TSGetTimeStep"
1018 /*@
1019    TSGetTimeStep - Gets the current timestep size.
1020 
1021    Not Collective
1022 
1023    Input Parameter:
1024 .  ts - the TS context obtained from TSCreate()
1025 
1026    Output Parameter:
1027 .  dt - the current timestep size
1028 
1029    Level: intermediate
1030 
1031 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1032 
1033 .keywords: TS, get, timestep
1034 @*/
1035 PetscErrorCode  TSGetTimeStep(TS ts,PetscReal* dt)
1036 {
1037   PetscFunctionBegin;
1038   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1039   PetscValidDoublePointer(dt,2);
1040   *dt = ts->time_step;
1041   PetscFunctionReturn(0);
1042 }
1043 
1044 #undef __FUNCT__
1045 #define __FUNCT__ "TSGetSolution"
1046 /*@
1047    TSGetSolution - Returns the solution at the present timestep. It
1048    is valid to call this routine inside the function that you are evaluating
1049    in order to move to the new timestep. This vector not changed until
1050    the solution at the next timestep has been calculated.
1051 
1052    Not Collective, but Vec returned is parallel if TS is parallel
1053 
1054    Input Parameter:
1055 .  ts - the TS context obtained from TSCreate()
1056 
1057    Output Parameter:
1058 .  v - the vector containing the solution
1059 
1060    Level: intermediate
1061 
1062 .seealso: TSGetTimeStep()
1063 
1064 .keywords: TS, timestep, get, solution
1065 @*/
1066 PetscErrorCode  TSGetSolution(TS ts,Vec *v)
1067 {
1068   PetscFunctionBegin;
1069   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1070   PetscValidPointer(v,2);
1071   *v = ts->vec_sol_always;
1072   PetscFunctionReturn(0);
1073 }
1074 
1075 /* ----- Routines to initialize and destroy a timestepper ---- */
1076 #undef __FUNCT__
1077 #define __FUNCT__ "TSSetProblemType"
1078 /*@
1079   TSSetProblemType - Sets the type of problem to be solved.
1080 
1081   Not collective
1082 
1083   Input Parameters:
1084 + ts   - The TS
1085 - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1086 .vb
1087          U_t = A U
1088          U_t = A(t) U
1089          U_t = F(t,U)
1090 .ve
1091 
1092    Level: beginner
1093 
1094 .keywords: TS, problem type
1095 .seealso: TSSetUp(), TSProblemType, TS
1096 @*/
1097 PetscErrorCode  TSSetProblemType(TS ts, TSProblemType type)
1098 {
1099   PetscFunctionBegin;
1100   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1101   ts->problem_type = type;
1102   PetscFunctionReturn(0);
1103 }
1104 
1105 #undef __FUNCT__
1106 #define __FUNCT__ "TSGetProblemType"
1107 /*@C
1108   TSGetProblemType - Gets the type of problem to be solved.
1109 
1110   Not collective
1111 
1112   Input Parameter:
1113 . ts   - The TS
1114 
1115   Output Parameter:
1116 . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1117 .vb
1118          U_t = A U
1119          U_t = A(t) U
1120          U_t = F(t,U)
1121 .ve
1122 
1123    Level: beginner
1124 
1125 .keywords: TS, problem type
1126 .seealso: TSSetUp(), TSProblemType, TS
1127 @*/
1128 PetscErrorCode  TSGetProblemType(TS ts, TSProblemType *type)
1129 {
1130   PetscFunctionBegin;
1131   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1132   PetscValidIntPointer(type,2);
1133   *type = ts->problem_type;
1134   PetscFunctionReturn(0);
1135 }
1136 
1137 #undef __FUNCT__
1138 #define __FUNCT__ "TSSetUp"
1139 /*@
1140    TSSetUp - Sets up the internal data structures for the later use
1141    of a timestepper.
1142 
1143    Collective on TS
1144 
1145    Input Parameter:
1146 .  ts - the TS context obtained from TSCreate()
1147 
1148    Notes:
1149    For basic use of the TS solvers the user need not explicitly call
1150    TSSetUp(), since these actions will automatically occur during
1151    the call to TSStep().  However, if one wishes to control this
1152    phase separately, TSSetUp() should be called after TSCreate()
1153    and optional routines of the form TSSetXXX(), but before TSStep().
1154 
1155    Level: advanced
1156 
1157 .keywords: TS, timestep, setup
1158 
1159 .seealso: TSCreate(), TSStep(), TSDestroy()
1160 @*/
1161 PetscErrorCode  TSSetUp(TS ts)
1162 {
1163   PetscErrorCode ierr;
1164 
1165   PetscFunctionBegin;
1166   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1167   if (!ts->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first");
1168   if (!((PetscObject)ts)->type_name) {
1169     ierr = TSSetType(ts,TSEULER);CHKERRQ(ierr);
1170   }
1171   ierr = (*ts->ops->setup)(ts);CHKERRQ(ierr);
1172   ts->setupcalled = 1;
1173   PetscFunctionReturn(0);
1174 }
1175 
1176 #undef __FUNCT__
1177 #define __FUNCT__ "TSDestroy"
1178 /*@
1179    TSDestroy - Destroys the timestepper context that was created
1180    with TSCreate().
1181 
1182    Collective on TS
1183 
1184    Input Parameter:
1185 .  ts - the TS context obtained from TSCreate()
1186 
1187    Level: beginner
1188 
1189 .keywords: TS, timestepper, destroy
1190 
1191 .seealso: TSCreate(), TSSetUp(), TSSolve()
1192 @*/
1193 PetscErrorCode  TSDestroy(TS ts)
1194 {
1195   PetscErrorCode ierr;
1196 
1197   PetscFunctionBegin;
1198   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1199   if (--((PetscObject)ts)->refct > 0) PetscFunctionReturn(0);
1200 
1201   /* if memory was published with AMS then destroy it */
1202   ierr = PetscObjectDepublish(ts);CHKERRQ(ierr);
1203 
1204   if (ts->dm) {ierr = DMDestroy(ts->dm);CHKERRQ(ierr);}
1205   if (ts->A) {ierr = MatDestroy(ts->A);CHKERRQ(ierr);}
1206   if (ts->ksp) {ierr = KSPDestroy(ts->ksp);CHKERRQ(ierr);}
1207   if (ts->snes) {ierr = SNESDestroy(ts->snes);CHKERRQ(ierr);}
1208   if (ts->ops->destroy) {ierr = (*(ts)->ops->destroy)(ts);CHKERRQ(ierr);}
1209   ierr = TSMonitorCancel(ts);CHKERRQ(ierr);
1210   ierr = PetscHeaderDestroy(ts);CHKERRQ(ierr);
1211   PetscFunctionReturn(0);
1212 }
1213 
1214 #undef __FUNCT__
1215 #define __FUNCT__ "TSGetSNES"
1216 /*@
1217    TSGetSNES - Returns the SNES (nonlinear solver) associated with
1218    a TS (timestepper) context. Valid only for nonlinear problems.
1219 
1220    Not Collective, but SNES is parallel if TS is parallel
1221 
1222    Input Parameter:
1223 .  ts - the TS context obtained from TSCreate()
1224 
1225    Output Parameter:
1226 .  snes - the nonlinear solver context
1227 
1228    Notes:
1229    The user can then directly manipulate the SNES context to set various
1230    options, etc.  Likewise, the user can then extract and manipulate the
1231    KSP, KSP, and PC contexts as well.
1232 
1233    TSGetSNES() does not work for integrators that do not use SNES; in
1234    this case TSGetSNES() returns PETSC_NULL in snes.
1235 
1236    Level: beginner
1237 
1238 .keywords: timestep, get, SNES
1239 @*/
1240 PetscErrorCode  TSGetSNES(TS ts,SNES *snes)
1241 {
1242   PetscFunctionBegin;
1243   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1244   PetscValidPointer(snes,2);
1245   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"SNES is not created yet. Call TSSetType() first");
1246   if (ts->problem_type == TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Nonlinear only; use TSGetKSP()");
1247   *snes = ts->snes;
1248   PetscFunctionReturn(0);
1249 }
1250 
1251 #undef __FUNCT__
1252 #define __FUNCT__ "TSGetKSP"
1253 /*@
1254    TSGetKSP - Returns the KSP (linear solver) associated with
1255    a TS (timestepper) context.
1256 
1257    Not Collective, but KSP is parallel if TS is parallel
1258 
1259    Input Parameter:
1260 .  ts - the TS context obtained from TSCreate()
1261 
1262    Output Parameter:
1263 .  ksp - the nonlinear solver context
1264 
1265    Notes:
1266    The user can then directly manipulate the KSP context to set various
1267    options, etc.  Likewise, the user can then extract and manipulate the
1268    KSP and PC contexts as well.
1269 
1270    TSGetKSP() does not work for integrators that do not use KSP;
1271    in this case TSGetKSP() returns PETSC_NULL in ksp.
1272 
1273    Level: beginner
1274 
1275 .keywords: timestep, get, KSP
1276 @*/
1277 PetscErrorCode  TSGetKSP(TS ts,KSP *ksp)
1278 {
1279   PetscFunctionBegin;
1280   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1281   PetscValidPointer(ksp,2);
1282   if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
1283   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
1284   *ksp = ts->ksp;
1285   PetscFunctionReturn(0);
1286 }
1287 
1288 /* ----------- Routines to set solver parameters ---------- */
1289 
1290 #undef __FUNCT__
1291 #define __FUNCT__ "TSGetDuration"
1292 /*@
1293    TSGetDuration - Gets the maximum number of timesteps to use and
1294    maximum time for iteration.
1295 
1296    Not Collective
1297 
1298    Input Parameters:
1299 +  ts       - the TS context obtained from TSCreate()
1300 .  maxsteps - maximum number of iterations to use, or PETSC_NULL
1301 -  maxtime  - final time to iterate to, or PETSC_NULL
1302 
1303    Level: intermediate
1304 
1305 .keywords: TS, timestep, get, maximum, iterations, time
1306 @*/
1307 PetscErrorCode  TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
1308 {
1309   PetscFunctionBegin;
1310   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1311   if (maxsteps) {
1312     PetscValidIntPointer(maxsteps,2);
1313     *maxsteps = ts->max_steps;
1314   }
1315   if (maxtime ) {
1316     PetscValidScalarPointer(maxtime,3);
1317     *maxtime  = ts->max_time;
1318   }
1319   PetscFunctionReturn(0);
1320 }
1321 
1322 #undef __FUNCT__
1323 #define __FUNCT__ "TSSetDuration"
1324 /*@
1325    TSSetDuration - Sets the maximum number of timesteps to use and
1326    maximum time for iteration.
1327 
1328    Logically Collective on TS
1329 
1330    Input Parameters:
1331 +  ts - the TS context obtained from TSCreate()
1332 .  maxsteps - maximum number of iterations to use
1333 -  maxtime - final time to iterate to
1334 
1335    Options Database Keys:
1336 .  -ts_max_steps <maxsteps> - Sets maxsteps
1337 .  -ts_max_time <maxtime> - Sets maxtime
1338 
1339    Notes:
1340    The default maximum number of iterations is 5000. Default time is 5.0
1341 
1342    Level: intermediate
1343 
1344 .keywords: TS, timestep, set, maximum, iterations
1345 @*/
1346 PetscErrorCode  TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
1347 {
1348   PetscFunctionBegin;
1349   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1350   PetscValidLogicalCollectiveInt(ts,maxsteps,2);
1351   PetscValidLogicalCollectiveReal(ts,maxtime,2);
1352   ts->max_steps = maxsteps;
1353   ts->max_time  = maxtime;
1354   PetscFunctionReturn(0);
1355 }
1356 
1357 #undef __FUNCT__
1358 #define __FUNCT__ "TSSetSolution"
1359 /*@
1360    TSSetSolution - Sets the initial solution vector
1361    for use by the TS routines.
1362 
1363    Logically Collective on TS and Vec
1364 
1365    Input Parameters:
1366 +  ts - the TS context obtained from TSCreate()
1367 -  x - the solution vector
1368 
1369    Level: beginner
1370 
1371 .keywords: TS, timestep, set, solution, initial conditions
1372 @*/
1373 PetscErrorCode  TSSetSolution(TS ts,Vec x)
1374 {
1375   PetscFunctionBegin;
1376   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1377   PetscValidHeaderSpecific(x,VEC_CLASSID,2);
1378   ts->vec_sol        = ts->vec_sol_always = x;
1379   PetscFunctionReturn(0);
1380 }
1381 
1382 #undef __FUNCT__
1383 #define __FUNCT__ "TSSetPreStep"
1384 /*@C
1385   TSSetPreStep - Sets the general-purpose function
1386   called once at the beginning of each time step.
1387 
1388   Logically Collective on TS
1389 
1390   Input Parameters:
1391 + ts   - The TS context obtained from TSCreate()
1392 - func - The function
1393 
1394   Calling sequence of func:
1395 . func (TS ts);
1396 
1397   Level: intermediate
1398 
1399 .keywords: TS, timestep
1400 @*/
1401 PetscErrorCode  TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
1402 {
1403   PetscFunctionBegin;
1404   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1405   ts->ops->prestep = func;
1406   PetscFunctionReturn(0);
1407 }
1408 
1409 #undef __FUNCT__
1410 #define __FUNCT__ "TSPreStep"
1411 /*@C
1412   TSPreStep - Runs the user-defined pre-step function.
1413 
1414   Collective on TS
1415 
1416   Input Parameters:
1417 . ts   - The TS context obtained from TSCreate()
1418 
1419   Notes:
1420   TSPreStep() is typically used within time stepping implementations,
1421   so most users would not generally call this routine themselves.
1422 
1423   Level: developer
1424 
1425 .keywords: TS, timestep
1426 @*/
1427 PetscErrorCode  TSPreStep(TS ts)
1428 {
1429   PetscErrorCode ierr;
1430 
1431   PetscFunctionBegin;
1432   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1433   if (ts->ops->prestep) {
1434     PetscStackPush("TS PreStep function");
1435     ierr = (*ts->ops->prestep)(ts);CHKERRQ(ierr);
1436     PetscStackPop;
1437   }
1438   PetscFunctionReturn(0);
1439 }
1440 
1441 #undef __FUNCT__
1442 #define __FUNCT__ "TSDefaultPreStep"
1443 /*@
1444   TSDefaultPreStep - The default pre-stepping function which does nothing.
1445 
1446   Collective on TS
1447 
1448   Input Parameters:
1449 . ts  - The TS context obtained from TSCreate()
1450 
1451   Level: developer
1452 
1453 .keywords: TS, timestep
1454 @*/
1455 PetscErrorCode  TSDefaultPreStep(TS ts)
1456 {
1457   PetscFunctionBegin;
1458   PetscFunctionReturn(0);
1459 }
1460 
1461 #undef __FUNCT__
1462 #define __FUNCT__ "TSSetPostStep"
1463 /*@C
1464   TSSetPostStep - Sets the general-purpose function
1465   called once at the end of each time step.
1466 
1467   Logically Collective on TS
1468 
1469   Input Parameters:
1470 + ts   - The TS context obtained from TSCreate()
1471 - func - The function
1472 
1473   Calling sequence of func:
1474 . func (TS ts);
1475 
1476   Level: intermediate
1477 
1478 .keywords: TS, timestep
1479 @*/
1480 PetscErrorCode  TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
1481 {
1482   PetscFunctionBegin;
1483   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1484   ts->ops->poststep = func;
1485   PetscFunctionReturn(0);
1486 }
1487 
1488 #undef __FUNCT__
1489 #define __FUNCT__ "TSPostStep"
1490 /*@C
1491   TSPostStep - Runs the user-defined post-step function.
1492 
1493   Collective on TS
1494 
1495   Input Parameters:
1496 . ts   - The TS context obtained from TSCreate()
1497 
1498   Notes:
1499   TSPostStep() is typically used within time stepping implementations,
1500   so most users would not generally call this routine themselves.
1501 
1502   Level: developer
1503 
1504 .keywords: TS, timestep
1505 @*/
1506 PetscErrorCode  TSPostStep(TS ts)
1507 {
1508   PetscErrorCode ierr;
1509 
1510   PetscFunctionBegin;
1511   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1512   if (ts->ops->poststep) {
1513     PetscStackPush("TS PostStep function");
1514     ierr = (*ts->ops->poststep)(ts);CHKERRQ(ierr);
1515     PetscStackPop;
1516   }
1517   PetscFunctionReturn(0);
1518 }
1519 
1520 #undef __FUNCT__
1521 #define __FUNCT__ "TSDefaultPostStep"
1522 /*@
1523   TSDefaultPostStep - The default post-stepping function which does nothing.
1524 
1525   Collective on TS
1526 
1527   Input Parameters:
1528 . ts  - The TS context obtained from TSCreate()
1529 
1530   Level: developer
1531 
1532 .keywords: TS, timestep
1533 @*/
1534 PetscErrorCode  TSDefaultPostStep(TS ts)
1535 {
1536   PetscFunctionBegin;
1537   PetscFunctionReturn(0);
1538 }
1539 
1540 /* ------------ Routines to set performance monitoring options ----------- */
1541 
1542 #undef __FUNCT__
1543 #define __FUNCT__ "TSMonitorSet"
1544 /*@C
1545    TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
1546    timestep to display the iteration's  progress.
1547 
1548    Logically Collective on TS
1549 
1550    Input Parameters:
1551 +  ts - the TS context obtained from TSCreate()
1552 .  func - monitoring routine
1553 .  mctx - [optional] user-defined context for private data for the
1554              monitor routine (use PETSC_NULL if no context is desired)
1555 -  monitordestroy - [optional] routine that frees monitor context
1556           (may be PETSC_NULL)
1557 
1558    Calling sequence of func:
1559 $    int func(TS ts,PetscInt steps,PetscReal time,Vec x,void *mctx)
1560 
1561 +    ts - the TS context
1562 .    steps - iteration number
1563 .    time - current time
1564 .    x - current iterate
1565 -    mctx - [optional] monitoring context
1566 
1567    Notes:
1568    This routine adds an additional monitor to the list of monitors that
1569    already has been loaded.
1570 
1571    Fortran notes: Only a single monitor function can be set for each TS object
1572 
1573    Level: intermediate
1574 
1575 .keywords: TS, timestep, set, monitor
1576 
1577 .seealso: TSMonitorDefault(), TSMonitorCancel()
1578 @*/
1579 PetscErrorCode  TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void*))
1580 {
1581   PetscFunctionBegin;
1582   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1583   if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
1584   ts->monitor[ts->numbermonitors]           = monitor;
1585   ts->mdestroy[ts->numbermonitors]          = mdestroy;
1586   ts->monitorcontext[ts->numbermonitors++]  = (void*)mctx;
1587   PetscFunctionReturn(0);
1588 }
1589 
1590 #undef __FUNCT__
1591 #define __FUNCT__ "TSMonitorCancel"
1592 /*@C
1593    TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
1594 
1595    Logically Collective on TS
1596 
1597    Input Parameters:
1598 .  ts - the TS context obtained from TSCreate()
1599 
1600    Notes:
1601    There is no way to remove a single, specific monitor.
1602 
1603    Level: intermediate
1604 
1605 .keywords: TS, timestep, set, monitor
1606 
1607 .seealso: TSMonitorDefault(), TSMonitorSet()
1608 @*/
1609 PetscErrorCode  TSMonitorCancel(TS ts)
1610 {
1611   PetscErrorCode ierr;
1612   PetscInt       i;
1613 
1614   PetscFunctionBegin;
1615   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1616   for (i=0; i<ts->numbermonitors; i++) {
1617     if (ts->mdestroy[i]) {
1618       ierr = (*ts->mdestroy[i])(ts->monitorcontext[i]);CHKERRQ(ierr);
1619     }
1620   }
1621   ts->numbermonitors = 0;
1622   PetscFunctionReturn(0);
1623 }
1624 
1625 #undef __FUNCT__
1626 #define __FUNCT__ "TSMonitorDefault"
1627 /*@
1628    TSMonitorDefault - Sets the Default monitor
1629 
1630    Level: intermediate
1631 
1632 .keywords: TS, set, monitor
1633 
1634 .seealso: TSMonitorDefault(), TSMonitorSet()
1635 @*/
1636 PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *ctx)
1637 {
1638   PetscErrorCode          ierr;
1639   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor)ctx;
1640 
1641   PetscFunctionBegin;
1642   if (!ctx) {
1643     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)ts)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
1644   }
1645   ierr = PetscViewerASCIIMonitorPrintf(viewer,"%D TS dt %G time %G\n",step,ts->time_step,ptime);CHKERRQ(ierr);
1646   if (!ctx) {
1647     ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr);
1648   }
1649   PetscFunctionReturn(0);
1650 }
1651 
1652 #undef __FUNCT__
1653 #define __FUNCT__ "TSStep"
1654 /*@
1655    TSStep - Steps the requested number of timesteps.
1656 
1657    Collective on TS
1658 
1659    Input Parameter:
1660 .  ts - the TS context obtained from TSCreate()
1661 
1662    Output Parameters:
1663 +  steps - number of iterations until termination
1664 -  ptime - time until termination
1665 
1666    Level: beginner
1667 
1668 .keywords: TS, timestep, solve
1669 
1670 .seealso: TSCreate(), TSSetUp(), TSDestroy()
1671 @*/
1672 PetscErrorCode  TSStep(TS ts,PetscInt *steps,PetscReal *ptime)
1673 {
1674   PetscErrorCode ierr;
1675 
1676   PetscFunctionBegin;
1677   PetscValidHeaderSpecific(ts, TS_CLASSID,1);
1678   if (!ts->setupcalled) {
1679     ierr = TSSetUp(ts);CHKERRQ(ierr);
1680   }
1681 
1682   ierr = PetscLogEventBegin(TS_Step, ts, 0, 0, 0);CHKERRQ(ierr);
1683   ierr = (*ts->ops->step)(ts, steps, ptime);CHKERRQ(ierr);
1684   ierr = PetscLogEventEnd(TS_Step, ts, 0, 0, 0);CHKERRQ(ierr);
1685 
1686   if (!PetscPreLoadingOn) {
1687     ierr = TSViewFromOptions(ts,((PetscObject)ts)->name);CHKERRQ(ierr);
1688   }
1689   PetscFunctionReturn(0);
1690 }
1691 
1692 #undef __FUNCT__
1693 #define __FUNCT__ "TSSolve"
1694 /*@
1695    TSSolve - Steps the requested number of timesteps.
1696 
1697    Collective on TS
1698 
1699    Input Parameter:
1700 +  ts - the TS context obtained from TSCreate()
1701 -  x - the solution vector, or PETSC_NULL if it was set with TSSetSolution()
1702 
1703    Level: beginner
1704 
1705 .keywords: TS, timestep, solve
1706 
1707 .seealso: TSCreate(), TSSetSolution(), TSStep()
1708 @*/
1709 PetscErrorCode  TSSolve(TS ts, Vec x)
1710 {
1711   PetscInt       steps;
1712   PetscReal      ptime;
1713   PetscErrorCode ierr;
1714 
1715   PetscFunctionBegin;
1716   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1717   /* set solution vector if provided */
1718   if (x) { ierr = TSSetSolution(ts, x); CHKERRQ(ierr); }
1719   /* reset time step and iteration counters */
1720   ts->steps = 0; ts->linear_its = 0; ts->nonlinear_its = 0;
1721   /* steps the requested number of timesteps. */
1722   ierr = TSStep(ts, &steps, &ptime);CHKERRQ(ierr);
1723   PetscFunctionReturn(0);
1724 }
1725 
1726 #undef __FUNCT__
1727 #define __FUNCT__ "TSMonitor"
1728 /*
1729      Runs the user provided monitor routines, if they exists.
1730 */
1731 PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec x)
1732 {
1733   PetscErrorCode ierr;
1734   PetscInt       i,n = ts->numbermonitors;
1735 
1736   PetscFunctionBegin;
1737   for (i=0; i<n; i++) {
1738     ierr = (*ts->monitor[i])(ts,step,ptime,x,ts->monitorcontext[i]);CHKERRQ(ierr);
1739   }
1740   PetscFunctionReturn(0);
1741 }
1742 
1743 /* ------------------------------------------------------------------------*/
1744 
1745 #undef __FUNCT__
1746 #define __FUNCT__ "TSMonitorLGCreate"
1747 /*@C
1748    TSMonitorLGCreate - Creates a line graph context for use with
1749    TS to monitor convergence of preconditioned residual norms.
1750 
1751    Collective on TS
1752 
1753    Input Parameters:
1754 +  host - the X display to open, or null for the local machine
1755 .  label - the title to put in the title bar
1756 .  x, y - the screen coordinates of the upper left coordinate of the window
1757 -  m, n - the screen width and height in pixels
1758 
1759    Output Parameter:
1760 .  draw - the drawing context
1761 
1762    Options Database Key:
1763 .  -ts_monitor_draw - automatically sets line graph monitor
1764 
1765    Notes:
1766    Use TSMonitorLGDestroy() to destroy this line graph, not PetscDrawLGDestroy().
1767 
1768    Level: intermediate
1769 
1770 .keywords: TS, monitor, line graph, residual, seealso
1771 
1772 .seealso: TSMonitorLGDestroy(), TSMonitorSet()
1773 
1774 @*/
1775 PetscErrorCode  TSMonitorLGCreate(const char host[],const char label[],int x,int y,int m,int n,PetscDrawLG *draw)
1776 {
1777   PetscDraw      win;
1778   PetscErrorCode ierr;
1779 
1780   PetscFunctionBegin;
1781   ierr = PetscDrawCreate(PETSC_COMM_SELF,host,label,x,y,m,n,&win);CHKERRQ(ierr);
1782   ierr = PetscDrawSetType(win,PETSC_DRAW_X);CHKERRQ(ierr);
1783   ierr = PetscDrawLGCreate(win,1,draw);CHKERRQ(ierr);
1784   ierr = PetscDrawLGIndicateDataPoints(*draw);CHKERRQ(ierr);
1785 
1786   ierr = PetscLogObjectParent(*draw,win);CHKERRQ(ierr);
1787   PetscFunctionReturn(0);
1788 }
1789 
1790 #undef __FUNCT__
1791 #define __FUNCT__ "TSMonitorLG"
1792 PetscErrorCode TSMonitorLG(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
1793 {
1794   PetscDrawLG    lg = (PetscDrawLG) monctx;
1795   PetscReal      x,y = ptime;
1796   PetscErrorCode ierr;
1797 
1798   PetscFunctionBegin;
1799   if (!monctx) {
1800     MPI_Comm    comm;
1801     PetscViewer viewer;
1802 
1803     ierr   = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr);
1804     viewer = PETSC_VIEWER_DRAW_(comm);
1805     ierr   = PetscViewerDrawGetDrawLG(viewer,0,&lg);CHKERRQ(ierr);
1806   }
1807 
1808   if (!n) {ierr = PetscDrawLGReset(lg);CHKERRQ(ierr);}
1809   x = (PetscReal)n;
1810   ierr = PetscDrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr);
1811   if (n < 20 || (n % 5)) {
1812     ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr);
1813   }
1814   PetscFunctionReturn(0);
1815 }
1816 
1817 #undef __FUNCT__
1818 #define __FUNCT__ "TSMonitorLGDestroy"
1819 /*@C
1820    TSMonitorLGDestroy - Destroys a line graph context that was created
1821    with TSMonitorLGCreate().
1822 
1823    Collective on PetscDrawLG
1824 
1825    Input Parameter:
1826 .  draw - the drawing context
1827 
1828    Level: intermediate
1829 
1830 .keywords: TS, monitor, line graph, destroy
1831 
1832 .seealso: TSMonitorLGCreate(),  TSMonitorSet(), TSMonitorLG();
1833 @*/
1834 PetscErrorCode  TSMonitorLGDestroy(PetscDrawLG drawlg)
1835 {
1836   PetscDraw      draw;
1837   PetscErrorCode ierr;
1838 
1839   PetscFunctionBegin;
1840   ierr = PetscDrawLGGetDraw(drawlg,&draw);CHKERRQ(ierr);
1841   ierr = PetscDrawDestroy(draw);CHKERRQ(ierr);
1842   ierr = PetscDrawLGDestroy(drawlg);CHKERRQ(ierr);
1843   PetscFunctionReturn(0);
1844 }
1845 
1846 #undef __FUNCT__
1847 #define __FUNCT__ "TSGetTime"
1848 /*@
1849    TSGetTime - Gets the current time.
1850 
1851    Not Collective
1852 
1853    Input Parameter:
1854 .  ts - the TS context obtained from TSCreate()
1855 
1856    Output Parameter:
1857 .  t  - the current time
1858 
1859    Level: beginner
1860 
1861 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1862 
1863 .keywords: TS, get, time
1864 @*/
1865 PetscErrorCode  TSGetTime(TS ts,PetscReal* t)
1866 {
1867   PetscFunctionBegin;
1868   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1869   PetscValidDoublePointer(t,2);
1870   *t = ts->ptime;
1871   PetscFunctionReturn(0);
1872 }
1873 
1874 #undef __FUNCT__
1875 #define __FUNCT__ "TSSetTime"
1876 /*@
1877    TSSetTime - Allows one to reset the time.
1878 
1879    Logically Collective on TS
1880 
1881    Input Parameters:
1882 +  ts - the TS context obtained from TSCreate()
1883 -  time - the time
1884 
1885    Level: intermediate
1886 
1887 .seealso: TSGetTime(), TSSetDuration()
1888 
1889 .keywords: TS, set, time
1890 @*/
1891 PetscErrorCode  TSSetTime(TS ts, PetscReal t)
1892 {
1893   PetscFunctionBegin;
1894   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1895   PetscValidLogicalCollectiveReal(ts,t,2);
1896   ts->ptime = t;
1897   PetscFunctionReturn(0);
1898 }
1899 
1900 #undef __FUNCT__
1901 #define __FUNCT__ "TSSetOptionsPrefix"
1902 /*@C
1903    TSSetOptionsPrefix - Sets the prefix used for searching for all
1904    TS options in the database.
1905 
1906    Logically Collective on TS
1907 
1908    Input Parameter:
1909 +  ts     - The TS context
1910 -  prefix - The prefix to prepend to all option names
1911 
1912    Notes:
1913    A hyphen (-) must NOT be given at the beginning of the prefix name.
1914    The first character of all runtime options is AUTOMATICALLY the
1915    hyphen.
1916 
1917    Level: advanced
1918 
1919 .keywords: TS, set, options, prefix, database
1920 
1921 .seealso: TSSetFromOptions()
1922 
1923 @*/
1924 PetscErrorCode  TSSetOptionsPrefix(TS ts,const char prefix[])
1925 {
1926   PetscErrorCode ierr;
1927 
1928   PetscFunctionBegin;
1929   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1930   ierr = PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
1931   switch(ts->problem_type) {
1932     case TS_NONLINEAR:
1933       if (ts->snes) {
1934         ierr = SNESSetOptionsPrefix(ts->snes,prefix);CHKERRQ(ierr);
1935       }
1936       break;
1937     case TS_LINEAR:
1938       if (ts->ksp) {
1939         ierr = KSPSetOptionsPrefix(ts->ksp,prefix);CHKERRQ(ierr);
1940       }
1941       break;
1942   }
1943   PetscFunctionReturn(0);
1944 }
1945 
1946 
1947 #undef __FUNCT__
1948 #define __FUNCT__ "TSAppendOptionsPrefix"
1949 /*@C
1950    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
1951    TS options in the database.
1952 
1953    Logically Collective on TS
1954 
1955    Input Parameter:
1956 +  ts     - The TS context
1957 -  prefix - The prefix to prepend to all option names
1958 
1959    Notes:
1960    A hyphen (-) must NOT be given at the beginning of the prefix name.
1961    The first character of all runtime options is AUTOMATICALLY the
1962    hyphen.
1963 
1964    Level: advanced
1965 
1966 .keywords: TS, append, options, prefix, database
1967 
1968 .seealso: TSGetOptionsPrefix()
1969 
1970 @*/
1971 PetscErrorCode  TSAppendOptionsPrefix(TS ts,const char prefix[])
1972 {
1973   PetscErrorCode ierr;
1974 
1975   PetscFunctionBegin;
1976   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
1977   ierr = PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
1978   switch(ts->problem_type) {
1979     case TS_NONLINEAR:
1980       if (ts->snes) {
1981         ierr = SNESAppendOptionsPrefix(ts->snes,prefix);CHKERRQ(ierr);
1982       }
1983       break;
1984     case TS_LINEAR:
1985       if (ts->ksp) {
1986         ierr = KSPAppendOptionsPrefix(ts->ksp,prefix);CHKERRQ(ierr);
1987       }
1988       break;
1989   }
1990   PetscFunctionReturn(0);
1991 }
1992 
1993 #undef __FUNCT__
1994 #define __FUNCT__ "TSGetOptionsPrefix"
1995 /*@C
1996    TSGetOptionsPrefix - Sets the prefix used for searching for all
1997    TS options in the database.
1998 
1999    Not Collective
2000 
2001    Input Parameter:
2002 .  ts - The TS context
2003 
2004    Output Parameter:
2005 .  prefix - A pointer to the prefix string used
2006 
2007    Notes: On the fortran side, the user should pass in a string 'prifix' of
2008    sufficient length to hold the prefix.
2009 
2010    Level: intermediate
2011 
2012 .keywords: TS, get, options, prefix, database
2013 
2014 .seealso: TSAppendOptionsPrefix()
2015 @*/
2016 PetscErrorCode  TSGetOptionsPrefix(TS ts,const char *prefix[])
2017 {
2018   PetscErrorCode ierr;
2019 
2020   PetscFunctionBegin;
2021   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2022   PetscValidPointer(prefix,2);
2023   ierr = PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);CHKERRQ(ierr);
2024   PetscFunctionReturn(0);
2025 }
2026 
2027 #undef __FUNCT__
2028 #define __FUNCT__ "TSGetRHSJacobian"
2029 /*@C
2030    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
2031 
2032    Not Collective, but parallel objects are returned if TS is parallel
2033 
2034    Input Parameter:
2035 .  ts  - The TS context obtained from TSCreate()
2036 
2037    Output Parameters:
2038 +  J   - The Jacobian J of F, where U_t = F(U,t)
2039 .  M   - The preconditioner matrix, usually the same as J
2040 - ctx - User-defined context for Jacobian evaluation routine
2041 
2042    Notes: You can pass in PETSC_NULL for any return argument you do not need.
2043 
2044    Level: intermediate
2045 
2046 .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
2047 
2048 .keywords: TS, timestep, get, matrix, Jacobian
2049 @*/
2050 PetscErrorCode  TSGetRHSJacobian(TS ts,Mat *J,Mat *M,void **ctx)
2051 {
2052   PetscFunctionBegin;
2053   if (J) *J = ts->Arhs;
2054   if (M) *M = ts->B;
2055   if (ctx) *ctx = ts->jacP;
2056   PetscFunctionReturn(0);
2057 }
2058 
2059 #undef __FUNCT__
2060 #define __FUNCT__ "TSGetIJacobian"
2061 /*@C
2062    TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
2063 
2064    Not Collective, but parallel objects are returned if TS is parallel
2065 
2066    Input Parameter:
2067 .  ts  - The TS context obtained from TSCreate()
2068 
2069    Output Parameters:
2070 +  A   - The Jacobian of F(t,U,U_t)
2071 .  B   - The preconditioner matrix, often the same as A
2072 .  f   - The function to compute the matrices
2073 - ctx - User-defined context for Jacobian evaluation routine
2074 
2075    Notes: You can pass in PETSC_NULL for any return argument you do not need.
2076 
2077    Level: advanced
2078 
2079 .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
2080 
2081 .keywords: TS, timestep, get, matrix, Jacobian
2082 @*/
2083 PetscErrorCode  TSGetIJacobian(TS ts,Mat *A,Mat *B,TSIJacobian *f,void **ctx)
2084 {
2085   PetscFunctionBegin;
2086   if (A) *A = ts->A;
2087   if (B) *B = ts->B;
2088   if (f) *f = ts->ops->ijacobian;
2089   if (ctx) *ctx = ts->jacP;
2090   PetscFunctionReturn(0);
2091 }
2092 
2093 #undef __FUNCT__
2094 #define __FUNCT__ "TSMonitorSolution"
2095 /*@C
2096    TSMonitorSolution - Monitors progress of the TS solvers by calling
2097    VecView() for the solution at each timestep
2098 
2099    Collective on TS
2100 
2101    Input Parameters:
2102 +  ts - the TS context
2103 .  step - current time-step
2104 .  ptime - current time
2105 -  dummy - either a viewer or PETSC_NULL
2106 
2107    Level: intermediate
2108 
2109 .keywords: TS,  vector, monitor, view
2110 
2111 .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
2112 @*/
2113 PetscErrorCode  TSMonitorSolution(TS ts,PetscInt step,PetscReal ptime,Vec x,void *dummy)
2114 {
2115   PetscErrorCode ierr;
2116   PetscViewer    viewer = (PetscViewer) dummy;
2117 
2118   PetscFunctionBegin;
2119   if (!dummy) {
2120     viewer = PETSC_VIEWER_DRAW_(((PetscObject)ts)->comm);
2121   }
2122   ierr = VecView(x,viewer);CHKERRQ(ierr);
2123   PetscFunctionReturn(0);
2124 }
2125 
2126 
2127 #undef __FUNCT__
2128 #define __FUNCT__ "TSSetDM"
2129 /*@
2130    TSSetDM - Sets the DM that may be used by some preconditioners
2131 
2132    Logically Collective on TS and DM
2133 
2134    Input Parameters:
2135 +  ts - the preconditioner context
2136 -  dm - the dm
2137 
2138    Level: intermediate
2139 
2140 
2141 .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
2142 @*/
2143 PetscErrorCode  TSSetDM(TS ts,DM dm)
2144 {
2145   PetscErrorCode ierr;
2146 
2147   PetscFunctionBegin;
2148   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2149   ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
2150   if (ts->dm) {ierr = DMDestroy(ts->dm);CHKERRQ(ierr);}
2151   ts->dm = dm;
2152   if (ts->snes) {
2153     ierr = SNESSetDM(ts->snes,dm);CHKERRQ(ierr);
2154   }
2155   if (ts->ksp) {
2156     ierr = KSPSetDM(ts->ksp,dm);CHKERRQ(ierr);
2157     ierr = KSPSetDMActive(ts->ksp,PETSC_FALSE);CHKERRQ(ierr);
2158   }
2159   PetscFunctionReturn(0);
2160 }
2161 
2162 #undef __FUNCT__
2163 #define __FUNCT__ "TSGetDM"
2164 /*@
2165    TSGetDM - Gets the DM that may be used by some preconditioners
2166 
2167    Not Collective
2168 
2169    Input Parameter:
2170 . ts - the preconditioner context
2171 
2172    Output Parameter:
2173 .  dm - the dm
2174 
2175    Level: intermediate
2176 
2177 
2178 .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
2179 @*/
2180 PetscErrorCode  TSGetDM(TS ts,DM *dm)
2181 {
2182   PetscFunctionBegin;
2183   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
2184   *dm = ts->dm;
2185   PetscFunctionReturn(0);
2186 }
2187 
2188 #undef __FUNCT__
2189 #define __FUNCT__ "SNESTSFormFunction"
2190 /*@
2191    SNESTSFormFunction - Function to evaluate nonlinear residual
2192 
2193    Logically Collective on SNES
2194 
2195    Input Parameter:
2196 + snes - nonlinear solver
2197 . X - the current state at which to evaluate the residual
2198 - ctx - user context, must be a TS
2199 
2200    Output Parameter:
2201 . F - the nonlinear residual
2202 
2203    Notes:
2204    This function is not normally called by users and is automatically registered with the SNES used by TS.
2205    It is most frequently passed to MatFDColoringSetFunction().
2206 
2207    Level: advanced
2208 
2209 .seealso: SNESSetFunction(), MatFDColoringSetFunction()
2210 @*/
2211 PetscErrorCode  SNESTSFormFunction(SNES snes,Vec X,Vec F,void *ctx)
2212 {
2213   TS ts = (TS)ctx;
2214   PetscErrorCode ierr;
2215 
2216   PetscFunctionBegin;
2217   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
2218   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
2219   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
2220   PetscValidHeaderSpecific(ts,TS_CLASSID,4);
2221   ierr = (ts->ops->snesfunction)(snes,X,F,ts);CHKERRQ(ierr);
2222   PetscFunctionReturn(0);
2223 }
2224 
2225 #undef __FUNCT__
2226 #define __FUNCT__ "SNESTSFormJacobian"
2227 /*@
2228    SNESTSFormJacobian - Function to evaluate the Jacobian
2229 
2230    Collective on SNES
2231 
2232    Input Parameter:
2233 + snes - nonlinear solver
2234 . X - the current state at which to evaluate the residual
2235 - ctx - user context, must be a TS
2236 
2237    Output Parameter:
2238 + A - the Jacobian
2239 . B - the preconditioning matrix (may be the same as A)
2240 - flag - indicates any structure change in the matrix
2241 
2242    Notes:
2243    This function is not normally called by users and is automatically registered with the SNES used by TS.
2244 
2245    Level: developer
2246 
2247 .seealso: SNESSetJacobian()
2248 @*/
2249 PetscErrorCode  SNESTSFormJacobian(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *flag,void *ctx)
2250 {
2251   TS ts = (TS)ctx;
2252   PetscErrorCode ierr;
2253 
2254   PetscFunctionBegin;
2255   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
2256   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
2257   PetscValidPointer(A,3);
2258   PetscValidHeaderSpecific(*A,MAT_CLASSID,3);
2259   PetscValidPointer(B,4);
2260   PetscValidHeaderSpecific(*B,MAT_CLASSID,4);
2261   PetscValidPointer(flag,5);
2262   PetscValidHeaderSpecific(ts,TS_CLASSID,6);
2263   ierr = (ts->ops->snesjacobian)(snes,X,A,B,flag,ts);CHKERRQ(ierr);
2264   PetscFunctionReturn(0);
2265 }
2266 
2267 #if defined(PETSC_HAVE_MATLAB_ENGINE)
2268 #include "mex.h"
2269 
2270 typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
2271 
2272 #undef __FUNCT__
2273 #define __FUNCT__ "TSComputeFunction_Matlab"
2274 /*
2275    TSComputeFunction_Matlab - Calls the function that has been set with
2276                          TSSetFunctionMatlab().
2277 
2278    Collective on TS
2279 
2280    Input Parameters:
2281 +  snes - the TS context
2282 -  x - input vector
2283 
2284    Output Parameter:
2285 .  y - function vector, as set by TSSetFunction()
2286 
2287    Notes:
2288    TSComputeFunction() is typically used within nonlinear solvers
2289    implementations, so most users would not generally call this routine
2290    themselves.
2291 
2292    Level: developer
2293 
2294 .keywords: TS, nonlinear, compute, function
2295 
2296 .seealso: TSSetFunction(), TSGetFunction()
2297 */
2298 PetscErrorCode  TSComputeFunction_Matlab(TS snes,PetscReal time,Vec x,Vec xdot,Vec y, void *ctx)
2299 {
2300   PetscErrorCode   ierr;
2301   TSMatlabContext *sctx = (TSMatlabContext *)ctx;
2302   int              nlhs = 1,nrhs = 7;
2303   mxArray	   *plhs[1],*prhs[7];
2304   long long int    lx = 0,lxdot = 0,ly = 0,ls = 0;
2305 
2306   PetscFunctionBegin;
2307   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
2308   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
2309   PetscValidHeaderSpecific(xdot,VEC_CLASSID,4);
2310   PetscValidHeaderSpecific(y,VEC_CLASSID,5);
2311   PetscCheckSameComm(snes,1,x,3);
2312   PetscCheckSameComm(snes,1,y,5);
2313 
2314   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
2315   ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr);
2316   ierr = PetscMemcpy(&lxdot,&xdot,sizeof(xdot));CHKERRQ(ierr);
2317   ierr = PetscMemcpy(&ly,&y,sizeof(x));CHKERRQ(ierr);
2318   prhs[0] =  mxCreateDoubleScalar((double)ls);
2319   prhs[1] =  mxCreateDoubleScalar(time);
2320   prhs[2] =  mxCreateDoubleScalar((double)lx);
2321   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
2322   prhs[4] =  mxCreateDoubleScalar((double)ly);
2323   prhs[5] =  mxCreateString(sctx->funcname);
2324   prhs[6] =  sctx->ctx;
2325   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");CHKERRQ(ierr);
2326   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
2327   mxDestroyArray(prhs[0]);
2328   mxDestroyArray(prhs[1]);
2329   mxDestroyArray(prhs[2]);
2330   mxDestroyArray(prhs[3]);
2331   mxDestroyArray(prhs[4]);
2332   mxDestroyArray(prhs[5]);
2333   mxDestroyArray(plhs[0]);
2334   PetscFunctionReturn(0);
2335 }
2336 
2337 
2338 #undef __FUNCT__
2339 #define __FUNCT__ "TSSetFunctionMatlab"
2340 /*
2341    TSSetFunctionMatlab - Sets the function evaluation routine and function
2342    vector for use by the TS routines in solving ODEs
2343    equations from MATLAB. Here the function is a string containing the name of a MATLAB function
2344 
2345    Logically Collective on TS
2346 
2347    Input Parameters:
2348 +  ts - the TS context
2349 -  func - function evaluation routine
2350 
2351    Calling sequence of func:
2352 $    func (TS ts,PetscReal time,Vec x,Vec xdot,Vec f,void *ctx);
2353 
2354    Level: beginner
2355 
2356 .keywords: TS, nonlinear, set, function
2357 
2358 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
2359 */
2360 PetscErrorCode  TSSetFunctionMatlab(TS snes,const char *func,mxArray *ctx)
2361 {
2362   PetscErrorCode  ierr;
2363   TSMatlabContext *sctx;
2364 
2365   PetscFunctionBegin;
2366   /* currently sctx is memory bleed */
2367   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
2368   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
2369   /*
2370      This should work, but it doesn't
2371   sctx->ctx = ctx;
2372   mexMakeArrayPersistent(sctx->ctx);
2373   */
2374   sctx->ctx = mxDuplicateArray(ctx);
2375   ierr = TSSetIFunction(snes,TSComputeFunction_Matlab,sctx);CHKERRQ(ierr);
2376   PetscFunctionReturn(0);
2377 }
2378 
2379 #undef __FUNCT__
2380 #define __FUNCT__ "TSComputeJacobian_Matlab"
2381 /*
2382    TSComputeJacobian_Matlab - Calls the function that has been set with
2383                          TSSetJacobianMatlab().
2384 
2385    Collective on TS
2386 
2387    Input Parameters:
2388 +  snes - the TS context
2389 .  x - input vector
2390 .  A, B - the matrices
2391 -  ctx - user context
2392 
2393    Output Parameter:
2394 .  flag - structure of the matrix
2395 
2396    Level: developer
2397 
2398 .keywords: TS, nonlinear, compute, function
2399 
2400 .seealso: TSSetFunction(), TSGetFunction()
2401 @*/
2402 PetscErrorCode  TSComputeJacobian_Matlab(TS snes,PetscReal time,Vec x,Vec xdot,PetscReal shift,Mat *A,Mat *B,MatStructure *flag, void *ctx)
2403 {
2404   PetscErrorCode  ierr;
2405   TSMatlabContext *sctx = (TSMatlabContext *)ctx;
2406   int             nlhs = 2,nrhs = 9;
2407   mxArray	  *plhs[2],*prhs[9];
2408   long long int   lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
2409 
2410   PetscFunctionBegin;
2411   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
2412   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
2413 
2414   /* call Matlab function in ctx with arguments x and y */
2415 
2416   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
2417   ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr);
2418   ierr = PetscMemcpy(&lxdot,&xdot,sizeof(x));CHKERRQ(ierr);
2419   ierr = PetscMemcpy(&lA,A,sizeof(x));CHKERRQ(ierr);
2420   ierr = PetscMemcpy(&lB,B,sizeof(x));CHKERRQ(ierr);
2421   prhs[0] =  mxCreateDoubleScalar((double)ls);
2422   prhs[1] =  mxCreateDoubleScalar((double)time);
2423   prhs[2] =  mxCreateDoubleScalar((double)lx);
2424   prhs[3] =  mxCreateDoubleScalar((double)lxdot);
2425   prhs[4] =  mxCreateDoubleScalar((double)shift);
2426   prhs[5] =  mxCreateDoubleScalar((double)lA);
2427   prhs[6] =  mxCreateDoubleScalar((double)lB);
2428   prhs[7] =  mxCreateString(sctx->funcname);
2429   prhs[8] =  sctx->ctx;
2430   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");CHKERRQ(ierr);
2431   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
2432   *flag   =  (MatStructure) mxGetScalar(plhs[1]);CHKERRQ(ierr);
2433   mxDestroyArray(prhs[0]);
2434   mxDestroyArray(prhs[1]);
2435   mxDestroyArray(prhs[2]);
2436   mxDestroyArray(prhs[3]);
2437   mxDestroyArray(prhs[4]);
2438   mxDestroyArray(prhs[5]);
2439   mxDestroyArray(prhs[6]);
2440   mxDestroyArray(prhs[7]);
2441   mxDestroyArray(plhs[0]);
2442   mxDestroyArray(plhs[1]);
2443   PetscFunctionReturn(0);
2444 }
2445 
2446 
2447 #undef __FUNCT__
2448 #define __FUNCT__ "TSSetJacobianMatlab"
2449 /*
2450    TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
2451    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
2452 
2453    Logically Collective on TS
2454 
2455    Input Parameters:
2456 +  snes - the TS context
2457 .  A,B - Jacobian matrices
2458 .  func - function evaluation routine
2459 -  ctx - user context
2460 
2461    Calling sequence of func:
2462 $    flag = func (TS snes,PetscReal time,Vec x,Vec xdot,Mat A,Mat B,void *ctx);
2463 
2464 
2465    Level: developer
2466 
2467 .keywords: TS, nonlinear, set, function
2468 
2469 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
2470 */
2471 PetscErrorCode  TSSetJacobianMatlab(TS snes,Mat A,Mat B,const char *func,mxArray *ctx)
2472 {
2473   PetscErrorCode    ierr;
2474   TSMatlabContext *sctx;
2475 
2476   PetscFunctionBegin;
2477   /* currently sctx is memory bleed */
2478   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
2479   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
2480   /*
2481      This should work, but it doesn't
2482   sctx->ctx = ctx;
2483   mexMakeArrayPersistent(sctx->ctx);
2484   */
2485   sctx->ctx = mxDuplicateArray(ctx);
2486   ierr = TSSetIJacobian(snes,A,B,TSComputeJacobian_Matlab,sctx);CHKERRQ(ierr);
2487   PetscFunctionReturn(0);
2488 }
2489 
2490 #undef __FUNCT__
2491 #define __FUNCT__ "TSMonitor_Matlab"
2492 /*
2493    TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
2494 
2495    Collective on TS
2496 
2497 .seealso: TSSetFunction(), TSGetFunction()
2498 @*/
2499 PetscErrorCode  TSMonitor_Matlab(TS snes,PetscInt it, PetscReal time,Vec x, void *ctx)
2500 {
2501   PetscErrorCode  ierr;
2502   TSMatlabContext *sctx = (TSMatlabContext *)ctx;
2503   int             nlhs = 1,nrhs = 6;
2504   mxArray	  *plhs[1],*prhs[6];
2505   long long int   lx = 0,ls = 0;
2506 
2507   PetscFunctionBegin;
2508   PetscValidHeaderSpecific(snes,TS_CLASSID,1);
2509   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
2510 
2511   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
2512   ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr);
2513   prhs[0] =  mxCreateDoubleScalar((double)ls);
2514   prhs[1] =  mxCreateDoubleScalar((double)it);
2515   prhs[2] =  mxCreateDoubleScalar((double)time);
2516   prhs[3] =  mxCreateDoubleScalar((double)lx);
2517   prhs[4] =  mxCreateString(sctx->funcname);
2518   prhs[5] =  sctx->ctx;
2519   ierr    =  mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");CHKERRQ(ierr);
2520   ierr    =  mxGetScalar(plhs[0]);CHKERRQ(ierr);
2521   mxDestroyArray(prhs[0]);
2522   mxDestroyArray(prhs[1]);
2523   mxDestroyArray(prhs[2]);
2524   mxDestroyArray(prhs[3]);
2525   mxDestroyArray(prhs[4]);
2526   mxDestroyArray(plhs[0]);
2527   PetscFunctionReturn(0);
2528 }
2529 
2530 
2531 #undef __FUNCT__
2532 #define __FUNCT__ "TSMonitorSetMatlab"
2533 /*
2534    TSMonitorSetMatlab - Sets the monitor function from Matlab
2535 
2536    Level: developer
2537 
2538 .keywords: TS, nonlinear, set, function
2539 
2540 .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
2541 */
2542 PetscErrorCode  TSMonitorSetMatlab(TS snes,const char *func,mxArray *ctx)
2543 {
2544   PetscErrorCode    ierr;
2545   TSMatlabContext *sctx;
2546 
2547   PetscFunctionBegin;
2548   /* currently sctx is memory bleed */
2549   ierr = PetscMalloc(sizeof(TSMatlabContext),&sctx);CHKERRQ(ierr);
2550   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
2551   /*
2552      This should work, but it doesn't
2553   sctx->ctx = ctx;
2554   mexMakeArrayPersistent(sctx->ctx);
2555   */
2556   sctx->ctx = mxDuplicateArray(ctx);
2557   ierr = TSMonitorSet(snes,TSMonitor_Matlab,sctx,PETSC_NULL);CHKERRQ(ierr);
2558   PetscFunctionReturn(0);
2559 }
2560 
2561 #endif
2562