|
Packit |
67cb25 |
.. index::
|
|
Packit |
67cb25 |
single: discrete Hankel transforms
|
|
Packit |
67cb25 |
single: Hankel transforms, discrete
|
|
Packit |
67cb25 |
single: transforms, Hankel
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
**************************
|
|
Packit |
67cb25 |
Discrete Hankel Transforms
|
|
Packit |
67cb25 |
**************************
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
This chapter describes functions for performing Discrete Hankel
|
|
Packit |
67cb25 |
Transforms (DHTs). The functions are declared in the header file
|
|
Packit |
67cb25 |
:file:`gsl_dht.h`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Definitions
|
|
Packit |
67cb25 |
===========
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
The discrete Hankel transform acts on a vector of sampled data, where
|
|
Packit |
67cb25 |
the samples are assumed to have been taken at points related to the
|
|
Packit |
67cb25 |
zeros of a Bessel function of fixed order; compare this to the case of
|
|
Packit |
67cb25 |
the discrete Fourier transform, where samples are taken at points
|
|
Packit |
67cb25 |
related to the zeroes of the sine or cosine function.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Starting with its definition, the Hankel transform (or Bessel transform) of
|
|
Packit |
67cb25 |
order :math:`\nu` of a function :math:`f` with :math:`\nu > -1/2` is defined as
|
|
Packit |
67cb25 |
(see Johnson, 1987 and Lemoine, 1994)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. math:: F_\nu(u) = \int_0^\infty f(t) J_\nu(u t) t dt
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
If the integral exists, :math:`F_\nu` is called the Hankel transformation
|
|
Packit |
67cb25 |
of :math:`f`. The reverse transform is given by
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. math:: f(t) = \int_0^\infty F_\nu(u) J_\nu(u t) u du
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
where :math:`\int_0^\infty f(t) t^{1/2} dt` must exist and be
|
|
Packit |
67cb25 |
absolutely convergent, and where :math:`f(t)` satisfies Dirichlet's
|
|
Packit |
67cb25 |
conditions (of limited total fluctuations) in the interval
|
|
Packit |
67cb25 |
:math:`[0,\infty]`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Now the discrete Hankel transform works on a discrete function
|
|
Packit |
67cb25 |
:math:`f`, which is sampled on points :math:`n=1...M` located at
|
|
Packit |
67cb25 |
positions :math:`t_n=(j_{\nu,n}/j_{\nu,M}) X` in real space and
|
|
Packit |
67cb25 |
at :math:`u_n=j_{\nu,n}/X` in reciprocal space. Here,
|
|
Packit |
67cb25 |
:math:`j_{\nu,m}` are the m-th zeros of the Bessel function
|
|
Packit |
67cb25 |
:math:`J_\nu(x)` arranged in ascending order. Moreover, the
|
|
Packit |
67cb25 |
discrete functions are assumed to be band limited, so
|
|
Packit |
67cb25 |
:math:`f(t_n)=0` and :math:`F(u_n)=0` for :math:`n>M`. Accordingly,
|
|
Packit |
67cb25 |
the function :math:`f` is defined on the interval :math:`[0,X]`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Following the work of Johnson, 1987 and
|
|
Packit |
67cb25 |
Lemoine, 1994, the discrete Hankel transform is given by
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. only:: not texinfo
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. math::
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
F_\nu(u_m) = {{2 X^2}\over{j_{\nu,M}^2}}
|
|
Packit |
67cb25 |
\sum_{k=1}^{M-1} f\left({{j_{\nu,k} X}\over{j_{\nu,M}}}\right)
|
|
Packit |
67cb25 |
{{J_\nu(j_{\nu,m} j_{\nu,k} / j_{\nu,M})}\over{J_{\nu+1}(j_{\nu,k})^2}}.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. only:: texinfo
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
::
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
F_\nu(u_m) = (2 X^2 / j_(\nu,M)^2)
|
|
Packit |
67cb25 |
\sum_{k=1}^{M-1} f(j_(\nu,k) X/j_(\nu,M))
|
|
Packit |
67cb25 |
(J_\nu(j_(\nu,m) j_(\nu,k) / j_(\nu,M)) / J_(\nu+1)(j_(\nu,k))^2).
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
It is this discrete expression which defines the discrete Hankel
|
|
Packit |
67cb25 |
transform calculated by GSL. In GSL, forward and backward transforms
|
|
Packit |
67cb25 |
are defined equally and calculate :math:`F_\nu(u_m)`.
|
|
Packit |
67cb25 |
Following Johnson, the backward transform reads
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. only:: not texinfo
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. math::
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
f(t_k) = {{2}\over{X^2}}
|
|
Packit |
67cb25 |
\sum_{m=1}^{M-1} F\left({{j_{\nu,m}}\over{X}}\right)
|
|
Packit |
67cb25 |
{{J_\nu(j_{\nu,m} j_{\nu,k} / j_{\nu,M})}\over{J_{\nu+1}(j_{\nu,m})^2}}.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. only:: texinfo
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
::
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
f(t_k) = (2 / X^2)
|
|
Packit |
67cb25 |
\sum_{m=1}^{M-1} F(j_(\nu,m)/X)
|
|
Packit |
67cb25 |
(J_\nu(j_(\nu,m) j_(\nu,k) / j_(\nu,M)) / J_(\nu+1)(j_(\nu,m))^2).
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Obviously, using the forward transform instead of the backward transform gives an
|
|
Packit |
67cb25 |
additional factor :math:`X^4/j_{\nu,M}^2=t_m^2/u_m^2`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
The kernel in the summation above defines the matrix of the
|
|
Packit |
67cb25 |
:math:`\nu`-Hankel transform of size :math:`M-1`. The coefficients of
|
|
Packit |
67cb25 |
this matrix, being dependent on :math:`\nu` and :math:`M`, must be
|
|
Packit |
67cb25 |
precomputed and stored; the :type:`gsl_dht` object encapsulates this
|
|
Packit |
67cb25 |
data. The allocation function :func:`gsl_dht_alloc` returns a
|
|
Packit |
67cb25 |
:type:`gsl_dht` object which must be properly initialized with
|
|
Packit |
67cb25 |
:func:`gsl_dht_init` before it can be used to perform transforms on data
|
|
Packit |
67cb25 |
sample vectors, for fixed :math:`\nu` and :math:`M`, using the
|
|
Packit |
67cb25 |
:func:`gsl_dht_apply` function. The implementation allows to define the
|
|
Packit |
67cb25 |
length :math:`X` of the fundamental interval, for convenience, while
|
|
Packit |
67cb25 |
discrete Hankel transforms are often defined on the unit interval
|
|
Packit |
67cb25 |
instead of :math:`[0,X]`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Notice that by assumption :math:`f(t)` vanishes at the endpoints
|
|
Packit |
67cb25 |
of the interval, consistent with the inversion formula
|
|
Packit |
67cb25 |
and the sampling formula given above. Therefore, this transform
|
|
Packit |
67cb25 |
corresponds to an orthogonal expansion in eigenfunctions
|
|
Packit |
67cb25 |
of the Dirichlet problem for the Bessel differential equation.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Functions
|
|
Packit |
67cb25 |
=========
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. type:: gsl_dht
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Workspace for computing discrete Hankel transforms
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. function:: gsl_dht * gsl_dht_alloc (size_t size)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
This function allocates a Discrete Hankel transform object of size
|
|
Packit |
67cb25 |
:data:`size`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. function:: int gsl_dht_init (gsl_dht * t, double nu, double xmax)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
This function initializes the transform :data:`t` for the given values of
|
|
Packit |
67cb25 |
:data:`nu` and :data:`xmax`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. function:: gsl_dht * gsl_dht_new (size_t size, double nu, double xmax)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
This function allocates a Discrete Hankel transform object of size
|
|
Packit |
67cb25 |
:data:`size` and initializes it for the given values of :data:`nu` and
|
|
Packit |
67cb25 |
:data:`xmax`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. function:: void gsl_dht_free (gsl_dht * t)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
This function frees the transform :data:`t`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. function:: int gsl_dht_apply (const gsl_dht * t, double * f_in, double * f_out)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
This function applies the transform :data:`t` to the array :data:`f_in`
|
|
Packit |
67cb25 |
whose size is equal to the size of the transform. The result is stored
|
|
Packit |
67cb25 |
in the array :data:`f_out` which must be of the same length.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
Applying this function to its output gives the original data
|
|
Packit |
67cb25 |
multiplied by :math:`(X^2/j_{\nu,M})^2`,
|
|
Packit |
67cb25 |
up to numerical errors.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. function:: double gsl_dht_x_sample (const gsl_dht * t, int n)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
This function returns the value of the :data:`n`-th sample point in the unit interval,
|
|
Packit |
67cb25 |
:math:`{({j_{\nu,n+1}} / {j_{\nu,M}}}) X`.
|
|
Packit |
67cb25 |
These are the points where the function :math:`f(t)` is assumed to be sampled.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
.. function:: double gsl_dht_k_sample (const gsl_dht * t, int n)
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
This function returns the value of the :data:`n`-th sample point in "k-space",
|
|
Packit |
67cb25 |
:math:`{{j_{\nu,n+1}} / X}`.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
References and Further Reading
|
|
Packit |
67cb25 |
==============================
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
The algorithms used by these functions are described in the following papers,
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
* H. Fisk Johnson, Comp.: Phys.: Comm.: 43, 181 (1987).
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
* D. Lemoine, J. Chem.: Phys.: 101, 3936 (1994).
|