Exemplo n.º 1
0
def spherical_besselj_root(ell, nmax, only=True, derivative=False):
    r"""Find positive zero(s) :math:`u_{\ell n}` of the spherical Bessel
    function :math:`j_{\ell}` of the first kind of order :math:`\ell`, or
    its derivative :math:`j'_{\ell}`, up to a maximum number
    :math:`n_\textrm{max}`.

    Solving for roots of the spherical Bessel function relies on the
    identity :math:`j_\ell(x) = \sqrt{\pi/(2x)} J_{\ell + 1/2}(x)`, where
    :math:`J_\ell(x)` is the Bessel funcion of the first kind.  Solving for
    roots of the derivative function employs the interval bisection method,
    with the interval ansatz :math:`\ell + 1 \leqslant x \leqslant
    n_\textrm{max} \operatorname{max}\{4, \ell\}`.

    Parameters
    ----------
    ell : int
        Order of the spherical Bessel function, ``ell >= 0``.
    nmax : int
        Maximum number of positive zeros to be found, ``nmax >= 1``.
    only : bool, optional
        If `True` (default), return the maximal root only.
    derivative : bool, optional
        If `True` (default is `False`), compute the zero(s) of the
        derivative function instead.

    Returns
    -------
    u_ell : float, array_like
        Positive zero(s) for order `ell` (in ascending order).

    """
    if not derivative:
        # `mpmath` returns a ``mpf`` float which needs conversion.
        if only:
            u_ell = float(besseljzero(ell + 0.5, nmax, derivative=0))
        else:
            u_ell = np.asarray([
                float(besseljzero(ell + 0.5, n, derivative=0))
                for n in range(1, nmax + 1)
            ])
    else:
        u_elln_list = binary_search(
            lambda x: spherical_besselj(ell, x, derivative=True),
            ell + 1, nmax * max(4, ell),
            maxnum=nmax
        )
        u_ell = u_elln_list[-1] if only else u_elln_list

    return u_ell
Exemplo n.º 2
0
Arquivo: bessel.py Projeto: Aang/sympy
def jn_zeros(n, k, method="sympy"):
    """
    Zeros of the spherical Bessel function of the first kind.

    This returns an array of zeros of jn up to the k-th zero.

    method = "sympy": uses the SymPy's jn and findroot to find all roots
    method = "scipy": uses the SciPy's sph_jn and newton to find all roots,
            which if faster than method="sympy", but it requires SciPy and only
            works with low precision floating point numbers

    Examples:

        >>> from sympy.mpmath import nprint
        >>> from sympy import jn_zeros
        >>> nprint(jn_zeros(2, 4))
        [5.76345919689, 9.09501133048, 12.3229409706, 15.5146030109]

    """
    if method == "sympy":
        from sympy.mpmath import findroot
        f = lambda x: jn(n, x).n()
    elif method == "scipy":
        from scipy.special import sph_jn
        from scipy.optimize import newton
        f  = lambda x: sph_jn(n, x)[0][-1]
    elif method == 'mpmath':
        # this needs a recent version of mpmath, newer than in sympy
        from mpmath import besseljzero
        return [besseljzero(n + 0.5, k) for k in xrange(1, k + 1)]
    else:
        raise NotImplementedError("Unknown method.")
    def solver(f, x):
        if method == "sympy":
            # findroot(solver="newton") or findroot(solver="secant") can't find
            # the root within the given tolerance. So we use solver="muller",
            # which converges towards complex roots (even for real starting
            # points), and so we need to chop all complex parts (that are small
            # anyway). Also we need to set the tolerance, as it sometimes fail
            # without it.
            def f_real(x):
                return f(complex(x).real)
            root = findroot(f_real, x, solver="muller", tol=1e-9)
            root = complex(root).real
        elif method == "scipy":
            root = newton(f, x)
        else:
            raise NotImplementedError("Unknown method.")
        return root

    # we need to approximate the position of the first root:
    root = n+pi
    # determine the first root exactly:
    root = solver(f, root)
    roots = [root]
    for i in range(k-1):
        # estimate the position of the next root using the last root + pi:
        root = solver(f, root+pi)
        roots.append(root)
    return roots
Exemplo n.º 3
0
def test_bessel_dirichlet(m, N_coordinates, N_basis_functions = None):
  N_basis_functions = N_basis_functions or N_coordinates
  
  S_guess = bessel_dirichlet_S_guess(m, max(N_basis_functions, N_coordinates))
  bessel_j_zeros = numpy.double([mpmath.besseljzero(m, i) for i in xrange(1, N_basis_functions+1)])
  bessel_j_values = numpy.sqrt(2.0) / numpy.abs(scipy.special.jn(m + 1, bessel_j_zeros))
  
  return test_bessel(m, S_guess, N_coordinates, bessel_j_zeros, bessel_j_values, bessel_initial_guess)
Exemplo n.º 4
0
def bessel_initial_guess(m, N, S_guess):
  bessel_j_zeros = [mpmath.besseljzero(m, i) for i in xrange(1, N+1)]
  abscissas = [zero / S_guess for zero in bessel_j_zeros]
  weights = [2.0 / (S_guess * mpmath.besselj(m + 1, bessel_j_zeros[i]))**2 for i in xrange(N)]

  weights = numpy.reshape(numpy.double(weights), (N,))
  abscissas = numpy.reshape(numpy.double(abscissas), (N,))
  
  return weights, abscissas
Exemplo n.º 5
0
def besselJZeros(m, a, b):
  require_mpmath()
  if not hasattr(mpmath, 'besseljzero'):
    besseljn = lambda x: mpmath.besselj(m, x)
    results = [mpmath.findroot(besseljn, mpmath.pi*(kp - 1./4 + 0.5*m)) for kp in range(a, b+1)]
  else:
    results = [mpmath.besseljzero(m, i) for i in xrange(a, b+1)]
  # Check that we haven't found double roots or missed a root. All roots should be separated by approximately pi
  assert all([0.6*mpmath.pi < (b - a) < 1.4*mpmath.pi for a, b in zip(results[:-1], results[1:])]), "Separation of Bessel zeros was incorrect."
  return results
Exemplo n.º 6
0
def test_bessel_neumann(m, N_coordinates, N_basis_functions = None):
  N_basis_functions = N_basis_functions or N_coordinates
  
  S_guess = bessel_neumann_S_guess(m, max(N_basis_functions, N_coordinates))
  bessel_j_zeros = numpy.double([mpmath.besseljzero(m, i, derivative=True) for i in xrange(1, N_basis_functions+1)])
  bessel_j_values = numpy.sqrt(2.0) / numpy.abs(scipy.special.jn(m, bessel_j_zeros))
  
  if m > 0:
    bessel_j_values /= numpy.sqrt(1.0 - (m / bessel_j_zeros)**2)

  return test_bessel(m, S_guess, N_coordinates, bessel_j_zeros, bessel_j_values, bessel_initial_guess)
Exemplo n.º 7
0
def bessel_neumann_kspace_initial_guess(m, N, S_guess):
  bessel_j_zeros = [mpmath.besseljzero(m, i, derivative=True) for i in xrange(1, N+1)]
  abscissas = [zero / S_guess for zero in bessel_j_zeros]
  additional_factor = (lambda i: 1.0) if m == 0 else (lambda i: 1.0 - (m/bessel_j_zeros[i])**2)
  
  weights = [2.0 / (S_guess * additional_factor(i) * mpmath.besselj(m, bessel_j_zeros[i]))**2 for i in xrange(N)]
  
  weights = numpy.reshape(numpy.double(weights), (N,))
  abscissas = numpy.reshape(numpy.double(abscissas), (N,))
  
  return weights, abscissas
Exemplo n.º 8
0
def jn_zeros(n, k, method="diofant", dps=15):
    """
    Zeros of the spherical Bessel function of the first kind.

    This returns an array of zeros of jn up to the k-th zero.

    * method = "diofant": uses mpmath's function ``besseljzero``
    * method = "scipy": uses the
      `SciPy's sph_jn <http://docs.scipy.org/doc/scipy/reference/generated/scipy.special.jn_zeros.html>`_
      and
      `newton <http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.newton.html>`_
      to find all
      roots, which is faster than computing the zeros using a general
      numerical solver, but it requires SciPy and only works with low
      precision floating point numbers.  [The function used with
      method="diofant" is a recent addition to mpmath, before that a general
      solver was used.]

    Examples
    ========

    >>> from diofant import jn_zeros
    >>> jn_zeros(2, 4, dps=5)
    [5.7635, 9.095, 12.323, 15.515]

    See Also
    ========

    jn, yn, besselj, besselk, bessely
    """
    from math import pi

    if method == "diofant":
        prec = dps_to_prec(dps)
        return [
            Expr._from_mpmath(
                besseljzero(sympify(n + 0.5)._to_mpmath(prec), int(l)), prec)
            for l in range(1, k + 1)
        ]
    elif method == "scipy":
        from scipy.optimize import newton
        try:
            from scipy.special import spherical_jn
        except ImportError:  # pragma: no cover
            from scipy.special import sph_jn

            def spherical_jn(n, x):
                return sph_jn(n, x)[0][-1]

        def f(x):
            return spherical_jn(n, x)
    else:
        raise NotImplementedError("Unknown method.")

    def solver(f, x):
        if method == "scipy":
            root = newton(f, x)
        else:
            raise NotImplementedError("Unknown method.")
        return root

    # we need to approximate the position of the first root:
    root = n + pi
    # determine the first root exactly:
    root = solver(f, root)
    roots = [root]
    for i in range(k - 1):
        # estimate the position of the next root using the last root + pi:
        root = solver(f, root + pi)
        roots.append(root)
    return roots
Exemplo n.º 9
0
def jn_zeros(n, k, method="sympy", dps=15):
    """
    Zeros of the spherical Bessel function of the first kind.

    This returns an array of zeros of jn up to the k-th zero.

    * method = "sympy": uses :func:`mpmath.besseljzero`
    * method = "scipy": uses the
      `SciPy's sph_jn <http://docs.scipy.org/doc/scipy/reference/generated/scipy.special.jn_zeros.html>`_
      and
      `newton <http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.newton.html>`_
      to find all
      roots, which is faster than computing the zeros using a general
      numerical solver, but it requires SciPy and only works with low
      precision floating point numbers.  [The function used with
      method="sympy" is a recent addition to mpmath, before that a general
      solver was used.]

    Examples
    ========

    >>> from sympy import jn_zeros
    >>> jn_zeros(2, 4, dps=5)
    [5.7635, 9.095, 12.323, 15.515]

    See Also
    ========

    jn, yn, besselj, besselk, bessely
    """
    from math import pi

    if method == "sympy":
        from mpmath import besseljzero
        from mpmath.libmp.libmpf import dps_to_prec
        from sympy import Expr

        prec = dps_to_prec(dps)
        return [Expr._from_mpmath(besseljzero(S(n + 0.5)._to_mpmath(prec), int(l)), prec) for l in range(1, k + 1)]
    elif method == "scipy":
        from scipy.special import sph_jn
        from scipy.optimize import newton

        f = lambda x: sph_jn(n, x)[0][-1]
    else:
        raise NotImplementedError("Unknown method.")

    def solver(f, x):
        if method == "scipy":
            root = newton(f, x)
        else:
            raise NotImplementedError("Unknown method.")
        return root

    # we need to approximate the position of the first root:
    root = n + pi
    # determine the first root exactly:
    root = solver(f, root)
    roots = [root]
    for i in range(k - 1):
        # estimate the position of the next root using the last root + pi:
        root = solver(f, root + pi)
        roots.append(root)
    return roots
Exemplo n.º 10
0
def besselJPrimeZeros(m, a, b):
  require_mpmath()
  results = [mpmath.besseljzero(m, i, derivative=1) for i in xrange(a, b+1)]
  return results
Exemplo n.º 11
0
def jn_zeros(n, k, method="diofant", dps=15):
    """
    Zeros of the spherical Bessel function of the first kind.

    This returns an array of zeros of jn up to the k-th zero.

    * method = "diofant": uses mpmath's function ``besseljzero``
    * method = "scipy": uses :func:`scipy.special.jn_zeros`.
      and :func:`scipy.optimize.newton` to find all
      roots, which is faster than computing the zeros using a general
      numerical solver, but it requires SciPy and only works with low
      precision floating point numbers.  [The function used with
      method="diofant" is a recent addition to mpmath, before that a general
      solver was used.]

    Examples
    ========

    >>> jn_zeros(2, 4, dps=5)
    [5.7635, 9.095, 12.323, 15.515]

    See Also
    ========

    jn, yn, besselj, besselk, bessely

    """
    from math import pi

    if method == "diofant":
        prec = dps_to_prec(dps)
        return [Expr._from_mpmath(besseljzero(sympify(n + 0.5)._to_mpmath(prec),
                                              int(l)), prec)
                for l in range(1, k + 1)]
    elif method == "scipy":
        from scipy.optimize import newton
        try:
            from scipy.special import spherical_jn
        except ImportError:  # pragma: no cover
            from scipy.special import sph_jn

            def spherical_jn(n, x):
                return sph_jn(n, x)[0][-1]

        def f(x):
            return spherical_jn(n, x)
    else:
        raise NotImplementedError("Unknown method.")

    def solver(f, x):
        if method == "scipy":
            root = newton(f, x)
        else:
            raise NotImplementedError("Unknown method.")
        return root

    # we need to approximate the position of the first root:
    root = n + pi
    # determine the first root exactly:
    root = solver(f, root)
    roots = [root]
    for i in range(k - 1):
        # estimate the position of the next root using the last root + pi:
        root = solver(f, root + pi)
        roots.append(root)
    return roots
Exemplo n.º 12
0
from sympy.abc import x,n
from sympy.utilities.lambdify import lambdify
from scipy.special import j1,j0,jn_zeros
import numpy as np
import matplotlib.pyplot as plt
from sympy import *
import math
from mpltools.style import use as uuu
from mpmath import besseljzero
uuu('ggplot')

a=10.0
nu=1.0
nmax=100
Omega = 1.0
l = [float(besseljzero(1,n+1)) for n in range(nmax + 1)]

def u(r,t):
   summ=0
   for n in xrange(nmax):
      summ+=j1(r/a * l[n]) / (l[n] * j0(l[n]))  *  math.exp((- l[n]**2 * t * nu / a**2))
   return - 2 * Omega * summ

fig = plt.figure(num=None, figsize=(7.5,5), dpi=300)
ax = fig.add_subplot(1,1,1)

box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width, box.height])

ax.axis([0,a*100,0,Omega])
Exemplo n.º 13
0
def jn_zeros(n, k, method="sympy"):
    """
    Zeros of the spherical Bessel function of the first kind.

    This returns an array of zeros of jn up to the k-th zero.

    method = "sympy": uses the SymPy's jn and findroot to find all roots
    method = "scipy": uses the SciPy's sph_jn and newton to find all roots,
            which if faster than method="sympy", but it requires SciPy and only
            works with low precision floating point numbers

    Examples:

        >>> from sympy.mpmath import nprint
        >>> from sympy import jn_zeros
        >>> nprint(jn_zeros(2, 4))
        [5.76345919689, 9.09501133048, 12.3229409706, 15.5146030109]

    """
    if method == "sympy":
        from sympy.mpmath import findroot
        f = lambda x: jn(n, x).n()
    elif method == "scipy":
        from scipy.special import sph_jn
        from scipy.optimize import newton
        f = lambda x: sph_jn(n, x)[0][-1]
    elif method == 'mpmath':
        # this needs a recent version of mpmath, newer than in sympy
        from mpmath import besseljzero
        return [besseljzero(n + 0.5, k) for k in xrange(1, k + 1)]
    else:
        raise NotImplementedError("Unknown method.")

    def solver(f, x):
        if method == "sympy":
            # findroot(solver="newton") or findroot(solver="secant") can't find
            # the root within the given tolerance. So we use solver="muller",
            # which converges towards complex roots (even for real starting
            # points), and so we need to chop all complex parts (that are small
            # anyway). Also we need to set the tolerance, as it sometimes fail
            # without it.
            def f_real(x):
                return f(complex(x).real)

            root = findroot(f_real, x, solver="muller", tol=1e-9)
            root = complex(root).real
        elif method == "scipy":
            root = newton(f, x)
        else:
            raise NotImplementedError("Unknown method.")
        return root

    # we need to approximate the position of the first root:
    root = n + pi
    # determine the first root exactly:
    root = solver(f, root)
    roots = [root]
    for i in range(k - 1):
        # estimate the position of the next root using the last root + pi:
        root = solver(f, root + pi)
        roots.append(root)
    return roots
Exemplo n.º 14
0
def bessel_dirichlet_S_guess(m, N):
  return numpy.double(mpmath.besseljzero(m, N+1))
Exemplo n.º 15
0
def bessel_neumann_S_guess(m, N):
  return numpy.double(mpmath.besseljzero(m, N+1, derivative=True))