xref: /petsc/src/ts/interface/ts.c (revision 606d414c6e034e02e67059b83ebaefc3ebe99698)
1 #ifdef PETSC_RCS_HEADER
2 
3 #endif
4 
5 #include "src/ts/tsimpl.h"        /*I "ts.h"  I*/
6 
7 #undef __FUNC__
8 #define __FUNC__ "TSComputeRHSFunction"
9 /*
10    TSComputeRHSFunction - Evaluates the right-hand-side function.
11 
12    Note: If the user did not provide a function but merely a matrix,
13    this routine applies the matrix.
14 */
15 int TSComputeRHSFunction(TS ts,double t,Vec x, Vec y)
16 {
17   int ierr;
18 
19   PetscFunctionBegin;
20   PetscValidHeaderSpecific(ts,TS_COOKIE);
21   PetscValidHeader(x);  PetscValidHeader(y);
22 
23   if (ts->rhsfunction) {
24     PetscStackPush("TS user right-hand-side function");
25     ierr = (*ts->rhsfunction)(ts,t,x,y,ts->funP);CHKERRQ(ierr);
26     PetscStackPop;
27     PetscFunctionReturn(0);
28   }
29 
30   if (ts->rhsmatrix) { /* assemble matrix for this timestep */
31     MatStructure flg;
32     PetscStackPush("TS user right-hand-side matrix function");
33     ierr = (*ts->rhsmatrix)(ts,t,&ts->A,&ts->B,&flg,ts->jacP);CHKERRQ(ierr);
34     PetscStackPop;
35   }
36   ierr = MatMult(ts->A,x,y);CHKERRQ(ierr);
37 
38   /* apply user-provided boundary conditions (only needed if these are time dependent) */
39   ierr = TSComputeRHSBoundaryConditions(ts,t,y);CHKERRQ(ierr);
40 
41   PetscFunctionReturn(0);
42 }
43 
44 #undef __FUNC__
45 #define __FUNC__ "TSSetRHSFunction"
46 /*@C
47     TSSetRHSFunction - Sets the routine for evaluating the function,
48     F(t,u), where U_t = F(t,u).
49 
50     Collective on TS
51 
52     Input Parameters:
53 +   ts - the TS context obtained from TSCreate()
54 .   f - routine for evaluating the right-hand-side function
55 -   ctx - [optional] user-defined context for private data for the
56           function evaluation routine (may be PETSC_NULL)
57 
58     Calling sequence of func:
59 $     func (TS ts,double t,Vec u,Vec F,void *ctx);
60 
61 +   t - current timestep
62 .   u - input vector
63 .   F - function vector
64 -   ctx - [optional] user-defined function context
65 
66     Important:
67     The user MUST call either this routine or TSSetRHSMatrix().
68 
69     Level: beginner
70 
71 .keywords: TS, timestep, set, right-hand-side, function
72 
73 .seealso: TSSetRHSMatrix()
74 @*/
75 int TSSetRHSFunction(TS ts,int (*f)(TS,double,Vec,Vec,void*),void *ctx)
76 {
77   PetscFunctionBegin;
78 
79   PetscValidHeaderSpecific(ts,TS_COOKIE);
80   if (ts->problem_type == TS_LINEAR) {
81     SETERRQ(PETSC_ERR_ARG_WRONG,0,"Cannot set function for linear problem");
82   }
83   ts->rhsfunction = f;
84   ts->funP        = ctx;
85   PetscFunctionReturn(0);
86 }
87 
88 #undef __FUNC__
89 #define __FUNC__ "TSSetRHSMatrix"
90 /*@C
91    TSSetRHSMatrix - Sets the function to compute the matrix A, where U_t = A(t) U.
92    Also sets the location to store A.
93 
94    Collective on TS
95 
96    Input Parameters:
97 +  ts  - the TS context obtained from TSCreate()
98 .  A   - matrix
99 .  B   - preconditioner matrix (usually same as A)
100 .  f   - the matrix evaluation routine; use PETSC_NULL (PETSC_NULL_FUNCTION in fortran)
101          if A is not a function of t.
102 -  ctx - [optional] user-defined context for private data for the
103           matrix evaluation routine (may be PETSC_NULL)
104 
105    Calling sequence of func:
106 $     func (TS ts,double t,Mat *A,Mat *B,int *flag,void *ctx);
107 
108 +  t - current timestep
109 .  A - matrix A, where U_t = A(t) U
110 .  B - preconditioner matrix, usually the same as A
111 .  flag - flag indicating information about the preconditioner matrix
112           structure (same as flag in SLESSetOperators())
113 -  ctx - [optional] user-defined context for matrix evaluation routine
114 
115    Notes:
116    See SLESSetOperators() for important information about setting the flag
117    output parameter in the routine func().  Be sure to read this information!
118 
119    The routine func() takes Mat * as the matrix arguments rather than Mat.
120    This allows the matrix evaluation routine to replace A and/or B with a
121    completely new new matrix structure (not just different matrix elements)
122    when appropriate, for instance, if the nonzero structure is changing
123    throughout the global iterations.
124 
125    Important:
126    The user MUST call either this routine or TSSetRHSFunction().
127 
128    Level: beginner
129 
130 .keywords: TS, timestep, set, right-hand-side, matrix
131 
132 .seealso: TSSetRHSFunction()
133 @*/
134 int TSSetRHSMatrix(TS ts,Mat A, Mat B,int (*f)(TS,double,Mat*,Mat*,MatStructure*,void*),void *ctx)
135 {
136   PetscFunctionBegin;
137   PetscValidHeaderSpecific(ts,TS_COOKIE);
138   if (ts->problem_type == TS_NONLINEAR) {
139     SETERRQ(PETSC_ERR_ARG_WRONG,0,"Not for nonlinear problems; use TSSetRHSJacobian()");
140   }
141 
142   ts->rhsmatrix = f;
143   ts->jacP      = ctx;
144   ts->A         = A;
145   ts->B         = B;
146 
147   PetscFunctionReturn(0);
148 }
149 
150 #undef __FUNC__
151 #define __FUNC__ "TSSetRHSJacobian"
152 /*@C
153    TSSetRHSJacobian - Sets the function to compute the Jacobian of F,
154    where U_t = F(U,t), as well as the location to store the matrix.
155 
156    Collective on TS
157 
158    Input Parameters:
159 +  ts  - the TS context obtained from TSCreate()
160 .  A   - Jacobian matrix
161 .  B   - preconditioner matrix (usually same as A)
162 .  f   - the Jacobian evaluation routine
163 -  ctx - [optional] user-defined context for private data for the
164          Jacobian evaluation routine (may be PETSC_NULL)
165 
166    Calling sequence of func:
167 $     func (TS ts,double t,Vec u,Mat *A,Mat *B,int *flag,void *ctx);
168 
169 +  t - current timestep
170 .  u - input vector
171 .  A - matrix A, where U_t = A(t)u
172 .  B - preconditioner matrix, usually the same as A
173 .  flag - flag indicating information about the preconditioner matrix
174           structure (same as flag in SLESSetOperators())
175 -  ctx - [optional] user-defined context for matrix evaluation routine
176 
177    Notes:
178    See SLESSetOperators() for important information about setting the flag
179    output parameter in the routine func().  Be sure to read this information!
180 
181    The routine func() takes Mat * as the matrix arguments rather than Mat.
182    This allows the matrix evaluation routine to replace A and/or B with a
183    completely new new matrix structure (not just different matrix elements)
184    when appropriate, for instance, if the nonzero structure is changing
185    throughout the global iterations.
186 
187    Level: beginner
188 
189 .keywords: TS, timestep, set, right-hand-side, Jacobian
190 
191 .seealso: TSDefaultComputeJacobianColor(),
192           SNESDefaultComputeJacobianColor()
193 
194 @*/
195 int TSSetRHSJacobian(TS ts,Mat A, Mat B,int (*f)(TS,double,Vec,Mat*,Mat*,
196                      MatStructure*,void*),void *ctx)
197 {
198   PetscFunctionBegin;
199   PetscValidHeaderSpecific(ts,TS_COOKIE);
200   if (ts->problem_type != TS_NONLINEAR) {
201     SETERRQ(PETSC_ERR_ARG_WRONG,0,"Not for linear problems; use TSSetRHSMatrix()");
202   }
203 
204   ts->rhsjacobian = f;
205   ts->jacP        = ctx;
206   ts->A           = A;
207   ts->B           = B;
208   PetscFunctionReturn(0);
209 }
210 
211 #undef __FUNC__
212 #define __FUNC__ "TSComputeRHSBoundaryConditions"
213 /*
214    TSComputeRHSBoundaryConditions - Evaluates the boundary condition function.
215 
216    Note: If the user did not provide a function but merely a matrix,
217    this routine applies the matrix.
218 */
219 int TSComputeRHSBoundaryConditions(TS ts,double t,Vec x)
220 {
221   int ierr;
222 
223   PetscFunctionBegin;
224   PetscValidHeaderSpecific(ts,TS_COOKIE);
225   PetscValidHeader(x);
226 
227   if (ts->rhsbc) {
228     PetscStackPush("TS user boundary condition function");
229     ierr = (*ts->rhsbc)(ts,t,x,ts->bcP);CHKERRQ(ierr);
230     PetscStackPop;
231     PetscFunctionReturn(0);
232   }
233 
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNC__
238 #define __FUNC__ "TSSetRHSBoundaryConditions"
239 /*@C
240     TSSetRHSBoundaryConditions - Sets the routine for evaluating the function,
241     boundary conditions for the function F.
242 
243     Collective on TS
244 
245     Input Parameters:
246 +   ts - the TS context obtained from TSCreate()
247 .   f - routine for evaluating the boundary condition function
248 -   ctx - [optional] user-defined context for private data for the
249           function evaluation routine (may be PETSC_NULL)
250 
251     Calling sequence of func:
252 $     func (TS ts,double t,Vec F,void *ctx);
253 
254 +   t - current timestep
255 .   F - function vector
256 -   ctx - [optional] user-defined function context
257 
258     Level: intermediate
259 
260 .keywords: TS, timestep, set, boundary conditions, function
261 @*/
262 int TSSetRHSBoundaryConditions(TS ts,int (*f)(TS,double,Vec,void*),void *ctx)
263 {
264   PetscFunctionBegin;
265 
266   PetscValidHeaderSpecific(ts,TS_COOKIE);
267   if (ts->problem_type != TS_LINEAR) {
268     SETERRQ(PETSC_ERR_ARG_WRONG,0,"For linear problems only");
269   }
270   ts->rhsbc = f;
271   ts->bcP   = ctx;
272   PetscFunctionReturn(0);
273 }
274 
275 #undef __FUNC__
276 #define __FUNC__ "TSView"
277 /*@
278     TSView - Prints the TS data structure.
279 
280     Collective on TS, unless Viewer is VIEWER_STDOUT_SELF
281 
282     Input Parameters:
283 +   ts - the TS context obtained from TSCreate()
284 -   viewer - visualization context
285 
286     Options Database Key:
287 .   -ts_view - calls TSView() at end of TSStep()
288 
289     Notes:
290     The available visualization contexts include
291 +     VIEWER_STDOUT_SELF - standard output (default)
292 -     VIEWER_STDOUT_WORLD - synchronized standard
293          output where only the first processor opens
294          the file.  All other processors send their
295          data to the first processor to print.
296 
297     The user can open an alternative visualization context with
298     ViewerASCIIOpen() - output to a specified file.
299 
300     Level: beginner
301 
302 .keywords: TS, timestep, view
303 
304 .seealso: ViewerASCIIOpen()
305 @*/
306 int TSView(TS ts,Viewer viewer)
307 {
308   int                 ierr;
309   char                *method;
310   ViewerType          vtype;
311 
312   PetscFunctionBegin;
313   PetscValidHeaderSpecific(ts,TS_COOKIE);
314   ierr = ViewerGetType(viewer,&vtype);CHKERRQ(ierr);
315   if (PetscTypeCompare(vtype,ASCII_VIEWER)) {
316     ierr = ViewerASCIIPrintf(viewer,"TS Object:\n");CHKERRQ(ierr);
317     ierr = TSGetType(ts,(TSType *)&method);CHKERRQ(ierr);
318     ierr = ViewerASCIIPrintf(viewer,"  method: %s\n",method);CHKERRQ(ierr);
319     if (ts->view) {
320       ierr = ViewerASCIIPushTab(viewer);CHKERRQ(ierr);
321       ierr = (*ts->view)(ts,viewer);CHKERRQ(ierr);
322       ierr = ViewerASCIIPopTab(viewer);CHKERRQ(ierr);
323     }
324     ierr = ViewerASCIIPrintf(viewer,"  maximum steps=%d\n",ts->max_steps);CHKERRQ(ierr);
325     ierr = ViewerASCIIPrintf(viewer,"  maximum time=%g\n",ts->max_time);CHKERRQ(ierr);
326     if (ts->problem_type == TS_NONLINEAR) {
327       ierr = ViewerASCIIPrintf(viewer,"  total number of nonlinear solver iterations=%d\n",ts->nonlinear_its);CHKERRQ(ierr);
328     }
329     ierr = ViewerASCIIPrintf(viewer,"  total number of linear solver iterations=%d\n",ts->linear_its);CHKERRQ(ierr);
330   } else if (PetscTypeCompare(vtype,STRING_VIEWER)) {
331     ierr = TSGetType(ts,(TSType *)&method);CHKERRQ(ierr);
332     ierr = ViewerStringSPrintf(viewer," %-7.7s",method);CHKERRQ(ierr);
333   }
334   ierr = ViewerASCIIPushTab(viewer);CHKERRQ(ierr);
335   if (ts->sles) {ierr = SLESView(ts->sles,viewer);CHKERRQ(ierr);}
336   if (ts->snes) {ierr = SNESView(ts->snes,viewer);CHKERRQ(ierr);}
337   ierr = ViewerASCIIPopTab(viewer);CHKERRQ(ierr);
338   PetscFunctionReturn(0);
339 }
340 
341 
342 #undef __FUNC__
343 #define __FUNC__ "TSSetApplicationContext"
344 /*@C
345    TSSetApplicationContext - Sets an optional user-defined context for
346    the timesteppers.
347 
348    Collective on TS
349 
350    Input Parameters:
351 +  ts - the TS context obtained from TSCreate()
352 -  usrP - optional user context
353 
354    Level: intermediate
355 
356 .keywords: TS, timestep, set, application, context
357 
358 .seealso: TSGetApplicationContext()
359 @*/
360 int TSSetApplicationContext(TS ts,void *usrP)
361 {
362   PetscFunctionBegin;
363   PetscValidHeaderSpecific(ts,TS_COOKIE);
364   ts->user = usrP;
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNC__
369 #define __FUNC__ "TSGetApplicationContext"
370 /*@C
371     TSGetApplicationContext - Gets the user-defined context for the
372     timestepper.
373 
374     Not Collective
375 
376     Input Parameter:
377 .   ts - the TS context obtained from TSCreate()
378 
379     Output Parameter:
380 .   usrP - user context
381 
382     Level: intermediate
383 
384 .keywords: TS, timestep, get, application, context
385 
386 .seealso: TSSetApplicationContext()
387 @*/
388 int TSGetApplicationContext( TS ts,  void **usrP )
389 {
390   PetscFunctionBegin;
391   PetscValidHeaderSpecific(ts,TS_COOKIE);
392   *usrP = ts->user;
393   PetscFunctionReturn(0);
394 }
395 
396 #undef __FUNC__
397 #define __FUNC__ "TSGetTimeStepNumber"
398 /*@
399    TSGetTimeStepNumber - Gets the current number of timesteps.
400 
401    Not Collective
402 
403    Input Parameter:
404 .  ts - the TS context obtained from TSCreate()
405 
406    Output Parameter:
407 .  iter - number steps so far
408 
409    Level: intermediate
410 
411 .keywords: TS, timestep, get, iteration, number
412 @*/
413 int TSGetTimeStepNumber(TS ts,int* iter)
414 {
415   PetscFunctionBegin;
416   PetscValidHeaderSpecific(ts,TS_COOKIE);
417   *iter = ts->steps;
418   PetscFunctionReturn(0);
419 }
420 
421 #undef __FUNC__
422 #define __FUNC__ "TSSetInitialTimeStep"
423 /*@
424    TSSetInitialTimeStep - Sets the initial timestep to be used,
425    as well as the initial time.
426 
427    Collective on TS
428 
429    Input Parameters:
430 +  ts - the TS context obtained from TSCreate()
431 .  initial_time - the initial time
432 -  time_step - the size of the timestep
433 
434    Level: intermediate
435 
436 .seealso: TSSetTimeStep(), TSGetTimeStep()
437 
438 .keywords: TS, set, initial, timestep
439 @*/
440 int TSSetInitialTimeStep(TS ts,double initial_time,double time_step)
441 {
442   PetscFunctionBegin;
443   PetscValidHeaderSpecific(ts,TS_COOKIE);
444   ts->time_step         = time_step;
445   ts->initial_time_step = time_step;
446   ts->ptime             = initial_time;
447   PetscFunctionReturn(0);
448 }
449 
450 #undef __FUNC__
451 #define __FUNC__ "TSSetTimeStep"
452 /*@
453    TSSetTimeStep - Allows one to reset the timestep at any time,
454    useful for simple pseudo-timestepping codes.
455 
456    Collective on TS
457 
458    Input Parameters:
459 +  ts - the TS context obtained from TSCreate()
460 -  time_step - the size of the timestep
461 
462    Level: intermediate
463 
464 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
465 
466 .keywords: TS, set, timestep
467 @*/
468 int TSSetTimeStep(TS ts,double time_step)
469 {
470   PetscFunctionBegin;
471   PetscValidHeaderSpecific(ts,TS_COOKIE);
472   ts->time_step = time_step;
473   PetscFunctionReturn(0);
474 }
475 
476 #undef __FUNC__
477 #define __FUNC__ "TSGetTimeStep"
478 /*@
479    TSGetTimeStep - Gets the current timestep size.
480 
481    Not Collective
482 
483    Input Parameter:
484 .  ts - the TS context obtained from TSCreate()
485 
486    Output Parameter:
487 .  dt - the current timestep size
488 
489    Level: intermediate
490 
491 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
492 
493 .keywords: TS, get, timestep
494 @*/
495 int TSGetTimeStep(TS ts,double* dt)
496 {
497   PetscFunctionBegin;
498   PetscValidHeaderSpecific(ts,TS_COOKIE);
499   *dt = ts->time_step;
500   PetscFunctionReturn(0);
501 }
502 
503 #undef __FUNC__
504 #define __FUNC__ "TSGetSolution"
505 /*@C
506    TSGetSolution - Returns the solution at the present timestep. It
507    is valid to call this routine inside the function that you are evaluating
508    in order to move to the new timestep. This vector not changed until
509    the solution at the next timestep has been calculated.
510 
511    Not Collective, but Vec returned is parallel if TS is parallel
512 
513    Input Parameter:
514 .  ts - the TS context obtained from TSCreate()
515 
516    Output Parameter:
517 .  v - the vector containing the solution
518 
519    Level: intermediate
520 
521 .seealso: TSGetTimeStep()
522 
523 .keywords: TS, timestep, get, solution
524 @*/
525 int TSGetSolution(TS ts,Vec *v)
526 {
527   PetscFunctionBegin;
528   PetscValidHeaderSpecific(ts,TS_COOKIE);
529   *v = ts->vec_sol_always;
530   PetscFunctionReturn(0);
531 }
532 
533 #undef __FUNC__
534 #define __FUNC__ "TSPublish_Petsc"
535 static int TSPublish_Petsc(PetscObject object)
536 {
537 #if defined(PETSC_HAVE_AMS)
538   TS   v = (TS) object;
539   int  ierr;
540 
541   PetscFunctionBegin;
542 
543   /* if it is already published then return */
544   if (v->amem >=0 ) PetscFunctionReturn(0);
545 
546   ierr = PetscObjectPublishBaseBegin(object);CHKERRQ(ierr);
547   ierr = AMS_Memory_add_field((AMS_Memory)v->amem,"Step",&v->steps,1,AMS_INT,AMS_READ,
548                                 AMS_COMMON,AMS_REDUCT_UNDEF);CHKERRQ(ierr);
549   ierr = AMS_Memory_add_field((AMS_Memory)v->amem,"Time",&v->ptime,1,AMS_DOUBLE,AMS_READ,
550                                 AMS_COMMON,AMS_REDUCT_UNDEF);CHKERRQ(ierr);
551   ierr = AMS_Memory_add_field((AMS_Memory)v->amem,"CurrentTimeStep",&v->time_step,1,
552                                AMS_DOUBLE,AMS_READ,AMS_COMMON,AMS_REDUCT_UNDEF);CHKERRQ(ierr);
553   ierr = PetscObjectPublishBaseEnd(object);CHKERRQ(ierr);
554 #else
555   PetscFunctionBegin;
556 #endif
557   PetscFunctionReturn(0);
558 }
559 
560 /* -----------------------------------------------------------*/
561 
562 #undef __FUNC__
563 #define __FUNC__ "TSCreate"
564 /*@C
565    TSCreate - Creates a timestepper context.
566 
567    Collective on MPI_Comm
568 
569    Input Parameter:
570 +  comm - MPI communicator
571 -  type - One of  TS_LINEAR,TS_NONLINEAR
572    where these types refer to problems of the forms
573 .vb
574          U_t = A U
575          U_t = A(t) U
576          U_t = F(t,U)
577 .ve
578 
579    Output Parameter:
580 .  outts - the new TS context
581 
582    Level: beginner
583 
584 .keywords: TS, timestep, create, context
585 
586 .seealso: TSSetUp(), TSStep(), TSDestroy()
587 @*/
588 int TSCreate(MPI_Comm comm,TSProblemType problemtype,TS *outts)
589 {
590   TS   ts;
591 
592   PetscFunctionBegin;
593   *outts = 0;
594   PetscHeaderCreate(ts,_p_TS,int,TS_COOKIE,-1,"TS",comm,TSDestroy,TSView);
595   PLogObjectCreate(ts);
596   ts->bops->publish     = TSPublish_Petsc;
597   ts->max_steps         = 5000;
598   ts->max_time          = 5.0;
599   ts->time_step         = .1;
600   ts->initial_time_step = ts->time_step;
601   ts->steps             = 0;
602   ts->ptime             = 0.0;
603   ts->data              = 0;
604   ts->view              = 0;
605   ts->setupcalled       = 0;
606   ts->problem_type      = problemtype;
607   ts->numbermonitors    = 0;
608   ts->linear_its        = 0;
609   ts->nonlinear_its     = 0;
610 
611   *outts = ts;
612   PetscFunctionReturn(0);
613 }
614 
615 /* ----- Routines to initialize and destroy a timestepper ---- */
616 
617 #undef __FUNC__
618 #define __FUNC__ "TSSetUp"
619 /*@
620    TSSetUp - Sets up the internal data structures for the later use
621    of a timestepper.
622 
623    Collective on TS
624 
625    Input Parameter:
626 .  ts - the TS context obtained from TSCreate()
627 
628    Notes:
629    For basic use of the TS solvers the user need not explicitly call
630    TSSetUp(), since these actions will automatically occur during
631    the call to TSStep().  However, if one wishes to control this
632    phase separately, TSSetUp() should be called after TSCreate()
633    and optional routines of the form TSSetXXX(), but before TSStep().
634 
635    Level: advanced
636 
637 .keywords: TS, timestep, setup
638 
639 .seealso: TSCreate(), TSStep(), TSDestroy()
640 @*/
641 int TSSetUp(TS ts)
642 {
643   int ierr;
644 
645   PetscFunctionBegin;
646   PetscValidHeaderSpecific(ts,TS_COOKIE);
647   if (!ts->vec_sol) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"Must call TSSetSolution() first");
648   if (!ts->type_name) {
649     ierr = TSSetType(ts,TS_EULER);CHKERRQ(ierr);
650   }
651   ierr = (*ts->setup)(ts);CHKERRQ(ierr);
652   ts->setupcalled = 1;
653   PetscFunctionReturn(0);
654 }
655 
656 #undef __FUNC__
657 #define __FUNC__ "TSDestroy"
658 /*@C
659    TSDestroy - Destroys the timestepper context that was created
660    with TSCreate().
661 
662    Collective on TS
663 
664    Input Parameter:
665 .  ts - the TS context obtained from TSCreate()
666 
667    Level: beginner
668 
669 .keywords: TS, timestepper, destroy
670 
671 .seealso: TSCreate(), TSSetUp(), TSSolve()
672 @*/
673 int TSDestroy(TS ts)
674 {
675   int ierr;
676 
677   PetscFunctionBegin;
678   PetscValidHeaderSpecific(ts,TS_COOKIE);
679   if (--ts->refct > 0) PetscFunctionReturn(0);
680 
681   if (ts->sles) {ierr = SLESDestroy(ts->sles);CHKERRQ(ierr);}
682   if (ts->snes) {ierr = SNESDestroy(ts->snes);CHKERRQ(ierr);}
683   ierr = (*(ts)->destroy)(ts);CHKERRQ(ierr);
684   PLogObjectDestroy((PetscObject)ts);
685   PetscHeaderDestroy((PetscObject)ts);
686   PetscFunctionReturn(0);
687 }
688 
689 #undef __FUNC__
690 #define __FUNC__ "TSGetSNES"
691 /*@C
692    TSGetSNES - Returns the SNES (nonlinear solver) associated with
693    a TS (timestepper) context. Valid only for nonlinear problems.
694 
695    Not Collective, but SNES is parallel if TS is parallel
696 
697    Input Parameter:
698 .  ts - the TS context obtained from TSCreate()
699 
700    Output Parameter:
701 .  snes - the nonlinear solver context
702 
703    Notes:
704    The user can then directly manipulate the SNES context to set various
705    options, etc.  Likewise, the user can then extract and manipulate the
706    SLES, KSP, and PC contexts as well.
707 
708    TSGetSNES() does not work for integrators that do not use SNES; in
709    this case TSGetSNES() returns PETSC_NULL in snes.
710 
711    Level: beginner
712 
713 .keywords: timestep, get, SNES
714 @*/
715 int TSGetSNES(TS ts,SNES *snes)
716 {
717   PetscFunctionBegin;
718   PetscValidHeaderSpecific(ts,TS_COOKIE);
719   if (ts->problem_type == TS_LINEAR) SETERRQ(PETSC_ERR_ARG_WRONG,0,"Nonlinear only; use TSGetSLES()");
720   *snes = ts->snes;
721   PetscFunctionReturn(0);
722 }
723 
724 #undef __FUNC__
725 #define __FUNC__ "TSGetSLES"
726 /*@C
727    TSGetSLES - Returns the SLES (linear solver) associated with
728    a TS (timestepper) context.
729 
730    Not Collective, but SLES is parallel if TS is parallel
731 
732    Input Parameter:
733 .  ts - the TS context obtained from TSCreate()
734 
735    Output Parameter:
736 .  sles - the nonlinear solver context
737 
738    Notes:
739    The user can then directly manipulate the SLES context to set various
740    options, etc.  Likewise, the user can then extract and manipulate the
741    KSP and PC contexts as well.
742 
743    TSGetSLES() does not work for integrators that do not use SLES;
744    in this case TSGetSLES() returns PETSC_NULL in sles.
745 
746    Level: beginner
747 
748 .keywords: timestep, get, SLES
749 @*/
750 int TSGetSLES(TS ts,SLES *sles)
751 {
752   PetscFunctionBegin;
753   PetscValidHeaderSpecific(ts,TS_COOKIE);
754   if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_ERR_ARG_WRONG,0,"Linear only; use TSGetSNES()");
755   *sles = ts->sles;
756   PetscFunctionReturn(0);
757 }
758 
759 /* ----------- Routines to set solver parameters ---------- */
760 
761 #undef __FUNC__
762 #define __FUNC__ "TSSetDuration"
763 /*@
764    TSSetDuration - Sets the maximum number of timesteps to use and
765    maximum time for iteration.
766 
767    Collective on TS
768 
769    Input Parameters:
770 +  ts - the TS context obtained from TSCreate()
771 .  maxsteps - maximum number of iterations to use
772 -  maxtime - final time to iterate to
773 
774    Options Database Keys:
775 .  -ts_max_steps <maxsteps> - Sets maxsteps
776 .  -ts_max_time <maxtime> - Sets maxtime
777 
778    Notes:
779    The default maximum number of iterations is 5000. Default time is 5.0
780 
781    Level: intermediate
782 
783 .keywords: TS, timestep, set, maximum, iterations
784 @*/
785 int TSSetDuration(TS ts,int maxsteps,double maxtime)
786 {
787   PetscFunctionBegin;
788   PetscValidHeaderSpecific(ts,TS_COOKIE);
789   ts->max_steps = maxsteps;
790   ts->max_time  = maxtime;
791   PetscFunctionReturn(0);
792 }
793 
794 #undef __FUNC__
795 #define __FUNC__ "TSSetSolution"
796 /*@
797    TSSetSolution - Sets the initial solution vector
798    for use by the TS routines.
799 
800    Collective on TS and Vec
801 
802    Input Parameters:
803 +  ts - the TS context obtained from TSCreate()
804 -  x - the solution vector
805 
806    Level: beginner
807 
808 .keywords: TS, timestep, set, solution, initial conditions
809 @*/
810 int TSSetSolution(TS ts,Vec x)
811 {
812   PetscFunctionBegin;
813   PetscValidHeaderSpecific(ts,TS_COOKIE);
814   ts->vec_sol        = ts->vec_sol_always = x;
815   PetscFunctionReturn(0);
816 }
817 
818 /* ------------ Routines to set performance monitoring options ----------- */
819 
820 #undef __FUNC__
821 #define __FUNC__ "TSSetMonitor"
822 /*@C
823    TSSetMonitor - Sets an ADDITIONAL function that is to be used at every
824    timestep to display the iteration's  progress.
825 
826    Collective on TS
827 
828    Input Parameters:
829 +  ts - the TS context obtained from TSCreate()
830 .  func - monitoring routine
831 -  mctx - [optional] user-defined context for private data for the
832           monitor routine (may be PETSC_NULL)
833 
834    Calling sequence of func:
835 $    int func(TS ts,int steps,double time,Vec x,void *mctx)
836 
837 +    ts - the TS context
838 .    steps - iteration number
839 .    time - current timestep
840 .    x - current iterate
841 -    mctx - [optional] monitoring context
842 
843    Notes:
844    This routine adds an additional monitor to the list of monitors that
845    already has been loaded.
846 
847    Level: intermediate
848 
849 .keywords: TS, timestep, set, monitor
850 
851 .seealso: TSDefaultMonitor(), TSClearMonitor()
852 @*/
853 int TSSetMonitor(TS ts, int (*monitor)(TS,int,double,Vec,void*), void *mctx )
854 {
855   PetscFunctionBegin;
856   PetscValidHeaderSpecific(ts,TS_COOKIE);
857   if (ts->numbermonitors >= MAXTSMONITORS) {
858     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Too many monitors set");
859   }
860   ts->monitor[ts->numbermonitors]           = monitor;
861   ts->monitorcontext[ts->numbermonitors++]  = (void*)mctx;
862   PetscFunctionReturn(0);
863 }
864 
865 #undef __FUNC__
866 #define __FUNC__ "TSClearMonitor"
867 /*@C
868    TSClearMonitor - Clears all the monitors that have been set on a time-step object.
869 
870    Collective on TS
871 
872    Input Parameters:
873 .  ts - the TS context obtained from TSCreate()
874 
875    Notes:
876    There is no way to remove a single, specific monitor.
877 
878    Level: intermediate
879 
880 .keywords: TS, timestep, set, monitor
881 
882 .seealso: TSDefaultMonitor(), TSSetMonitor()
883 @*/
884 int TSClearMonitor(TS ts)
885 {
886   PetscFunctionBegin;
887   PetscValidHeaderSpecific(ts,TS_COOKIE);
888   ts->numbermonitors = 0;
889   PetscFunctionReturn(0);
890 }
891 
892 #undef __FUNC__
893 #define __FUNC__ "TSDefaultMonitor"
894 int TSDefaultMonitor(TS ts, int step, double time,Vec v, void *ctx)
895 {
896   int ierr;
897 
898   PetscFunctionBegin;
899   ierr = PetscPrintf(ts->comm,"timestep %d dt %g time %g\n",step,ts->time_step,time);CHKERRQ(ierr);
900   PetscFunctionReturn(0);
901 }
902 
903 #undef __FUNC__
904 #define __FUNC__ "TSStep"
905 /*@
906    TSStep - Steps the requested number of timesteps.
907 
908    Collective on TS
909 
910    Input Parameter:
911 .  ts - the TS context obtained from TSCreate()
912 
913    Output Parameters:
914 +  steps - number of iterations until termination
915 -  time - time until termination
916 
917    Level: beginner
918 
919 .keywords: TS, timestep, solve
920 
921 .seealso: TSCreate(), TSSetUp(), TSDestroy()
922 @*/
923 int TSStep(TS ts,int *steps,double *time)
924 {
925   int ierr,flg;
926 
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(ts,TS_COOKIE);
929   if (!ts->setupcalled) {ierr = TSSetUp(ts);CHKERRQ(ierr);}
930   PLogEventBegin(TS_Step,ts,0,0,0);
931   ierr = (*(ts)->step)(ts,steps,time);CHKERRQ(ierr);
932   PLogEventEnd(TS_Step,ts,0,0,0);
933   ierr = OptionsHasName(PETSC_NULL,"-ts_view",&flg);CHKERRQ(ierr);
934   if (flg) {
935     ierr = TSView(ts,VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
936   }
937   PetscFunctionReturn(0);
938 }
939 
940 #undef __FUNC__
941 #define __FUNC__ "TSMonitor"
942 /*
943      Runs the user provided monitor routines, if they exists.
944 */
945 int TSMonitor(TS ts,int step,double time,Vec x)
946 {
947   int i,ierr,n = ts->numbermonitors;
948 
949   PetscFunctionBegin;
950   for ( i=0; i<n; i++ ) {
951     ierr = (*ts->monitor[i])(ts,step,time,x,ts->monitorcontext[i]);CHKERRQ(ierr);
952   }
953   PetscFunctionReturn(0);
954 }
955 
956 /* ------------------------------------------------------------------------*/
957 
958 /*@C
959    TSLGMonitorCreate - Creates a line graph context for use with
960    TS to monitor convergence of preconditioned residual norms.
961 
962    Collective on TS
963 
964    Input Parameters:
965 +  host - the X display to open, or null for the local machine
966 .  label - the title to put in the title bar
967 .  x, y - the screen coordinates of the upper left coordinate of
968           the window
969 -  m, n - the screen width and height in pixels
970 
971    Output Parameter:
972 .  draw - the drawing context
973 
974    Options Database Key:
975 .  -ts_xmonitor - automatically sets line graph monitor
976 
977    Notes:
978    Use TSLGMonitorDestroy() to destroy this line graph, not DrawLGDestroy().
979 
980    Level: intermediate
981 
982 .keywords: TS, monitor, line graph, residual, create
983 
984 .seealso: TSLGMonitorDestroy(), TSSetMonitor()
985 @*/
986 int TSLGMonitorCreate(char *host,char *label,int x,int y,int m,
987                        int n, DrawLG *draw)
988 {
989   Draw win;
990   int  ierr;
991 
992   PetscFunctionBegin;
993   ierr = DrawOpenX(PETSC_COMM_SELF,host,label,x,y,m,n,&win);CHKERRQ(ierr);
994   ierr = DrawLGCreate(win,1,draw);CHKERRQ(ierr);
995   ierr = DrawLGIndicateDataPoints(*draw);CHKERRQ(ierr);
996 
997   PLogObjectParent(*draw,win);
998   PetscFunctionReturn(0);
999 }
1000 
1001 #undef __FUNC__
1002 #define __FUNC__ "TSLGMonitor"
1003 int TSLGMonitor(TS ts,int n,double time,Vec v,void *monctx)
1004 {
1005   DrawLG lg = (DrawLG) monctx;
1006   double x,y = time;
1007   int    ierr;
1008 
1009   PetscFunctionBegin;
1010   if (!n) {ierr = DrawLGReset(lg);CHKERRQ(ierr);}
1011   x = (double) n;
1012   ierr = DrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr);
1013   if (n < 20 || (n % 5)) {
1014     ierr = DrawLGDraw(lg);CHKERRQ(ierr);
1015   }
1016   PetscFunctionReturn(0);
1017 }
1018 
1019 #undef __FUNC__
1020 #define __FUNC__ "TSLGMonitorDestroy"
1021 /*@C
1022    TSLGMonitorDestroy - Destroys a line graph context that was created
1023    with TSLGMonitorCreate().
1024 
1025    Collective on DrawLG
1026 
1027    Input Parameter:
1028 .  draw - the drawing context
1029 
1030    Level: intermediate
1031 
1032 .keywords: TS, monitor, line graph, destroy
1033 
1034 .seealso: TSLGMonitorCreate(),  TSSetMonitor(), TSLGMonitor();
1035 @*/
1036 int TSLGMonitorDestroy(DrawLG drawlg)
1037 {
1038   Draw draw;
1039   int  ierr;
1040 
1041   PetscFunctionBegin;
1042   ierr = DrawLGGetDraw(drawlg,&draw);CHKERRQ(ierr);
1043   ierr = DrawDestroy(draw);CHKERRQ(ierr);
1044   ierr = DrawLGDestroy(drawlg);CHKERRQ(ierr);
1045   PetscFunctionReturn(0);
1046 }
1047 
1048 #undef __FUNC__
1049 #define __FUNC__ "TSGetTime"
1050 /*@
1051    TSGetTime - Gets the current time.
1052 
1053    Not Collective
1054 
1055    Input Parameter:
1056 .  ts - the TS context obtained from TSCreate()
1057 
1058    Output Parameter:
1059 .  t  - the current time
1060 
1061    Contributed by: Matthew Knepley
1062 
1063    Level: beginner
1064 
1065 .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1066 
1067 .keywords: TS, get, time
1068 @*/
1069 int TSGetTime(TS ts, double* t)
1070 {
1071   PetscFunctionBegin;
1072   PetscValidHeaderSpecific(ts, TS_COOKIE);
1073   *t = ts->ptime;
1074   PetscFunctionReturn(0);
1075 }
1076 
1077 #undef __FUNC__
1078 #define __FUNC__ "TSGetProblemType"
1079 /*@C
1080    TSGetProblemType - Returns the problem type of a TS (timestepper) context.
1081 
1082    Not Collective
1083 
1084    Input Parameter:
1085 .  ts   - The TS context obtained from TSCreate()
1086 
1087    Output Parameter:
1088 .  type - The problem type, TS_LINEAR or TS_NONLINEAR
1089 
1090    Level: intermediate
1091 
1092    Contributed by: Matthew Knepley
1093 
1094 .keywords: ts, get, type
1095 
1096 @*/
1097 int TSGetProblemType(TS ts, TSProblemType *type)
1098 {
1099   PetscFunctionBegin;
1100   PetscValidHeaderSpecific(ts, TS_COOKIE);
1101   *type = ts->problem_type;
1102   PetscFunctionReturn(0);
1103 }
1104 
1105 #undef __FUNC__
1106 #define __FUNC__ "TSSetOptionsPrefix"
1107 /*@C
1108    TSSetOptionsPrefix - Sets the prefix used for searching for all
1109    TS options in the database.
1110 
1111    Collective on TS
1112 
1113    Input Parameter:
1114 +  ts     - The TS context
1115 -  prefix - The prefix to prepend to all option names
1116 
1117    Notes:
1118    A hyphen (-) must NOT be given at the beginning of the prefix name.
1119    The first character of all runtime options is AUTOMATICALLY the
1120    hyphen.
1121 
1122    Contributed by: Matthew Knepley
1123 
1124    Level: advanced
1125 
1126 .keywords: TS, set, options, prefix, database
1127 
1128 .seealso: TSSetFromOptions()
1129 
1130 @*/
1131 int TSSetOptionsPrefix(TS ts, char *prefix)
1132 {
1133   int ierr;
1134 
1135   PetscFunctionBegin;
1136   PetscValidHeaderSpecific(ts, TS_COOKIE);
1137   ierr = PetscObjectSetOptionsPrefix((PetscObject) ts, prefix);CHKERRQ(ierr);
1138   switch(ts->problem_type) {
1139     case TS_NONLINEAR:
1140       ierr = SNESSetOptionsPrefix(ts->snes, prefix);CHKERRQ(ierr);
1141       break;
1142     case TS_LINEAR:
1143       ierr = SLESSetOptionsPrefix(ts->sles, prefix);CHKERRQ(ierr);
1144       break;
1145   }
1146   PetscFunctionReturn(0);
1147 }
1148 
1149 
1150 #undef __FUNC__
1151 #define __FUNC__ "TSAppendOptionsPrefix"
1152 /*@C
1153    TSAppendOptionsPrefix - Appends to the prefix used for searching for all
1154    TS options in the database.
1155 
1156    Collective on TS
1157 
1158    Input Parameter:
1159 +  ts     - The TS context
1160 -  prefix - The prefix to prepend to all option names
1161 
1162    Notes:
1163    A hyphen (-) must NOT be given at the beginning of the prefix name.
1164    The first character of all runtime options is AUTOMATICALLY the
1165    hyphen.
1166 
1167    Contributed by: Matthew Knepley
1168 
1169    Level: advanced
1170 
1171 .keywords: TS, append, options, prefix, database
1172 
1173 .seealso: TSGetOptionsPrefix()
1174 
1175 @*/
1176 int TSAppendOptionsPrefix(TS ts, char *prefix)
1177 {
1178   int ierr;
1179 
1180   PetscFunctionBegin;
1181   PetscValidHeaderSpecific(ts, TS_COOKIE);
1182   ierr = PetscObjectAppendOptionsPrefix((PetscObject) ts, prefix);CHKERRQ(ierr);
1183   switch(ts->problem_type) {
1184     case TS_NONLINEAR:
1185       ierr = SNESAppendOptionsPrefix(ts->snes, prefix);CHKERRQ(ierr);
1186       break;
1187     case TS_LINEAR:
1188       ierr = SLESAppendOptionsPrefix(ts->sles, prefix);CHKERRQ(ierr);
1189       break;
1190   }
1191   PetscFunctionReturn(0);
1192 }
1193 
1194 #undef __FUNC__
1195 #define __FUNC__ "TSGetOptionsPrefix"
1196 /*@C
1197    TSGetOptionsPrefix - Sets the prefix used for searching for all
1198    TS options in the database.
1199 
1200    Not Collective
1201 
1202    Input Parameter:
1203 .  ts - The TS context
1204 
1205    Output Parameter:
1206 .  prefix - A pointer to the prefix string used
1207 
1208    Contributed by: Matthew Knepley
1209 
1210    Notes: On the fortran side, the user should pass in a string 'prifix' of
1211    sufficient length to hold the prefix.
1212 
1213    Level: intermediate
1214 
1215 .keywords: TS, get, options, prefix, database
1216 
1217 .seealso: TSAppendOptionsPrefix()
1218 @*/
1219 int TSGetOptionsPrefix(TS ts, char **prefix)
1220 {
1221   int ierr;
1222 
1223   PetscFunctionBegin;
1224   PetscValidHeaderSpecific(ts, TS_COOKIE);
1225   ierr = PetscObjectGetOptionsPrefix((PetscObject) ts, prefix);CHKERRQ(ierr);
1226   PetscFunctionReturn(0);
1227 }
1228 
1229 #undef __FUNC__
1230 #define __FUNC__ "TSGetRHSMatrix"
1231 /*@C
1232    TSGetRHSMatrix - Returns the matrix A at the present timestep.
1233 
1234    Not Collective, but parallel objects are returned if TS is parallel
1235 
1236    Input Parameter:
1237 .  ts  - The TS context obtained from TSCreate()
1238 
1239    Output Parameters:
1240 +  A   - The matrix A, where U_t = A(t) U
1241 .  M   - The preconditioner matrix, usually the same as A
1242 -  ctx - User-defined context for matrix evaluation routine
1243 
1244    Notes: You can pass in PETSC_NULL for any return argument you do not need.
1245 
1246    Contributed by: Matthew Knepley
1247 
1248    Level: intermediate
1249 
1250 .seealso: TSGetTimeStep(), TSGetTime(), TSGetTimeStepNumber(), TSGetRHSJacobian()
1251 
1252 .keywords: TS, timestep, get, matrix
1253 
1254 @*/
1255 int TSGetRHSMatrix(TS ts, Mat *A, Mat *M, void **ctx)
1256 {
1257   PetscFunctionBegin;
1258   PetscValidHeaderSpecific(ts, TS_COOKIE);
1259   if (A)   *A = ts->A;
1260   if (M)   *M = ts->B;
1261   if (ctx) *ctx = ts->jacP;
1262   PetscFunctionReturn(0);
1263 }
1264 
1265 #undef __FUNC__
1266 #define __FUNC__ "TSGetRHSJacobian"
1267 /*@C
1268    TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
1269 
1270    Not Collective, but parallel objects are returned if TS is parallel
1271 
1272    Input Parameter:
1273 .  ts  - The TS context obtained from TSCreate()
1274 
1275    Output Parameters:
1276 +  J   - The Jacobian J of F, where U_t = F(U,t)
1277 .  M   - The preconditioner matrix, usually the same as J
1278 - ctx - User-defined context for Jacobian evaluation routine
1279 
1280    Notes: You can pass in PETSC_NULL for any return argument you do not need.
1281 
1282    Contributed by: Matthew Knepley
1283 
1284    Level: intermediate
1285 
1286 .seealso: TSGetTimeStep(), TSGetRHSMatrix(), TSGetTime(), TSGetTimeStepNumber()
1287 
1288 .keywords: TS, timestep, get, matrix, Jacobian
1289 @*/
1290 int TSGetRHSJacobian(TS ts, Mat *J, Mat *M, void **ctx)
1291 {
1292   int ierr;
1293 
1294   PetscFunctionBegin;
1295   ierr = TSGetRHSMatrix(ts, J, M, ctx);CHKERRQ(ierr);
1296   PetscFunctionReturn(0);
1297 }
1298 
1299 /*MC
1300    TSRegister - Adds a method to the timestepping solver package.
1301 
1302    Synopsis:
1303 
1304    TSRegister(char *name_solver,char *path,char *name_create,int (*routine_create)(TS))
1305 
1306    Not collective
1307 
1308    Input Parameters:
1309 +  name_solver - name of a new user-defined solver
1310 .  path - path (either absolute or relative) the library containing this solver
1311 .  name_create - name of routine to create method context
1312 -  routine_create - routine to create method context
1313 
1314    Notes:
1315    TSRegister() may be called multiple times to add several user-defined solvers.
1316 
1317    If dynamic libraries are used, then the fourth input argument (routine_create)
1318    is ignored.
1319 
1320    Sample usage:
1321 .vb
1322    TSRegister("my_solver",/home/username/my_lib/lib/libO/solaris/mylib.a,
1323               "MySolverCreate",MySolverCreate);
1324 .ve
1325 
1326    Then, your solver can be chosen with the procedural interface via
1327 $     TSSetType(ts,"my_solver")
1328    or at runtime via the option
1329 $     -ts_type my_solver
1330 
1331    Level: advanced
1332 
1333    $PETSC_ARCH, $PETSC_DIR, $PETSC_LDIR, and $BOPT occuring in pathname will be replaced with appropriate values.
1334 
1335 .keywords: TS, register
1336 
1337 .seealso: TSRegisterAll(), TSRegisterDestroy()
1338 M*/
1339 
1340 #undef __FUNC__
1341 #define __FUNC__ "TSRegister_Private"
1342 int TSRegister_Private(char *sname,char *path,char *name,int (*function)(TS))
1343 {
1344   char fullname[256];
1345   int  ierr;
1346 
1347   PetscFunctionBegin;
1348   ierr = PetscStrcpy(fullname,path);CHKERRQ(ierr);
1349   PetscStrcat(fullname,":"); PetscStrcat(fullname,name);
1350   FListAdd_Private(&TSList,sname,fullname,        (int (*)(void*))function);
1351   PetscFunctionReturn(0);
1352 }
1353