Providing the multidimensional system of equations to solve - GNU Scientific Library -- Reference Manual
Description: GNU Scientific Library -- Reference Manual

Next: Iteration of the multidimensional solver, Previous: Initializing the Multidimensional Solver, Up: Multidimensional Root-Finding

### 35.3 Providing the function to solve

You must provide n functions of n variables for the root finders to operate on. In order to allow for general parameters the functions are defined by the following data types:

— Data Type: gsl_multiroot_function

> This data type defines a general system of functions with parameters.

> `int (* f) (const gsl_vector *` x`, void *` params`, gsl_vector *` f`)`
>   this function should store the vector result f(x,params) in f for argument x and parameters params, returning an appropriate error code if the function cannot be computed.
> `size_t n`
>   the dimension of the system, i.e. the number of components of the vectors x and f.
> `void * params`
>   a pointer to the parameters of the function.

Here is an example using Powell's test function,

         f_1(x) = A x_0 x_1 - 1,
         f_2(x) = exp(-x_0) + exp(-x_1) - (1 + 1/A)

with A = 10^4. The following code defines a `gsl_multiroot_function` system `F` which you could pass to a solver:

         struct powell_params { double A; };

         int
         powell (gsl_vector * x, void * p, gsl_vector * f) {
            struct powell_params * params
              = *(struct powell_params *)p;
            const double A = (params->A);
            const double x0 = gsl_vector_get(x,0);
            const double x1 = gsl_vector_get(x,1);

            gsl_vector_set (f, 0, A * x0 * x1 - 1);
            gsl_vector_set (f, 1, (exp(-x0) + exp(-x1)
                                   - (1.0 + 1.0/A)));
            return GSL_SUCCESS
         }

         gsl_multiroot_function F;
         struct powell_params params = { 10000.0 };

         F.f = &powell;
         F.n = 2;
         F.params = &params;

— Data Type: gsl_multiroot_function_fdf

> This data type defines a general system of functions with parameters and the corresponding Jacobian matrix of derivatives,

> `int (* f) (const gsl_vector *` x`, void *` params`, gsl_vector *` f`)`
>   this function should store the vector result f(x,params) in f for argument x and parameters params, returning an appropriate error code if the function cannot be computed.
> `int (* df) (const gsl_vector *` x`, void *` params`, gsl_matrix *` J`)`
>   this function should store the n-by-n matrix result J_ij = d f_i(x,params) / d x_j in J for argument x and parameters params, returning an appropriate error code if the function cannot be computed.
> `int (* fdf) (const gsl_vector *` x`, void *` params`, gsl_vector *` f`, gsl_matrix *` J`)`
>   This function should set the values of the f and J as above, for arguments x and parameters params. This function provides an optimization of the separate functions for f(x) and J(x)—it is always faster to compute the function and its derivative at the same time.
> `size_t n`
>   the dimension of the system, i.e. the number of components of the vectors x and f.
> `void * params`
>   a pointer to the parameters of the function.

The example of Powell's test function defined above can be extended to include analytic derivatives using the following code,

         int
         powell_df (gsl_vector * x, void * p, gsl_matrix * J)
         {
            struct powell_params * params
              = *(struct powell_params *)p;
            const double A = (params->A);
            const double x0 = gsl_vector_get(x,0);
            const double x1 = gsl_vector_get(x,1);
            gsl_matrix_set (J, 0, 0, A * x1);
            gsl_matrix_set (J, 0, 1, A * x0);
            gsl_matrix_set (J, 1, 0, -exp(-x0));
            gsl_matrix_set (J, 1, 1, -exp(-x1));
            return GSL_SUCCESS
         }

         int
         powell_fdf (gsl_vector * x, void * p,
                     gsl_matrix * f, gsl_matrix * J) {
            struct powell_params * params
              = *(struct powell_params *)p;
            const double A = (params->A);
            const double x0 = gsl_vector_get(x,0);
            const double x1 = gsl_vector_get(x,1);

            const double u0 = exp(-x0);
            const double u1 = exp(-x1);

            gsl_vector_set (f, 0, A * x0 * x1 - 1);
            gsl_vector_set (f, 1, u0 + u1 - (1 + 1/A));

            gsl_matrix_set (J, 0, 0, A * x1);
            gsl_matrix_set (J, 0, 1, A * x0);
            gsl_matrix_set (J, 1, 0, -u0);
            gsl_matrix_set (J, 1, 1, -u1);
            return GSL_SUCCESS
         }

         gsl_multiroot_function_fdf FDF;

         FDF.f = &powell_f;
         FDF.df = &powell_df;
         FDF.fdf = &powell_fdf;
         FDF.n = 2;
         FDF.params = 0;

Note that the function `powell_fdf` is able to reuse existing terms from the function when calculating the Jacobian, thus saving time.

The GNU Scientific Library - a free numerical library licensed under the GNU GPL
Back to the GNU Scientific Library Homepage