next up previous contents
Next: A Few Remarks on Up: User-Defined Dynamical Systems Previous: Installing a Defined Dynamical   Contents


A Vector Field Example: Duffing's Equations

In this section we present an example of installing a user-defined vector field into DsTool. It is assumed that the reader is familiar with the material in Section 4.2.

Our task is to install the vector field defined by the equations

\begin{displaymath}
\begin{array}{rcl}
\dot{u} &=& v, \\
\dot{v} &=& u - u^3 - \delta v - \gamma \cos \omega t.
\end{array}\end{displaymath} (4.5)

This system is known as Duffing's equations and we direct the reader to [1] and references therein for an exposition of the dynamics of this system.

To define and install this system, change to your local DsTool directory and copy the file GENERIC.c to the file userduffing_def.c. Use any text editor to edit userduffing_def.c.

The segment of code which defines the equations of motion (Equation 4.5) will be called userduffing(). This function is defined as follows:

/* ------------------------------------------------------------------------
   function used to define the vector field 
   ------------------------------------------------------------------------ */
int userduffing(f,x,p)
double *f,*x,*p;
{
   f[0] = x[1];
   f[1] = x[0] - x[0]*x[0]*x[0] - p[0]*x[1] - p[1]*cos( p[2]*x[2] );
}
Here we have defined the variables and parameters as

\begin{eqnarray*}
{\tt x} &=& \{ {\tt x[0]}, {\tt x[1]} \} = \{ u, v \}, \\
{...
...p[0]}, {\tt p[1]}, {\tt p[2]} \} = \{ \delta, \gamma, \omega \}.
\end{eqnarray*}

As usual, the independent variable is stored after the spatial variables so that x[2] is time. The function userduffing() returns in the array f the strength of the vector field with parameters p, evaluated at the point x.

We now define the Jacobian of Equation 4.5 by writing the function userduffing_jac():

/* ------------------------------------------------------------------------
   function used to define the Jacobian
   ------------------------------------------------------------------------ */
int userduffing_jac(m,x,p)
double  **m, *x, *p;
{
   m[0][0] = 0.0;
   m[0][1] = 1.0;
   m[1][0] = 1.0 - 3.0 * x[0] * x[0];
   m[1][1] = -p[0];
}

Since our equations are for a vector field, we do not need to define an inverse function. Our vector field is time-dependent, so we can define a function which returns the temporal derivatives of the vector field. This function is not yet used by DsTool, and there is no template for such a function in GENERIC.c, but it is easy enough to write:

/* ------------------------------------------------------------------------
   function used to define temporal derivatives
   ------------------------------------------------------------------------ */
int userduffing_dfdt(f,x,p)
double  *f, *x, *p;
{
   f[0] = 0.0;
   f[1] = -p[1] * p[2] * sin( p[2] * x[2] ); 
}

Since our vector field is Hamiltonian for $\delta = 0$, we choose

\begin{displaymath}H(u,v) = \frac{v^2}{2} - \frac{u^2}{2} + \frac{u^4}{4}
\end{displaymath}

as an auxiliary function. We will also define a second auxiliary function. Since our vector field is periodic in time (with period $2 \pi / \omega$), it is a common technique to look at the time- $2 \pi / \omega$ map in order to better understand the dynamics. This ``stroboscopic map'' can also be thought of as a Poincaré map for the extended phase space. We are thus interested in the times $t$ for which $\sin( wt + t_0) = 0$. Choosing $t_0 = 0$ we define the procedure userduffing_aux() by:
/* ------------------------------------------------------------------------
   function used to define aux functions of the varbs, time, or params
   ------------------------------------------------------------------------ */
int userduffing_aux(f,x,p)
double *f,*x,*p;
{
   double   temp;

   temp = 0.5 * x[0] * x[0];
   f[0] = 0.5 * x[1] * x[1] - temp + temp * temp;
   f[1] = sin( p[2] * x[2] );
}

We are now ready to define the labels and initial conditions for Duffing's equations by writing the function userduffing_init(). We choose $[-2, 2]$ as default plotting ranges for both $u$ and $v$. Initializing the variables is straightforward:

int userduffing_init()
{
/* ------------ define the dynamical system in this segment --------------- */

int            n_varb=2;                  /* dim of phase space           */
static char    *variable_names[]={"u","v"}; /* list of phase varb names   */
static double  variables[]={0.5,0.5};     /* default varb initial values  */
static double  variable_min[]={-2.,-2.};  /* default varb min for display */
static double  variable_max[]={2.,2.};    /* default varb max for display */

static char    *indep_varb_name="time";   /* name of indep variable             */
static double  indep_varb_min=0.;         /* default indep varb min for display */
static double  indep_varb_max=1000;       /* default indep varb max for display */

Defining the parameter ranges is somewhat arbitrary. Sometimes it is difficult to tell a priori what range of parameters will provide interesting bifurcations. This is not a big problem since it is a trivial matter to change the range upon which a function (or parameter) is plotted once within DsTool. We choose $[0,1]$ as a range for each parameter. We choose $(\delta_0, \gamma_0, \omega_0)
= (0.25, 0.4, 1.0)$:

int           n_param=3;                  /* dim of parameter space        */
static char   *parameter_names[]={"delta","gamma", "w"}; /* list of param names */
static double parameters[]={0.25,0.4,1.}; /* initial parameter values      */
static double parameter_min[]={0.,0.,0.}; /* default param min for display */
static double parameter_max[]={1.,1.,1.}; /* default param max for display */

The initialization of our two auxiliary functions is accomplished by the code segment:

int            n_funct=2;               /* number of user-defined functions */
static char    *funct_names[]={"H", "P_Section"}; /* list of funct names; {""} if none */
static double  funct_min[]={-4.,-1.};   /* default funct min for display    */
static double  funct_max[]={4.,1.};     /* default funct max for display    */
As in the case with parameters, it is sometimes difficult to choose a priori what appropriate ranges for the functions should be.

The manifold type for Duffing's equations is EUCLIDEAN since we do not have any periodic spatial variables. Thus we do not need to modify the following segment of code:

int           manifold_type=EUCLIDEAN; /* EUCLIDEAN or PERIODIC                 */
static int    periodic_varb[]={FALSE, FALSE}; /* if PERIODIC, which varbs periodic? */
static double period_start[]={0.,0.};  /* if PERIODIC, begin fundamental domain */
static double period_end[]={1., 1.};   /* if PERIODIC, end of fundamental domain*/

The last segment of code we need to modify is the segment which tells DsTool which numerical algorithms may be used on the Duffing's equations. We complete the definition of userduffing_init() with the code segment:

int           mapping_toggle=FALSE;       /* this is a map? TRUE or FALSE         */
int           inverse_toggle=FALSE;       /* if so, is inverse FALSE, APPROX_INV, */
                                        /* or EXPLICIT_INV? FALSE for vec field */ 

/*  In this section, input NULL or the name of the function which contains...   */
int     (*def_name)()=userduffing;          /* the eqns of motion                   */
int     (*jac_name)()=userduffing_jac;      /* the jacobian (deriv w.r.t. space)    */
int     (*aux_func_name)()=userduffing_aux; /* the auxiliary functions              */
int     (*inv_name)()=NULL;             /* the inverse or approx inverse        */
int     (*dfdt_name)()=userduffing_dfdt;    /* the deriv w.r.t time                 */
int     (*dfdparam_name)()=NULL;        /* the derivs w.r.t. parameters         */

As in Section 4.2, we now need to edit two other files. We edit Makefile and add userduffing_def.c to the USER_SRCS list, and add userduffing_def.o to the USER_OBJS list. We also edit the file user.c and add the lines

extern int  userduffing_init();
and
{0, "Duffing's Eqns", userduffing_init},
to the second and third blocks of code, respectively.

Typing make will create a local executable of DsTool which includes Duffing's equations among its installed dynamical systems.



Subsections
next up previous contents
Next: A Few Remarks on Up: User-Defined Dynamical Systems Previous: Installing a Defined Dynamical   Contents
2010-01-04