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