This is gsl-ref.info, produced by makeinfo version 4.2 from
gsl-ref.texi.

INFO-DIR-SECTION Scientific software
START-INFO-DIR-ENTRY
* gsl-ref: (gsl-ref).                   GNU Scientific Library - Reference
END-INFO-DIR-ENTRY


File: gsl-ref.info,  Node: Monte Carlo Examples,  Next: Monte Carlo Integration References and Further Reading,  Prev: VEGAS,  Up: Monte Carlo Integration

Examples
========

   The example program below uses the Monte Carlo routines to estimate
the value of the following 3-dimensional integral from the theory of
random walks,

     I = \int_{-pi}^{+pi} {dk_x/(2 pi)}
         \int_{-pi}^{+pi} {dk_y/(2 pi)}
         \int_{-pi}^{+pi} {dk_z/(2 pi)}
          1 / (1 - cos(k_x)cos(k_y)cos(k_z))

The analytic value of this integral can be shown to be I =
\Gamma(1/4)^4/(4 \pi^3) = 1.393203929685676859....  The integral gives
the mean time spent at the origin by a random walk on a body-centered
cubic lattice in three dimensions.

   For simplicity we will compute the integral over the region (0,0,0)
to (\pi,\pi,\pi) and multiply by 8 to obtain the full result.  The
integral is slowly varying in the middle of the region but has
integrable singularities at the corners (0,0,0), (0,\pi,\pi),
(\pi,0,\pi) and (\pi,\pi,0).  The Monte Carlo routines only select
points which are strictly within the integration region and so no
special measures are needed to avoid these singularities.

     #include <stdlib.h>
     #include <gsl/gsl_math.h>
     #include <gsl/gsl_monte.h>
     #include <gsl/gsl_monte_plain.h>
     #include <gsl/gsl_monte_miser.h>
     #include <gsl/gsl_monte_vegas.h>
     
     /* Computation of the integral,
     
           I = int (dx dy dz)/(2pi)^3  1/(1-cos(x)cos(y)cos(z))
     
        over (-pi,-pi,-pi) to (+pi, +pi, +pi).  The exact answer
        is Gamma(1/4)^4/(4 pi^3).  This example is taken from
        C.Itzykson, J.M.Drouffe, "Statistical Field Theory -
        Volume 1", Section 1.1, p21, which cites the original
        paper M.L.Glasser, I.J.Zucker, Proc.Natl.Acad.Sci.USA 74
        1800 (1977) */
     
     /* For simplicity we compute the integral over the region
        (0,0,0) -> (pi,pi,pi) and multiply by 8 */
     
     double exact = 1.3932039296856768591842462603255;
     
     double
     g (double *k, size_t dim, void *params)
     {
       double A = 1.0 / (M_PI * M_PI * M_PI);
       return A / (1.0 - cos (k[0]) * cos (k[1]) * cos (k[2]));
     }
     
     void
     display_results (char *title, double result, double error)
     {
       printf ("%s ==================\n", title);
       printf ("result = % .6f\n", result);
       printf ("sigma  = % .6f\n", error);
       printf ("exact  = % .6f\n", exact);
       printf ("error  = % .6f = %.1g sigma\n", result - exact,
               fabs (result - exact) / error);
     }
     
     int
     main (void)
     {
       double res, err;
     
       double xl[3] = { 0, 0, 0 };
       double xu[3] = { M_PI, M_PI, M_PI };
     
       const gsl_rng_type *T;
       gsl_rng *r;
     
       gsl_monte_function G = { &g, 3, 0 };
     
       size_t calls = 500000;
     
       gsl_rng_env_setup ();
     
       T = gsl_rng_default;
       r = gsl_rng_alloc (T);
     
       {
         gsl_monte_plain_state *s = gsl_monte_plain_alloc (3);
         gsl_monte_plain_integrate (&G, xl, xu, 3, calls, r, s,
                                    &res, &err);
         gsl_monte_plain_free (s);
     
         display_results ("plain", res, err);
       }
     
       {
         gsl_monte_miser_state *s = gsl_monte_miser_alloc (3);
         gsl_monte_miser_integrate (&G, xl, xu, 3, calls, r, s,
                                    &res, &err);
         gsl_monte_miser_free (s);
     
         display_results ("miser", res, err);
       }
     
       {
         gsl_monte_vegas_state *s = gsl_monte_vegas_alloc (3);
     
         gsl_monte_vegas_integrate (&G, xl, xu, 3, 10000, r, s,
                                    &res, &err);
         display_results ("vegas warm-up", res, err);
     
         printf ("converging...\n");
     
         do
           {
             gsl_monte_vegas_integrate (&G, xl, xu, 3, calls/5, r, s,
                                        &res, &err);
             printf ("result = % .6f sigma = % .6f "
                     "chisq/dof = %.1f\n", res, err, s->chisq);
           }
         while (fabs (s->chisq - 1.0) > 0.5);
     
         display_results ("vegas final", res, err);
     
         gsl_monte_vegas_free (s);
       }
       return 0;
     }

With 500,000 function calls the plain Monte Carlo algorithm achieves a
fractional error of 0.6%.  The estimated error `sigma' is consistent
with the actual error, and the computed result differs from the true
result by about one standard deviation,

     plain ==================
     result =  1.385867
     sigma  =  0.007938
     exact  =  1.393204
     error  = -0.007337 = 0.9 sigma

The MISER algorithm reduces the error by a factor of two, and also
correctly estimates the error,

     miser ==================
     result =  1.390656
     sigma  =  0.003743
     exact  =  1.393204
     error  = -0.002548 = 0.7 sigma

In the case of the VEGAS algorithm the program uses an initial warm-up
run of 10,000 function calls to prepare, or "warm up", the grid.  This
is followed by a main run with five iterations of 100,000 function
calls. The chi-squared per degree of freedom for the five iterations are
checked for consistency with 1, and the run is repeated if the results
have not converged. In this case the estimates are consistent on the
first pass.

     vegas warm-up ==================
     result =  1.386925
     sigma  =  0.002651
     exact  =  1.393204
     error  = -0.006278 = 2 sigma
     converging...
     result =  1.392957 sigma =  0.000452 chisq/dof = 1.1
     vegas final ==================
     result =  1.392957
     sigma  =  0.000452
     exact  =  1.393204
     error  = -0.000247 = 0.5 sigma

If the value of `chisq' had differed significantly from 1 it would
indicate inconsistent results, with a correspondingly underestimated
error.  The final estimate from VEGAS (using a similar number of
function calls) is significantly more accurate than the other two
algorithms.


File: gsl-ref.info,  Node: Monte Carlo Integration References and Further Reading,  Prev: Monte Carlo Examples,  Up: Monte Carlo Integration

References and Further Reading
==============================

The MISER algorithm is described in the following article,

     W.H. Press, G.R. Farrar, `Recursive Stratified Sampling for
     Multidimensional Monte Carlo Integration', Computers in Physics,
     v4 (1990), pp190-195.

The VEGAS algorithm is described in the following papers,

     G.P. Lepage, `A New Algorithm for Adaptive Multidimensional
     Integration', Journal of Computational Physics 27, 192-203, (1978)

     G.P. Lepage, `VEGAS: An Adaptive Multi-dimensional Integration
     Program', Cornell preprint CLNS 80-447, March 1980


File: gsl-ref.info,  Node: Simulated Annealing,  Next: Ordinary Differential Equations,  Prev: Monte Carlo Integration,  Up: Top

Simulated Annealing
*******************

   Stochastic search techniques are used when the structure of a space
is not well understood or is not smooth, so that techniques like
Newton's method (which requires calculating Jacobian derivative
matrices) cannot be used. In particular, these techniques are
frequently used to solve combinatorial optimization problems, such as
the traveling salesman problem.

   The goal is to find a point in the space at which a real valued
"energy function" (or "cost function") is minimized.  Simulated
annealing is a minimization technique which has given good results in
avoiding local minima; it is based on the idea of taking a random walk
through the space at successively lower temperatures, where the
probability of taking a step is given by a Boltzmann distribution.

   The functions described in this chapter are declared in the header
file `gsl_siman.h'.

* Menu:

* Simulated Annealing algorithm::
* Simulated Annealing functions::
* Examples with Simulated Annealing::


File: gsl-ref.info,  Node: Simulated Annealing algorithm,  Next: Simulated Annealing functions,  Prev: Simulated Annealing,  Up: Simulated Annealing

Simulated Annealing algorithm
=============================

   The simulated annealing algorithm takes random walks through the
problem space, looking for points with low energies; in these random
walks, the probability of taking a step is determined by the Boltzmann
distribution,

     p = e^{-(E_{i+1} - E_i)/(kT)}

if E_{i+1} > E_i, and p = 1 when E_{i+1} <= E_i.

   In other words, a step will occur if the new energy is lower.  If
the new energy is higher, the transition can still occur, and its
likelihood is proportional to the temperature T and inversely
proportional to the energy difference E_{i+1} - E_i.

   The temperature T is initially set to a high value, and a random
walk is carried out at that temperature.  Then the temperature is
lowered very slightly according to a "cooling schedule", for example: T
-> T/mu_T where \mu_T is slightly greater than 1.

   The slight probability of taking a step that gives higher energy is
what allows simulated annealing to frequently get out of local minima.


File: gsl-ref.info,  Node: Simulated Annealing functions,  Next: Examples with Simulated Annealing,  Prev: Simulated Annealing algorithm,  Up: Simulated Annealing

Simulated Annealing functions
=============================

 - Function: void gsl_siman_solve (const gsl_rng * R, void *X0_P,
          gsl_siman_Efunc_t EF, gsl_siman_step_t TAKE_STEP,
          gsl_siman_metric_t DISTANCE, gsl_siman_print_t
          PRINT_POSITION, gsl_siman_copy_t COPYFUNC,
          gsl_siman_copy_construct_t COPY_CONSTRUCTOR,
          gsl_siman_destroy_t DESTRUCTOR, size_t ELEMENT_SIZE,
          gsl_siman_params_t PARAMS)
     This function performs a simulated annealing search through a given
     space.  The space is specified by providing the functions EF and
     DISTANCE.  The simulated annealing steps are generated using the
     random number generator R and the function TAKE_STEP.

     The starting configuration of the system should be given by X0_P.
     The routine offers two modes for updating configurations, a
     fixed-size mode and a variable-size mode.  In the fixed-size mode
     the configuration is stored as a single block of memory of size
     ELEMENT_SIZE.  Copies of this configuration are created, copied
     and destroyed internally using the standard library functions
     `malloc', `memcpy' and `free'.  The function pointers COPYFUNC,
     COPY_CONSTRUCTOR and DESTRUCTOR should be null pointers in
     fixed-size mode.  In the variable-size mode the functions
     COPYFUNC, COPY_CONSTRUCTOR and DESTRUCTOR are used to create, copy
     and destroy configurations internally.  The variable ELEMENT_SIZE
     should be zero in the variable-size mode.

     The PARAMS structure (described below) controls the run by
     providing the temperature schedule and other tunable parameters to
     the algorithm.

     On exit the best result achieved during the search is placed in
     `*X0_P'.  If the annealing process has been successful this should
     be a good approximation to the optimal point in the space.

     If the function pointer PRINT_POSITION is not null, a debugging
     log will be printed to `stdout' with the following columns:

          number_of_iterations temperature x x-(*x0_p) Ef(x)

     and the output of the function PRINT_POSITION itself.  If
     PRINT_POSITION is null then no information is printed.

The simulated annealing routines require several user-specified
functions to define the configuration space and energy function.  The
prototypes for these functions are given below.

 - Data Type: gsl_siman_Efunc_t
     This function type should return the energy of a configuration XP.
          double (*gsl_siman_Efunc_t) (void *xp)

 - Data Type: gsl_siman_step_t
     This function type should modify the configuration XP using a
     random step taken from the generator R, up to a maximium distance
     of STEP_SIZE.
          void (*gsl_siman_step_t) (const gsl_rng *r, void *xp,
                                    double step_size)

 - Data Type: gsl_siman_metric_t
     This function type should return the distance between two
     configurations XP and YP.
          double (*gsl_siman_metric_t) (void *xp, void *yp)

 - Data Type: gsl_siman_print_t
     This function type should print the contents of the configuration
     XP.
          void (*gsl_siman_print_t) (void *xp)

 - Data Type: gsl_siman_copy_t
     This function type should copy the configuration DEST into SOURCE.
          void (*gsl_siman_copy_t) (void *source, void *dest)

 - Data Type: gsl_siman_copy_construct_t
     This function type should create a new copy of the configuration
     XP.
          void * (*gsl_siman_copy_construct_t) (void *xp)

 - Data Type: gsl_siman_destroy_t
     This function type should destroy the configuration XP, freeing its
     memory.
          void (*gsl_siman_destroy_t) (void *xp)

 - Data Type: gsl_siman_params_t
     These are the parameters that control a run of `gsl_siman_solve'.
     This structure contains all the information needed to control the
     search, beyond the energy function, the step function and the
     initial guess.

    `int n_tries'
          The number of points to try for each step

    `int iters_fixed_T'
          The number of iterations at each temperature

    `double step_size'
          The maximum step size in the random walk

    `double k, t_initial, mu_t, t_min'
          The parameters of the Boltzmann distribution and cooling
          schedule


File: gsl-ref.info,  Node: Examples with Simulated Annealing,  Prev: Simulated Annealing functions,  Up: Simulated Annealing

Examples with Simulated Annealing
=================================

   The simulated Annealing package is clumsy, and it has to be because
it is written in C, for C callers, and tries to be polymorphic at the
same time.  But here we provide some examples which can be pasted into
your application with little change and should make things easier.

* Menu:

* Trivial example::
* Traveling Salesman Problem::


File: gsl-ref.info,  Node: Trivial example,  Next: Traveling Salesman Problem,  Prev: Examples with Simulated Annealing,  Up: Examples with Simulated Annealing

Trivial example
---------------

   The first example, in one dimensional cartesian space, sets up an
energy function which is a damped sine wave; this has many local
minima, but only one global minimum, somewhere between 1.0 and 1.5.
The initial guess given is 15.5, which is several local minima away
from the global minimum.

     #include <math.h>
     #include <stdlib.h>
     #include <gsl/gsl_siman.h>
     
     /* set up parameters for this simulated annealing run */
     
     /* how many points do we try before stepping */
     #define N_TRIES 200
     
     /* how many iterations for each T? */
     #define ITERS_FIXED_T 10
     
     /* max step size in random walk */
     #define STEP_SIZE 10
     
     /* Boltzmann constant */
     #define K 1.0
     
     /* initial temperature */
     #define T_INITIAL 0.002
     
     /* damping factor for temperature */
     #define MU_T 1.005
     #define T_MIN 2.0e-6
     
     gsl_siman_params_t params
       = {N_TRIES, ITERS_FIXED_T, STEP_SIZE,
          K, T_INITIAL, MU_T, T_MIN};
     
     /* now some functions to test in one dimension */
     double E1(void *xp)
     {
       double x = * ((double *) xp);
     
       return exp(-pow((x-1.0),2.0))*sin(8*x);
     }
     
     double M1(void *xp, void *yp)
     {
       double x = *((double *) xp);
       double y = *((double *) yp);
     
       return fabs(x - y);
     }
     
     void S1(const gsl_rng * r, void *xp, double step_size)
     {
       double old_x = *((double *) xp);
       double new_x;
     
       double u = gsl_rng_uniform(r);
       new_x = u * 2 * step_size - step_size + old_x;
     
       memcpy(xp, &new_x, sizeof(new_x));
     }
     
     void P1(void *xp)
     {
       printf("%12g", *((double *) xp));
     }
     
     int
     main(int argc, char *argv[])
     {
       gsl_rng_type * T;
       gsl_rng * r;
     
       double x_initial = 15.5;
     
       gsl_rng_env_setup();
     
       T = gsl_rng_default;
       r = gsl_rng_alloc(T);
     
       gsl_siman_solve(r, &x_initial, E1, S1, M1, P1,
                       NULL, NULL, NULL,
                       sizeof(double), params);
       return 0;
     }

   Here are a couple of plots that are generated by running
`siman_test' in the following way:
     ./siman_test | grep -v "^#"
       | xyplot -xyil -y -0.88 -0.83 -d "x...y"
       | xyps -d > siman-test.eps
     ./siman_test | grep -v "^#"
       | xyplot -xyil -xl "generation" -yl "energy" -d "x..y"
       | xyps -d > siman-energy.eps


File: gsl-ref.info,  Node: Traveling Salesman Problem,  Prev: Trivial example,  Up: Examples with Simulated Annealing

Traveling Salesman Problem
--------------------------

   The TSP ("Traveling Salesman Problem") is the classic combinatorial
optimization problem.  I have provided a very simple version of it,
based on the coordinates of twelve cities in the southwestern United
States.  This should maybe be called the "Flying Salesman Problem",
since I am using the great-circle distance between cities, rather than
the driving distance.  Also: I assume the earth is a sphere, so I don't
use geoid distances.

   The `gsl_siman_solve()' routine finds a route which is 3490.62
Kilometers long; this is confirmed by an exhaustive search of all
possible routes with the same initial city.

   The full code can be found in `siman/siman_tsp.c', but I include
here some plots generated with in the following way:
     ./siman_tsp > tsp.output
     grep -v "^#" tsp.output
       | xyplot -xyil -d "x................y"
                -lx "generation" -ly "distance"
                -lt "TSP -- 12 southwest cities"
       | xyps -d > 12-cities.eps
     grep initial_city_coord tsp.output
       | awk '{print $2, $3, $4, $5}'
       | xyplot -xyil -lb0 -cs 0.8
                -lx "longitude (- means west)"
                -ly "latitude"
                -lt "TSP -- initial-order"
       | xyps -d > initial-route.eps
     grep final_city_coord tsp.output
       | awk '{print $2, $3, $4, $5}'
       | xyplot -xyil -lb0 -cs 0.8
                -lx "longitude (- means west)"
                -ly "latitude"
                -lt "TSP -- final-order"
       | xyps -d > final-route.eps

   This is the output showing the initial order of the cities;
longitude is negative, since it is west and I want the plot to look
like a map.
     # initial coordinates of cities (longitude and latitude)
     ###initial_city_coord: -105.95 35.68 Santa Fe
     ###initial_city_coord: -112.07 33.54 Phoenix
     ###initial_city_coord: -106.62 35.12 Albuquerque
     ###initial_city_coord: -103.2 34.41 Clovis
     ###initial_city_coord: -107.87 37.29 Durango
     ###initial_city_coord: -96.77 32.79 Dallas
     ###initial_city_coord: -105.92 35.77 Tesuque
     ###initial_city_coord: -107.84 35.15 Grants
     ###initial_city_coord: -106.28 35.89 Los Alamos
     ###initial_city_coord: -106.76 32.34 Las Cruces
     ###initial_city_coord: -108.58 37.35 Cortez
     ###initial_city_coord: -108.74 35.52 Gallup
     ###initial_city_coord: -105.95 35.68 Santa Fe

   The optimal route turns out to be:
     # final coordinates of cities (longitude and latitude)
     ###final_city_coord: -105.95 35.68 Santa Fe
     ###final_city_coord: -106.28 35.89 Los Alamos
     ###final_city_coord: -106.62 35.12 Albuquerque
     ###final_city_coord: -107.84 35.15 Grants
     ###final_city_coord: -107.87 37.29 Durango
     ###final_city_coord: -108.58 37.35 Cortez
     ###final_city_coord: -108.74 35.52 Gallup
     ###final_city_coord: -112.07 33.54 Phoenix
     ###final_city_coord: -106.76 32.34 Las Cruces
     ###final_city_coord: -96.77 32.79 Dallas
     ###final_city_coord: -103.2 34.41 Clovis
     ###final_city_coord: -105.92 35.77 Tesuque
     ###final_city_coord: -105.95 35.68 Santa Fe

Here's a plot of the cost function (energy) versus generation (point in
the calculation at which a new temperature is set) for this problem:


File: gsl-ref.info,  Node: Ordinary Differential Equations,  Next: Interpolation,  Prev: Simulated Annealing,  Up: Top

Ordinary Differential Equations
*******************************

   This chapter describes functions for solving ordinary differential
equation (ODE) initial value problems.  The library provides a variety
of low-level methods, such as Runge-Kutta and Bulirsch-Stoer routines,
and higher-level components for adaptive step-size control.  The
components can be combined by the user to achieve the desired solution,
with full access to any intermediate steps.

   These functions are declared in the header file `gsl_odeiv.h'.

* Menu:

* Defining the ODE System::
* Stepping Functions::
* Adaptive Step-size Control::
* Evolution::
* ODE Example programs::
* ODE References and Further Reading::


File: gsl-ref.info,  Node: Defining the ODE System,  Next: Stepping Functions,  Up: Ordinary Differential Equations

Defining the ODE System
=======================

   The routines solve the general n-dimensional first-order system,

     dy_i(t)/dt = f_i(t, y_1(t), ..., y_n(t))

for i = 1, \dots, n.  The stepping functions rely on the vector of
derivatives f_i and the Jacobian matrix, J_{ij} = df_i(t,y(t)) / dy_j.
A system of equations is defined using the `gsl_odeiv_system' datatype.

 - Data Type: gsl_odeiv_system
     This data type defines a general ODE system with arbitrary
     parameters.

    `int (* FUNCTION) (double t, const double y[], double dydt[], void * params)'
          This function should store the vector elements
          f_i(t,y,params) in the array DYDT, for arguments (T,Y) and
          parameters PARAMS

    `int (* JACOBIAN) (double t, const double y[], double * dfdy, double dfdt[], void * params);'
          This function should store the vector elements
          df_i(t,y,params)/dt in the array DFDT and the Jacobian matrix
          J_{ij} in the array DFDY regarded as a row-ordered matrix
          `J(i,j) = dfdy[i * dim + j]' where `dim' is the dimension of
          the system.

          Some of the simpler solver algorithms do not make use of the
          Jacobian matrix, so it is not always strictly necessary to
          provide it (this element of the struct can be replace by a
          null pointer).  However, it is useful to provide the Jacobian
          to allow the solver algorithms to be interchanged - the best
          algorithms make use of the Jacobian.

    `size_t DIMENSION;'
          This is the dimension of the system of equations

    `void * PARAMS'
          This is a pointer to the arbitrary parameters of the system.


File: gsl-ref.info,  Node: Stepping Functions,  Next: Adaptive Step-size Control,  Prev: Defining the ODE System,  Up: Ordinary Differential Equations

Stepping Functions
==================

   The lowest level components are the "stepping functions" which
advance a solution from time t to t+h for a fixed step-size h and
estimate the resulting local error.

 - Function: gsl_odeiv_step * gsl_odeiv_step_alloc (const
          gsl_odeiv_step_type * T, size_t DIM)
     This function returns a pointer to a newly allocated instance of a
     stepping function of type T for a system of DIM dimensions.

 - Function: int gsl_odeiv_step_reset (gsl_odeiv_step * S)
     This function resets the stepping function S.  It should be used
     whenever the next use of S will not be a continuation of a
     previous step.

 - Function: void gsl_odeiv_step_free (gsl_odeiv_step * S)
     This function frees all the memory associated with the stepping
     function S.

 - Function: const char * gsl_odeiv_step_name (const gsl_odeiv_step * S)
     This function returns a pointer to the name of the stepping
     function.  For example,

          printf("step method is '%s'\n",
                  gsl_odeiv_step_name (s));

     would print something like `step method is 'rk4''.

 - Function: unsigned int gsl_odeiv_step_order (const gsl_odeiv_step *
          S)
     This function returns the order of the stepping function on the
     previous step.  This order can vary if the stepping function
     itself is adaptive.

 - Function: int gsl_odeiv_step_apply (gsl_odeiv_step * S, double T,
          double H, double y[], double yerr[], const double dydt_in[],
          double dydt_out[], const gsl_odeiv_system * DYDT)
     This function applies the stepping function S to the system of
     equations defined by DYDT, using the step size H to advance the
     system from time T and state Y to time T+H.  The new state of the
     system is stored in Y on output, with an estimate of the absolute
     error in each component stored in YERR.  If the argument DYDT_IN
     is not null it should point an array containing the derivatives
     for the system at time T on input. This is optional as the
     derivatives will be computed internally if they are not provided,
     but allows the reuse of existing derivative information.  On
     output the new derivatives of the system at time T+H will be
     stored in DYDT_OUT if it is not null.

   The following algorithms are available,

 - Step Type: gsl_odeiv_step_rk2
     Embedded 2nd order Runge-Kutta with 3rd order error estimate.

 - Step Type: gsl_odeiv_step_rk4
     4th order (classical) Runge-Kutta.

 - Step Type: gsl_odeiv_step_rkf45
     Embedded 4th order Runge-Kutta-Fehlberg method with 5th order error
     estimate.  This method is a good general-purpose integrator.

 - Step Type: gsl_odeiv_step_rkck
     Embedded 4th order Runge-Kutta Cash-Karp method with 5th order
     error estimate.

 - Step Type: gsl_odeiv_step_rk8pd
     Embedded 8th order Runge-Kutta Prince-Dormand method with 9th order
     error estimate.

 - Step Type: gsl_odeiv_step_rk2imp
     Implicit 2nd order Runge-Kutta at Gaussian points

 - Step Type: gsl_odeiv_step_rk4imp
     Implicit 4th order Runge-Kutta at Gaussian points

 - Step Type: gsl_odeiv_step_bsimp
     Implicit Bulirsch-Stoer method of Bader and Deuflhard.  This
     algorithm requires the Jacobian.

 - Step Type: gsl_odeiv_step_gear1
     M=1 implicit Gear method

 - Step Type: gsl_odeiv_step_gear2
     M=2 implicit Gear method


File: gsl-ref.info,  Node: Adaptive Step-size Control,  Next: Evolution,  Prev: Stepping Functions,  Up: Ordinary Differential Equations

Adaptive Step-size Control
==========================

   The control function examines the proposed change to the solution and
its error estimate produced by a stepping function and attempts to
determine the optimal step-size for a user-specified level of error.

 - Function: gsl_odeiv_control * gsl_odeiv_control_standard_new (double
          EPS_ABS, double EPS_REL, double A_Y, double A_DYDT)
     The standard control object is a four parameter heuristic based on
     absolute and relative errors EPS_ABS and EPS_REL, and scaling
     factors A_Y and A_DYDT for the system state y(t) and derivatives
     y'(t) respectively.

     The step-size adjustment procedure for this method begins by
     computing the desired error level D_i for each component,

          D_i = eps_abs + eps_rel * (a_y |y_i| + a_dydt h |y'_i|)

     and comparing it with the observed error E_i = |yerr_i|.  If the
     observed error E exceeds the desired error level D by more than
     10% for any component then the method reduces the step-size by an
     appropriate factor,

          h_new = h_old * S * (D/E)^(1/q)

     where q is the consistency order of method (e.g. q=4 for 4(5)
     embedded RK), and S is a safety factor of 0.9. The ratio D/E is
     taken to be the maximum of the ratios D_i/E_i.

     If the observed error E is less than 50% of the desired error
     level D for the maximum ratio D_i/E_i then the algorithm takes the
     opportunity to increase the step-size to bring the error in line
     with the desired level,

          h_new = h_old * S * (E/D)^(1/(q+1))

     This encompasses all the standard error scaling methods.

 - Function: gsl_odeiv_control * gsl_odeiv_control_y_new (double
          EPS_ABS, double EPS_REL)
     This function creates a new control object which will keep the
     local error on each step within an absolute error of EPS_ABS and
     relative error of EPS_REL with respect to the solution y_i(t).
     This is equivalent to the standard control object with A_Y=1 and
     A_DYDT=0.

 - Function: gsl_odeiv_control * gsl_odeiv_control_yp_new (double
          EPS_ABS, double EPS_REL)
     This function creates a new control object which will keep the
     local error on each step within an absolute error of EPS_ABS and
     relative error of EPS_REL with respect to the derivatives of the
     solution y'_i(t) .  This is equivalent to the standard control
     object with A_Y=0 and A_DYDT=1.

 - Function: gsl_odeiv_control * gsl_odeiv_control_scaled_new (double
          EPS_ABS, double EPS_REL, double A_Y, double A_DYDT, const
          double SCALE_ABS[], size_t DIM)
     This function creates a new control object which uses the same
     algorithm as `gsl_odeiv_control_standard_new' but with an absolute
     error which is scaled for each component by the array SCALE_ABS.
     The formula for D_i for this control object is,

          D_i = eps_abs * s_i + eps_rel * (a_y |y_i| + a_dydt h |y'_i|)

     where s_i is the i-th component of the array SCALE_ABS.  The same
     error control heuristic is used by the Matlab ODE suite.

 - Function: gsl_odeiv_control * gsl_odeiv_control_alloc (const
          gsl_odeiv_control_type * T)
     This function returns a pointer to a newly allocated instance of a
     control function of type T.  This function is only needed for
     defining new types of control functions.  For most purposes the
     standard control functions described above should be sufficient.

 - Function: int gsl_odeiv_control_init (gsl_odeiv_control * C, double
          EPS_ABS, double EPS_REL, double A_Y, double A_DYDT)
     This function initializes the control function C with the
     parameters EPS_ABS (absolute error), EPS_REL (relative error), A_Y
     (scaling factor for y) and A_DYDT (scaling factor for derivatives).

 - Function: void gsl_odeiv_control_free (gsl_odeiv_control * C)
     This function frees all the memory associated with the control
     function C.

 - Function: int gsl_odeiv_control_hadjust (gsl_odeiv_control * C,
          gsl_odeiv_step * S, const double y0[], const double yerr[],
          const double dydt[], double * H)
     This function adjusts the step-size H using the control function
     C, and the current values of Y, YERR and DYDT.  The stepping
     function STEP is also needed to determine the order of the method.
     If the error in the y-values YERR is found to be too large then
     the step-size H is reduced and the function returns
     `GSL_ODEIV_HADJ_DEC'.  If the error is sufficiently small then H
     may be increased and `GSL_ODEIV_HADJ_INC' is returned.  The
     function returns `GSL_ODEIV_HADJ_NIL' if the step-size is
     unchanged.  The goal of the function is to estimate the largest
     step-size which satisfies the user-specified accuracy requirements
     for the current point.

 - Function: const char * gsl_odeiv_control_name (const
          gsl_odeiv_control * C)
     This function returns a pointer to the name of the control
     function.  For example,

          printf("control method is '%s'\n",
                 gsl_odeiv_control_name (c));

     would print something like `control method is 'standard''


File: gsl-ref.info,  Node: Evolution,  Next: ODE Example programs,  Prev: Adaptive Step-size Control,  Up: Ordinary Differential Equations

Evolution
=========

   The highest level of the system is the evolution function which
combines the results of a stepping function and control function to
reliably advance the solution forward over an interval (t_0, t_1).  If
the control function signals that the step-size should be decreased the
evolution function backs out of the current step and tries the proposed
smaller step-size.  This is process is continued until an acceptable
step-size is found.

 - Function: gsl_odeiv_evolve * gsl_odeiv_evolve_alloc (size_t DIM)
     This function returns a pointer to a newly allocated instance of an
     evolution function for a system of DIM dimensions.

 - Function: int gsl_odeiv_evolve_apply (gsl_odeiv_evolve * E,
          gsl_odeiv_control * CON, gsl_odeiv_step * STEP, const
          gsl_odeiv_system * DYDT, double * T, double T1, double * H,
          double y[])
     This function advances the system (E, DYDT) from time T and
     position Y using the stepping function STEP.  The new time and
     position are stored in T and Y on output.  The initial step-size
     is taken as H, but this will be modified using the control
     function C to achieve the appropriate error bound if necessary.
     The routine may make several calls to STEP in order to determine
     the optimum step-size. If the step-size has been changed the value
     of H will be modified on output.  The maximum time T1 is
     guaranteed not to be exceeded by the time-step.  On the final
     time-step the value of T will be set to T1 exactly.

 - Function: int gsl_odeiv_evolve_reset (gsl_odeiv_evolve * E)
     This function resets the evolution function E.  It should be used
     whenever the next use of E will not be a continuation of a
     previous step.

 - Function: void gsl_odeiv_evolve_free (gsl_odeiv_evolve * E)
     This function frees all the memory associated with the evolution
     function E.


File: gsl-ref.info,  Node: ODE Example programs,  Next: ODE References and Further Reading,  Prev: Evolution,  Up: Ordinary Differential Equations

Examples
========

   The following program solves the second-order nonlinear Van der Pol
oscillator equation,

     x''(t) + \mu x'(t) (x(t)^2 - 1) + x(t) = 0

This can be converted into a first order system suitable for use with
the library by introducing a separate variable for the velocity, y =
x'(t),

     x' = y
     y' = -x + \mu y (1-x^2)

The program begins by defining functions for these derivatives and
their Jacobian,

     #include <stdio.h>
     #include <gsl/gsl_errno.h>
     #include <gsl/gsl_matrix.h>
     #include <gsl/gsl_odeiv.h>
     
     int
     func (double t, const double y[], double f[],
           void *params)
     {
       double mu = *(double *)params;
       f[0] = y[1];
       f[1] = -y[0] - mu*y[1]*(y[0]*y[0] - 1);
       return GSL_SUCCESS;
     }
     
     int
     jac (double t, const double y[], double *dfdy,
          double dfdt[], void *params)
     {
       double mu = *(double *)params;
       gsl_matrix_view dfdy_mat
         = gsl_matrix_view_array (dfdy, 2, 2);
       gsl_matrix * m = &dfdy_mat.matrix;
       gsl_matrix_set (m, 0, 0, 0.0);
       gsl_matrix_set (m, 0, 1, 1.0);
       gsl_matrix_set (m, 1, 0, -2.0*mu*y[0]*y[1] - 1.0);
       gsl_matrix_set (m, 1, 1, -mu*(y[0]*y[0] - 1.0));
       dfdt[0] = 0.0;
       dfdt[1] = 0.0;
       return GSL_SUCCESS;
     }
     
     int
     main (void)
     {
       const gsl_odeiv_step_type * T
         = gsl_odeiv_step_rk8pd;
     
       gsl_odeiv_step * s
         = gsl_odeiv_step_alloc (T, 2);
       gsl_odeiv_control * c
         = gsl_odeiv_control_y_new (1e-6, 0.0);
       gsl_odeiv_evolve * e
         = gsl_odeiv_evolve_alloc (2);
     
       double mu = 10;
       gsl_odeiv_system sys = {func, jac, 2, &mu};
     
       double t = 0.0, t1 = 100.0;
       double h = 1e-6;
       double y[2] = { 1.0, 0.0 };
     
       while (t < t1)
         {
           int status = gsl_odeiv_evolve_apply (e, c, s,
                                                &sys,
                                                &t, t1,
                                                &h, y);
     
           if (status != GSL_SUCCESS)
               break;
     
           printf("%.5e %.5e %.5e\n", t, y[0], y[1]);
         }
     
       gsl_odeiv_evolve_free(e);
       gsl_odeiv_control_free(c);
       gsl_odeiv_step_free(s);
       return 0;
     }

The main loop of the program evolves the solution from (y, y') = (1, 0)
at t=0 to t=100.  The step-size h is automatically adjusted by the
controller to maintain an absolute accuracy of 10^{-6} in the function
values Y.

To obtain the values at regular intervals, rather than the variable
spacings chosen by the control function, the main loop can be modified
to advance the solution from one point to the next.  For example, the
following main loop prints the solution at the fixed points t = 0, 1,
2, \dots, 100,

       for (i = 1; i <= 100; i++)
         {
           double ti = i * t1 / 100.0;
     
           while (t < ti)
             {
               gsl_odeiv_evolve_apply (e, c, s,
                                       &sys,
                                       &t, ti, &h,
                                       y);
             }
     
           printf("%.5e %.5e %.5e\n", t, y[0], y[1]);
         }

It is also possible to work with a non-adaptive integrator, using only
the stepping function itself.  The following program uses the `rk4'
fourth-order Runge-Kutta stepping function with a fixed stepsize of
0.01,

     int
     main (void)
     {
       const gsl_odeiv_step_type * T
         = gsl_odeiv_step_rk4;
     
       gsl_odeiv_step * s
         = gsl_odeiv_step_alloc (T, 2);
     
       double mu = 10;
       gsl_odeiv_system sys = {func, jac, 2, &mu};
     
       double t = 0.0, t1 = 100.0;
       double h = 1e-2;
       double y[2] = { 1.0, 0.0 }, y_err[2];
       double dfdy[4], dydt_in[2], dydt_out[2];
     
       /* initialise dydt_in */
       GSL_ODEIV_JA_EVAL(&sys, t, y, dfdy, dydt_in);
     
       while (t < t1)
         {
           int status = gsl_odeiv_step_apply (s, t, h,
                                              y, y_err,
                                              dydt_in,
                                              dydt_out,
                                              &sys);
     
           if (status != GSL_SUCCESS)
               break;
     
           dydt_in[0] = dydt_out[0];
           dydt_in[1] = dydt_out[1];
     
           t += h;
     
           printf("%.5e %.5e %.5e\n", t, y[0], y[1]);
         }
     
       gsl_odeiv_step_free(s);
       return 0;
     }

The derivatives and jacobian must be initialised for the starting point
t=0 before the first step is taken.  Subsequent steps use the output
derivatives DYDT_OUT as inputs to the next step by copying their values
into DYDT_IN.


File: gsl-ref.info,  Node: ODE References and Further Reading,  Prev: ODE Example programs,  Up: Ordinary Differential Equations

References and Further Reading
==============================

Many of the basic Runge-Kutta formulas can be found in the Handbook of
Mathematical Functions,

     Abramowitz & Stegun (eds.), `Handbook of Mathematical Functions',
     Section 25.5.

The implicit Bulirsch-Stoer algorithm `bsimp' is described in the
following paper,

     G. Bader and P. Deuflhard, "A Semi-Implicit Mid-Point Rule for
     Stiff Systems of Ordinary Differential Equations.", Numer. Math.
     41, 373-398, 1983.


File: gsl-ref.info,  Node: Interpolation,  Next: Numerical Differentiation,  Prev: Ordinary Differential Equations,  Up: Top

Interpolation
*************

   This chapter describes functions for performing interpolation.  The
library provides a variety of interpolation methods, including Cubic
splines and Akima splines.  The interpolation types are interchangeable,
allowing different methods to be used without recompiling.
Interpolations can be defined for both normal and periodic boundary
conditions.  Additional functions are available for computing
derivatives and integrals of interpolating functions.

   The functions described in this section are declared in the header
files `gsl_interp.h' and `gsl_spline.h'.

* Menu:

* Introduction to Interpolation::
* Interpolation Functions::
* Interpolation Types::
* Index Look-up and Acceleration::
* Evaluation of Interpolating Functions::
* Higher-level Interface::
* Interpolation Example programs::
* Interpolation References and Further Reading::


File: gsl-ref.info,  Node: Introduction to Interpolation,  Next: Interpolation Functions,  Up: Interpolation

Introduction
============

   Given a set of data points (x_1, y_1) \dots (x_n, y_n) the routines
described in this section compute a continuous interpolating function
y(x) such that y_i = y(x_i).  The interpolation is piecewise smooth,
and its behavior at the end-points is determined by the type of
interpolation used.


File: gsl-ref.info,  Node: Interpolation Functions,  Next: Interpolation Types,  Prev: Introduction to Interpolation,  Up: Interpolation

Interpolation Functions
=======================

   The interpolation function for a given dataset is stored in a
`gsl_interp' object.  These are created by the following functions.

 - Function: gsl_interp * gsl_interp_alloc (const gsl_interp_type * T,
          size_t SIZE)
     This function returns a pointer to a newly allocated interpolation
     object of type T for SIZE data-points.

 - Function: int gsl_interp_init (gsl_interp * INTERP, const double
          XA[], const double YA[], size_t SIZE)
     This function initializes the interpolation object INTERP for the
     data (XA,YA) where XA and YA are arrays of size SIZE.  The
     interpolation object (`gsl_interp') does not save the data arrays
     XA and YA and only stores the static state computed from the data.
     The XA data array is always assumed to be strictly ordered; the
     behavior for other arrangements is not defined.

 - Function: void gsl_interp_free (gsl_interp * INTERP)
     This function frees the interpolation object INTERP.


File: gsl-ref.info,  Node: Interpolation Types,  Next: Index Look-up and Acceleration,  Prev: Interpolation Functions,  Up: Interpolation

Interpolation Types
===================

   The interpolation library provides five interpolation types:

 - Interpolation Type: gsl_interp_linear
     Linear interpolation.  This interpolation method does not require
     any additional memory.

 - Interpolation Type: gsl_interp_polynomial
     Polynomial interpolation.  This method should only be used for
     interpolating small numbers of points because polynomial
     interpolation introduces large oscillations, even for well-behaved
     datasets.  The number of terms in the interpolating polynomial is
     equal to the number of points.

 - Interpolation Type: gsl_interp_cspline
     Cubic spline with natural boundary conditions.

 - Interpolation Type: gsl_interp_cspline_periodic
     Cubic spline with periodic boundary conditions

 - Interpolation Type: gsl_interp_akima
     Akima spline with natural boundary conditions.

 - Interpolation Type: gsl_interp_akima_periodic
     Akima spline with periodic boundary conditions.

   The following related functions are available:

 - Function: const char * gsl_interp_name (const gsl_interp * INTERP)
     This function returns the name of the interpolation type used by
     INTERP.  For example,

          printf("interp uses '%s' interpolation.\n",
                 gsl_interp_name (interp));

     would print something like,
          interp uses 'cspline' interpolation.

 - Function: unsigned int gsl_interp_min_size (const gsl_interp *
          INTERP)
     This function returns the minimum number of points required by the
     interpolation type of INTERP.  For example, Akima spline
     interpolation requires a minimum of 5 points.


File: gsl-ref.info,  Node: Index Look-up and Acceleration,  Next: Evaluation of Interpolating Functions,  Prev: Interpolation Types,  Up: Interpolation

Index Look-up and Acceleration
==============================

   The state of searches can be stored in a `gsl_interp_accel' object,
which is a kind of iterator for interpolation lookups.  It caches the
previous value of an index lookup.  When the subsequent interpolation
point falls in the same interval its index value can be returned
immediately.

 - Function: size_t gsl_interp_bsearch (const double x_array[], double
          X, size_t INDEX_LO, size_t INDEX_HI)
     This function returns the index i of the array X_ARRAY such that
     `x_array[i] <= x < x_array[i+1]'.  The index is searched for in
     the range [INDEX_LO,INDEX_HI].

 - Function: gsl_interp_accel * gsl_interp_accel_alloc (void)
     This function returns a pointer to an accelerator object, which is
     a kind of iterator for interpolation lookups.  It tracks the state
     of lookups, thus allowing for application of various acceleration
     strategies.

 - Function: size_t gsl_interp_accel_find (gsl_interp_accel * A, const
          double x_array[], size_t SIZE, double X)
     This function performs a lookup action on the data array X_ARRAY
     of size SIZE, using the given accelerator A.  This is how lookups
     are performed during evaluation of an interpolation.  The function
     returns an index i such that `xarray[i] <= x < xarray[i+1]'.

 - Function: void gsl_interp_accel_free (gsl_interp_accel* A)
     This function frees the accelerator object A.


File: gsl-ref.info,  Node: Evaluation of Interpolating Functions,  Next: Higher-level Interface,  Prev: Index Look-up and Acceleration,  Up: Interpolation

Evaluation of Interpolating Functions
=====================================

 - Function: double gsl_interp_eval (const gsl_interp * INTERP, const
          double XA[], const double YA[], double X, gsl_interp_accel *
          A)
 - Function: int gsl_interp_eval_e (const gsl_interp * INTERP, const
          double XA[], const double YA[], double X, gsl_interp_accel *
          A, double * Y)
     These functions return the interpolated value of Y for a given
     point X, using the interpolation object INTERP, data arrays XA and
     YA and the accelerator A.

 - Function: double gsl_interp_eval_deriv (const gsl_interp * INTERP,
          const double XA[], const double YA[], double X,
          gsl_interp_accel * A)
 - Function: int gsl_interp_eval_deriv_e (const gsl_interp * INTERP,
          const double XA[], const double YA[], double X,
          gsl_interp_accel * A, double * D)
     These functions return the derivative D of an interpolated
     function for a given point X, using the interpolation object
     INTERP, data arrays XA and YA and the accelerator A.

 - Function: double gsl_interp_eval_deriv2 (const gsl_interp * INTERP,
          const double XA[], const double YA[], double X,
          gsl_interp_accel * A)
 - Function: int gsl_interp_eval_deriv2_e (const gsl_interp * INTERP,
          const double XA[], const double YA[], double X,
          gsl_interp_accel * A, double * D2)
     These functions return the second derivative D2 of an interpolated
     function for a given point X, using the interpolation object
     INTERP, data arrays XA and YA and the accelerator A.

 - Function: double gsl_interp_eval_integ (const gsl_interp * INTERP,
          const double XA[], const double YA[], double A, double
          Bdouble X, gsl_interp_accel * A)
 - Function: int gsl_interp_eval_integ_e (const gsl_interp * INTERP,
          const double XA[], const double YA[], , double A, double B,
          gsl_interp_accel * A, double * RESULT)
     These functions return the numerical integral RESULT of an
     interpolated function over the range [A, B], using the
     interpolation object INTERP, data arrays XA and YA and the
     accelerator A.


File: gsl-ref.info,  Node: Higher-level Interface,  Next: Interpolation Example programs,  Prev: Evaluation of Interpolating Functions,  Up: Interpolation

Higher-level Interface
======================

   The functions described in the previous sections required the user to
supply pointers to the x and y arrays on each call.  The following
functions are equivalent to the corresponding `gsl_interp' functions
but maintain a copy of this data in the `gsl_spline' object.  This
removes the need to pass both XA and YA as arguments on each
evaluation. These functions are defined in the header file
`gsl_spline.h'.

 - Function: gsl_spline * gsl_spline_alloc (const gsl_interp_type * T,
          size_t N)

 - Function: int gsl_spline_init (gsl_spline * SPLINE, const double
          xa[], const double YA[], size_t SIZE)

 - Function: void gsl_spline_free (gsl_spline * SPLINE)

 - Function: double gsl_spline_eval (const gsl_spline * SPLINE, double
          X, gsl_interp_accel * A)
 - Function: int gsl_spline_eval_e (const gsl_spline * SPLINE, double
          X, gsl_interp_accel * A, double * Y)

 - Function: double gsl_spline_eval_deriv (const gsl_spline * SPLINE,
          double X, gsl_interp_accel * A)
 - Function: int gsl_spline_eval_deriv_e (const gsl_spline * SPLINE,
          double X, gsl_interp_accel * A, double * D)

 - Function: double gsl_spline_eval_deriv2 (const gsl_spline * SPLINE,
          double X, gsl_interp_accel * A)
 - Function: int gsl_spline_eval_deriv2_e (const gsl_spline * SPLINE,
          double X, gsl_interp_accel * A, double * D2)

 - Function: double gsl_spline_eval_integ (const gsl_spline * SPLINE,
          double A, double B, gsl_interp_accel * ACC)
 - Function: int gsl_spline_eval_integ_e (const gsl_spline * SPLINE,
          double A, double B, gsl_interp_accel * ACC, double * RESULT)

