Example #1
0
 def integrate(self, integrand):
     res = []
     for integ, preset in zip(integrand, self.preset):
         if scipy.isrealobj(integ):
             res.append(fftlog.fht(integ, preset, self.direction))
         else:
             res.append(
                 fftlog.fht(integ.real, preset, self.direction) +
                 1j * fftlog.fht(integ.imag, preset, self.direction))
     return scipy.asarray(res)
Example #2
0
def test_fftlog():
    # This is the example provided in `fftlogtest.f` of the original code. It
    # is the same test that is shown as an example in the gallery.
    # See the example for more details.

    # Parameters.
    logrmin = -4
    logrmax = 4
    n = 64
    mu = 0
    q = 0
    kr = 1
    kropt = 1
    tdir = 1
    logrc = (logrmin + logrmax)/2
    nc = (n + 1)/2.0
    dlogr = (logrmax - logrmin)/n
    dlnr = dlogr*np.log(10.0)

    # Calculate input function: $r^{\mu+1}\exp\left(-\frac{r^2}{2}\right)$.
    r = 10**(logrc + (np.arange(1, n+1) - nc)*dlogr)
    ar = r**(mu + 1)*np.exp(-r**2/2.0)

    # Initialize FFTLog transform - note fhti resets `kr`
    kr, xsave, _ = fhti(n, mu, dlnr, q, kr, kropt)
    assert_allclose(kr, 0.953538967579)
    logkc = np.log10(kr) - logrc
    # rk = 10**(logrc - logkc)

    # Transform
    # ak = fftl(ar.copy(), xsave, rk, tdir)
    ak = fht(ar.copy(), xsave, tdir)

    # Calculate Output function: $k^{\mu+1}\exp\left(-\frac{k^2}{2}\right)$
    k = 10**(logkc + (np.arange(1, n+1) - nc)*dlogr)
    theo = k**(mu + 1)*np.exp(-k**2/2.0)

    # Check values
    assert_allclose(theo[theo > 1e-3], ak[theo > 1e-3], rtol=1e-8, atol=5e-5)
Example #3
0
def iHankel(k, f, N=4096, order=0.5):
    """
    This routine returns the inverse Hankel transform of order :math:`\\nu` of a log-spaced function.
    The computation is

    .. math ::

      f(r) = \int_0^\infty \ dk \ k \ f(k) \ J_\\nu(kr)

    .. warning::

     Because of log-spacing, an extra `k` factor has been already added in the code.

    .. warning::

     If ``order = 0.5`` it is similar to the 3D Fourier transform of a spherically symmetric function.


    Parameters
    ----------

    `k`: array
        Abscissae of function, log-spaced.

    `f`: array
        ordinates of function.

    `N`: int, default = 4096
        Number of output points

    `order`: float, default = 0.5
        Order of the transform (Bessel polynomial).

    Returns
    ----------

    rr: array
        Frequencies.

    Fr: array
        Transformed array.
    """

    # FFT specifics
    mu = order  # Order mu of Bessel function
    q = 0  # Bias exponent: q = 0 is unbiased
    kr = 1  # Sensible approximate choice of k_c r_c
    kropt = 1  # Tell fhti to change kr to low-ringing value
    tdir = -1  # Backward transform
    logkc = (np.max(np.log10(k)) + np.min(np.log10(k))) / 2.
    dlogk = (np.max(np.log10(k)) - np.min(np.log10(k))) / N
    dlnk = dlogk * np.log(10.)
    if N % 2 == 0: nc = N / 2
    else: nc = (N + 1) / 2
    k_t = 10.**(logkc + (np.arange(1, N + 1) - nc) * dlogk)

    # Initialise function (add k_t extra factor because of log-spacing)
    funct = si.interp1d(k, f, kind="cubic", bounds_error=False, fill_value=0.)
    ak = funct(k_t) * k_t

    # Initialization of transform
    #kr, xsave, ok = fftlog.fhti(N, mu, dlnk, q, kr, kropt)
    fft_obj = fftlog.fhti(N, mu, dlnk, q, kr, kropt)
    kr, xsave = fft_obj[0], fft_obj[1]
    logrc = np.log10(kr) - logkc

    # Transform (dividing by a rr extra factor because of log-spacing)
    Fr = fftlog.fht(ak.copy(), xsave, tdir)
    if N % 2 == 0: rr = 10.**(logrc + (np.arange(N) - nc) * dlogk)
    else: rr = 10.**(logrc + (np.arange(1, N + 1) - nc) * dlogk)
    Fr /= rr

    return rr, Fr
Example #4
0
def iHankel_3D_order(k, f, N=4096, order=0):
    """
    This routine is similar to the Fourier transform in 3D but it can return any order of the Bessel function

    .. math ::

      f_\ell(r) = \int_0^\infty \\frac{dk \ k^2}{2\pi^2} \ f(k) \ j_\ell(kr)

    Parameters
    ----------

    `k`: array
        Abscissae of function, log-spaced.

    `f`: array
        ordinates of function.

    `N`: int, default = 4096
        Number of output points

    `order`: float, default = 0
        Order of the Bessel spherical polynomial.

    Returns
    ----------

    rr: array
        Frequencies.

    Fr: array
        Transformed array.
    """
    # FFT specifics
    mu = order + 0.5  # Order mu of Bessel function
    q = 0  # Bias exponent: q = 0 is unbiased
    kr = 1  # Sensible approximate choice of k_c r_c
    kropt = 1  # Tell fhti to change kr to low-ringing value
    tdir = -1  # Backward transform
    logkc = (np.max(np.log10(k)) + np.min(np.log10(k))) / 2.
    dlogk = (np.max(np.log10(k)) - np.min(np.log10(k))) / N
    dlnk = dlogk * np.log(10.)
    if N % 2 == 0: nc = N / 2
    else: nc = (N + 1) / 2
    k_t = 10.**(logkc + (np.arange(1, N + 1) - nc) * dlogk)

    # Initialise function
    funct = si.interp1d(k, f, kind="cubic", bounds_error=False, fill_value=0.)
    ak = funct(k_t) * k_t**1.5

    # Initialization of transform
    #kr, xsave, ok = fftlog.fhti(N, mu, dlnk, q, kr, kropt)
    fft_obj = fftlog.fhti(N, mu, dlnk, q, kr, kropt)
    kr, xsave = fft_obj[0], fft_obj[1]
    logrc = np.log10(kr) - logkc

    # Transform
    ar = fftlog.fht(ak.copy(), xsave, tdir)
    if N % 2 == 0: rr = 10.**(logrc + (np.arange(N) - nc) * dlogk)
    else: rr = 10.**(logrc + (np.arange(1, N + 1) - nc) * dlogk)
    Fr = ar / (2. * np.pi * rr)**1.5

    return rr, Fr
Example #5
0
def Hankel_3D_order(r, f, N=4096, order=0):
    """
    This routine is analogous to the Fourier transform in 3D but it can return any order of the Bessel function

    .. math ::

      f_\ell(k) = \int_0^\infty dr \ 4\pi r^2 \ f(r) \ j_\ell(kr)

    Parameters
    ----------

    `r`: array
        Abscissae of function, log-spaced.

    `f`: array
        ordinates of function.

    `N`: int, default = 4096
        Number of output points

    `order`: float, default = 0
        Order of the Bessel spherical polynomial.

    Returns
    ----------

    kk: array
        Frequencies.

    Fk: array
        Transformed array.
    """
    mu = order + 0.5  # Order mu of Bessel function
    q = 0  # Bias exponent: q = 0 is unbiased
    kr = 1  # Sensible approximate choice of k_c r_c
    kropt = 1  # Tell fhti to change kr to low-ringing value
    tdir = 1  # Forward transform
    logrc = (np.max(np.log10(r)) + np.min(np.log10(r))) / 2.
    dlogr = (np.max(np.log10(r)) - np.min(np.log10(r))) / N
    dlnr = dlogr * np.log(10.)
    if N % 2 == 0: nc = N / 2
    else: nc = (N + 1) / 2
    r_t = 10.**(logrc + (np.arange(1, N + 1) - nc) * dlogr)

    # Initialise function
    funct = si.interp1d(r, f, kind="cubic", bounds_error=False, fill_value=0.)
    ar = funct(r_t) * (2. * np.pi * r_t)**1.5

    # Initialization of transform
    #kr, xsave, ok = fftlog.fhti(N, mu, dlnr, q, kr, kropt)
    fft_obj = fftlog.fhti(N, mu, dlnr, q, kr, kropt)
    kr, xsave = fft_obj[0], fft_obj[1]
    logkc = np.log10(kr) - logrc

    # Transform
    ak = fftlog.fht(ar.copy(), xsave, tdir)
    if N % 2 == 0: kk = 10.**(logkc + (np.arange(N) - nc) * dlogr)
    else: kk = 10.**(logkc + (np.arange(1, N + 1) - nc) * dlogr)
    Fk = ak / kk**1.5

    return kk, Fk
Example #6
0
def iFFT_iso_3D(k, f, N=4096):
    """
    This routine returns the inverse FFT of a radially symmetric function.
    It employs the ``FFTlog`` module, which in turn makes use of the Hankel transform: therefore the function
    that will be actually transformed is :math:`f(k) \ k^{1.5}/(2\pi r)^{1.5}`.
    N.B. Since the integral is performed in log-space, the exponent of `r` is 1.5 instead of 0.5.
    The computation is

    .. math ::

      f(r) = \int_0^\infty \\frac{dk \ k^2}{2\pi^2} \ f(k) \ j_0(kr)

    Parameters
    ----------

    `k`: array
        Abscissae of function, log-spaced.

    `f`: array
        ordinates of function.

    `N`: int, default = 4096
        Number of output points

    Returns
    ----------

    rr: array
        Frequencies.

    Fr: array
        Transformed array.
    """

    # FFT specifics
    mu = 0.5  # Order mu of Bessel function
    q = 0  # Bias exponent: q = 0 is unbiased
    kr = 1  # Sensible approximate choice of k_c r_c
    kropt = 1  # Tell fhti to change kr to low-ringing value
    tdir = -1  # Backward transform
    logkc = (np.max(np.log10(k)) + np.min(np.log10(k))) / 2.
    dlogk = (np.max(np.log10(k)) - np.min(np.log10(k))) / N
    dlnk = dlogk * np.log(10.)
    if N % 2 == 0: nc = N / 2
    else: nc = (N + 1) / 2
    k_t = 10.**(logkc + (np.arange(1, N + 1) - nc) * dlogk)

    # Initialise function
    funct = si.interp1d(k, f, kind="cubic", bounds_error=False, fill_value=0.)
    ak = funct(k_t) * k_t**1.5

    # Initialization of transform
    #kr, xsave, ok = fftlog.fhti(N, mu, dlnk, q, kr, kropt)
    fft_obj = fftlog.fhti(N, mu, dlnk, q, kr, kropt)
    kr, xsave = fft_obj[0], fft_obj[1]
    logrc = np.log10(kr) - logkc

    # Transform
    ar = fftlog.fht(ak.copy(), xsave, tdir)
    if N % 2 == 0: rr = 10.**(logrc + (np.arange(N) - nc) * dlogk)
    else: rr = 10.**(logrc + (np.arange(1, N + 1) - nc) * dlogk)
    Fr = ar / (2 * np.pi * rr)**1.5

    return rr, Fr
Example #7
0
def FFT_iso_3D(r, f, N=4096):
    """
    This routine returns the FFT of a radially symmetric function.
    It employs the ``FFTlog`` module, which in turn makes use of the Hankel transform: therefore the function
    that will be actually transformed is :math:`f(r) \ (2\pi r)^{1.5}/k^{1.5}`.
    N.B. Since the integral is performed in log-space, the exponent of `r` is 1.5 instead of 0.5.
    The computation is

    .. math ::

      f(k) = \int_0^\infty dr \ 4\pi r^2 \ f(r) \ j_0(kr)

    Parameters
    ----------

    `r`: array
        Abscissae of function, log-spaced.

    `f`: array
        ordinates of function.

    `N`: int, default = 4096
        Number of output points

    Returns
    ----------

    kk: array
        Frequencies.

    Fk: array
        Transformed array.
    """
    mu = 0.5  # Order mu of Bessel function
    q = 0  # Bias exponent: q = 0 is unbiased
    kr = 1  # Sensible approximate choice of k_c r_c
    kropt = 1  # Tell fhti to change kr to low-ringing value
    tdir = 1  # Forward transform
    logrc = (np.max(np.log10(r)) + np.min(np.log10(r))) / 2.
    dlogr = (np.max(np.log10(r)) - np.min(np.log10(r))) / N
    dlnr = dlogr * np.log(10.)
    if N % 2 == 0: nc = N / 2
    else: nc = (N + 1) / 2
    r_t = 10.**(logrc + (np.arange(1, N + 1) - nc) * dlogr)

    # Initialise function
    funct = si.interp1d(r, f, kind="cubic", bounds_error=False, fill_value=0.)
    ar = funct(r_t) * (2. * np.pi * r_t)**1.5

    # Initialization of transform
    #kr, xsave, ok = fftlog.fhti(N, mu, dlnr, q, kr, kropt)
    fft_obj = fftlog.fhti(N, mu, dlnr, q, kr, kropt)
    kr, xsave = fft_obj[0], fft_obj[1]
    logkc = np.log10(kr) - logrc

    # Transform
    ak = fftlog.fht(ar.copy(), xsave, tdir)
    if N % 2 == 0: kk = 10.**(logkc + (np.arange(N) - nc) * dlogr)
    else: kk = 10.**(logkc + (np.arange(1, N + 1) - nc) * dlogr)
    Fk = ak / kk**1.5

    return kk, Fk
Example #8
0
kr, wsave, ok = fftlog.fhti(n, mu, dlnr, q, kr, kropt)
print('fftlog.fhti: ok =', bool(ok), '; New kr = ', kr)

# ### Call `fftlog.fht` (or `fftlog.fhtl`)

# In[6]:

logkc = np.log10(kr) - logrc
print('Central point in k-space at log10(k_c) = ', logkc)

# rk = r_c/k_c
rk = 10**(logrc - logkc)

# Transform
#ak = fftlog.fftl(ar.copy(), wsave, rk, tdir)
ak = fftlog.fht(ar.copy(), wsave, tdir)

# ### Calculate Output function: $k^{\mu+1}\exp\left(-\frac{k^2}{2}\right)$

# In[7]:

k = 10**(logkc + (np.arange(1, n + 1) - nc) * dlogr)
theo = k**(mu + 1) * np.exp(-k**2 / 2.0)

# ### Plot result

# In[8]:

plt.figure(figsize=(16, 8))

# Transformed result
Example #9
0
kr, wsave, ok = fftlog.fhti(n, mu, dlnr, kr, q, kropt)
print('fftlog.fhti: ok =', bool(ok), '; New kr = ', kr)

# ### Call `fftlog.fht` (or `fftlog.fhtl`)

# In[6]:

logkc = np.log10(kr) - logrc
print('Central point in k-space at log10(k_c) = ', logkc)

# rk = r_c/k_c
rk = 10**(logrc - logkc)

# Transform
#ak = fftlog.fftl(ar, tdir, wsave, rk)
ak = fftlog.fht(ar.copy(), tdir, wsave)

# ### Calculate Output function: $k^{\mu+1}\exp\left(-\frac{k^2}{2}\right)$

# In[7]:

k = 10**(logkc + (np.arange(1, n + 1) - nc) * dlogr)
theo = k**(mu + 1) * np.exp(-k**2 / 2.0)

# ### Plot result

# In[8]:

plt.figure(figsize=(16, 8))

# Transformed result