GSL sample: Nonlinear Equation

Last Update: Oct. 4, 2007


Sample code

nonlinear.c

/***********************************************/
/* T.Kouya's GSL sample program collection     */
/*                  Solving Nonlinear Equation */
/*                   Written by Tomonori Kouya */
/*                                             */
/* Version 0.01: 2007-10-04                    */
/***********************************************/
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_roots.h>

/* Limit of Iterative Times */
#define MAXTIMES 100

/* func(x) = 0 */
/* x^2 - 2 = 0 */
double func(double x, void *param)
{
	return x * x - 2;
}

/* f'(x) */
double dfunc(double x, void *param)
{
	return 2.0 * x;
}

/* simultaneous eval of f and df */
void fdfunc(double x, void *param, double *ret_f, double *ret_df)
{
	*ret_f  = func(x, param);
	*ret_df = dfunc(x, param);

	return;
}

int main(void)
{
	int i, times, status;
	gsl_function f;
	gsl_root_fsolver *workspace_f;
	gsl_function_fdf fdf;
	gsl_root_fdfsolver *workspace;
	double x, x_l, x_r;

/* Fsolver */

	/* Define Solver */
	workspace_f = gsl_root_fsolver_alloc(gsl_root_fsolver_bisection);

	printf("F solver: %s\n", gsl_root_fsolver_name(workspace_f));

	f.function = &func;
	f.params = 0;

	/* set initial interval */
	x_l = 0.0;
	x_r = 2 * M_PI;

	/* set solver */
	gsl_root_fsolver_set(workspace_f, &f, x_l, x_r);

	/* main loop */
	for(times = 0; times < MAXTIMES; times++)
	{
		status = gsl_root_fsolver_iterate(workspace_f);

		x_l = gsl_root_fsolver_x_lower(workspace_f);
		x_r = gsl_root_fsolver_x_upper(workspace_f);
		printf("%d times: [%10.3e, %10.3e]\n", times, x_l, x_r);

		status = gsl_root_test_interval(x_l, x_r, 1.0e-13, 1.0e-20);
		if(status != GSL_CONTINUE)
		{
			printf("Status: %s\n", gsl_strerror(status));
			printf("\n Root = [%25.17e, %25.17e]\n\n", x_l, x_r);
			break;
		}
	}

	/* free */
	gsl_root_fsolver_free(workspace_f);

/* FDFsolver */

	/* Define Solver */
	workspace = gsl_root_fdfsolver_alloc(gsl_root_fdfsolver_newton);

	printf("FDF solver: %s\n", gsl_root_fdfsolver_name(workspace));

	fdf.f = &func;
	fdf.df = &dfunc;
	fdf.fdf = &fdfunc;
	fdf.params = 0;

	/* set initial value */
	x = 2.0;

	/* set solver */
	gsl_root_fdfsolver_set(workspace, &fdf, x);

	/* main loop */
	for(times = 0; times < MAXTIMES; times++)
	{
		status = gsl_root_fdfsolver_iterate(workspace);
		x = gsl_root_fdfsolver_root(workspace);
		status = gsl_root_test_residual(func(x, NULL), 1.0e-5);

		printf("%d times: %10.3e\n", times, x);

		if((status != GSL_CONTINUE) || (status == GSL_EZERODIV) || (status == GSL_EZERODIV))
		{
			printf("Status: %s\n", gsl_strerror(status));
			printf("\n Root = %25.17e\n\n", x);
			break;
		}
	}

	/* free */
	gsl_root_fdfsolver_free(workspace);

	return 0;
}

Example execution

$ ./nonlinear
F solver: bisection
0 times: [ 0.000e+00,  3.142e+00]
1 times: [ 0.000e+00,  1.571e+00]
2 times: [ 7.854e-01,  1.571e+00]
3 times: [ 1.178e+00,  1.571e+00]
4 times: [ 1.374e+00,  1.571e+00]
5 times: [ 1.374e+00,  1.473e+00]
6 times: [ 1.374e+00,  1.424e+00]
7 times: [ 1.399e+00,  1.424e+00]
8 times: [ 1.411e+00,  1.424e+00]
9 times: [ 1.411e+00,  1.417e+00]
10 times: [ 1.411e+00,  1.414e+00]
11 times: [ 1.413e+00,  1.414e+00]
12 times: [ 1.414e+00,  1.414e+00]
13 times: [ 1.414e+00,  1.414e+00]
14 times: [ 1.414e+00,  1.414e+00]
15 times: [ 1.414e+00,  1.414e+00]
16 times: [ 1.414e+00,  1.414e+00]
17 times: [ 1.414e+00,  1.414e+00]
18 times: [ 1.414e+00,  1.414e+00]
19 times: [ 1.414e+00,  1.414e+00]
20 times: [ 1.414e+00,  1.414e+00]
21 times: [ 1.414e+00,  1.414e+00]
22 times: [ 1.414e+00,  1.414e+00]
23 times: [ 1.414e+00,  1.414e+00]
24 times: [ 1.414e+00,  1.414e+00]
25 times: [ 1.414e+00,  1.414e+00]
26 times: [ 1.414e+00,  1.414e+00]
27 times: [ 1.414e+00,  1.414e+00]
28 times: [ 1.414e+00,  1.414e+00]
29 times: [ 1.414e+00,  1.414e+00]
30 times: [ 1.414e+00,  1.414e+00]
31 times: [ 1.414e+00,  1.414e+00]
32 times: [ 1.414e+00,  1.414e+00]
33 times: [ 1.414e+00,  1.414e+00]
34 times: [ 1.414e+00,  1.414e+00]
35 times: [ 1.414e+00,  1.414e+00]
36 times: [ 1.414e+00,  1.414e+00]
37 times: [ 1.414e+00,  1.414e+00]
38 times: [ 1.414e+00,  1.414e+00]
39 times: [ 1.414e+00,  1.414e+00]
40 times: [ 1.414e+00,  1.414e+00]
41 times: [ 1.414e+00,  1.414e+00]
42 times: [ 1.414e+00,  1.414e+00]
43 times: [ 1.414e+00,  1.414e+00]
44 times: [ 1.414e+00,  1.414e+00]
45 times: [ 1.414e+00,  1.414e+00]
Status: success

 Root = [  1.41421356237308871e+00,   1.41421356237317797e+00]

FDF solver: newton
0 times:  1.500e+00
1 times:  1.417e+00
2 times:  1.414e+00
Status: success

 Root =   1.41421568627450989e+00

<- Go back