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