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