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