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