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