[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-gsl] Numerical quadrature performed on a set of points
From: |
crow |
Subject: |
Re: [Help-gsl] Numerical quadrature performed on a set of points |
Date: |
13 Jul 2008 15:26:59 -0500 |
In some cases it makes sense to compute the quadrature formula associated
with the knots. So given x[0], ..., x[n - 1], compute the associated
weights w[0], ..., w[n - 1] and your integral is approximated by w[0] *
f(x[0]) + ... + w[n - 1] * f(x[n - 1]). The snippet below uses GSL to
generate weights so that your quadrature is exact for polynomials of degree
less than n. Check it out, especially if you are using n > 10 since the
system is not well-conditioned. Something to keep in mind is that you
really want nonnegative weights, and there is no guarantee you'll get them.
So if you go this route, make sure you check that none of the generated
weights are negative; if they are, maybe partition the knots into left and
right sets and try again.
Good luck -
- John
#include <stdlib.h>
#include <math.h>
#include "gsl/gsl_linalg.h"
#include "gsl/gsl_matrix.h"
#include "gsl/gsl_vector.h"
static void _getweights( unsigned n, double *x, double *w )
{
unsigned i, j;
double scale;
double t;
double xmax = x[0];
double xmin = x[0];
gsl_matrix *moments = gsl_matrix_alloc( n, n );
gsl_matrix *v = gsl_matrix_alloc( n, n );
gsl_vector *s = gsl_vector_alloc( n );
gsl_vector *work = gsl_vector_alloc( n );
gsl_vector *w0 = gsl_vector_alloc( n );
gsl_vector *r0 = gsl_vector_alloc( n );
for ( i = 1; i < n; i++ ) { /* scale knots to [0, 1] */
if ( x[i] > xmax )
xmax = x[i];
if ( x[i] < xmin )
xmin = x[i];
}
scale = 1 / ( xmax - xmin );
/* Compute the moment matrix and right hand side */
for ( i = 0; i < n; i++ ) {
for ( j = 0; j < n; j++ ) {
t = scale * ( x[j] - xmin );
gsl_matrix_set( moments, i, j, pow( t, ( double ) i ) );
}
gsl_vector_set( r0, i, 1.0 / ( i + 1 ) );
}
gsl_linalg_SV_decomp( moments, v, s, work );
gsl_linalg_SV_solve( moments, v, s, r0, w0 );
for ( i = 0; i < n; i++ )
w[i] = gsl_vector_get( w0, i ) / scale;
gsl_matrix_free( moments );
gsl_matrix_free( v );
gsl_vector_free( s );
gsl_vector_free( work );
gsl_vector_free( w0 );
gsl_vector_free( r0 );
}