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