Пример #1
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 mpmath besseljzero
    * method = "scipy": uses the SciPy's sph_jn and 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="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 sympy.mpmath import besseljzero
        from sympy.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(k)), prec)
                for k in xrange(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
Пример #2
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 mpmath besseljzero
    * method = "scipy": uses the SciPy's sph_jn and 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="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 sympy.mpmath import besseljzero
        from sympy.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(k)), prec) \
                for k in xrange(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
Пример #3
0
    def evalf(self, n=15, subs=None, maxn=100, chop=False, strict=False, quad=None, verbose=False):
        """
        Evaluate the given formula to an accuracy of n digits.
        Optional keyword arguments:

            subs=<dict>
                Substitute numerical values for symbols, e.g.
                subs={x:3, y:1+pi}.

            maxn=<integer>
                Allow a maximum temporary working precision of maxn digits
                (default=100)

            chop=<bool>
                Replace tiny real or imaginary parts in subresults
                by exact zeros (default=False)

            strict=<bool>
                Raise PrecisionExhausted if any subresult fails to evaluate
                to full accuracy, given the available maxprec
                (default=False)

            quad=<str>
                Choose algorithm for numerical quadrature. By default,
                tanh-sinh quadrature is used. For oscillatory
                integrals on an infinite interval, try quad='osc'.

            verbose=<bool>
                Print debug information (default=False)

        """
        # for sake of sage that doesn't like evalf(1)
        if n == 1 and isinstance(self, C.Number):
            from sympy.core.expr import _mag

            rv = self.evalf(2, subs, maxn, chop, strict, quad, verbose)
            m = _mag(rv)
            rv = rv.round(1 - m)
            return rv

        if not evalf_table:
            _create_evalf_table()
        prec = dps_to_prec(n)
        options = {"maxprec": max(prec, int(maxn * LG10)), "chop": chop, "strict": strict, "verbose": verbose}
        if subs is not None:
            options["subs"] = subs
        if quad is not None:
            options["quad"] = quad
        try:
            result = evalf(self, prec + 4, options)
        except NotImplementedError:
            # Fall back to the ordinary evalf
            v = self._eval_evalf(prec)
            if v is None:
                return self
            try:
                # If the result is numerical, normalize it
                result = evalf(v, prec, options)
            except NotImplementedError:
                # Probably contains symbols or unknown functions
                return v
        re, im, re_acc, im_acc = result
        if re:
            p = max(min(prec, re_acc), 1)
            # re = mpf_pos(re, p, rnd)
            re = C.Float._new(re, p)
        else:
            re = S.Zero
        if im:
            p = max(min(prec, im_acc), 1)
            # im = mpf_pos(im, p, rnd)
            im = C.Float._new(im, p)
            return re + im * S.ImaginaryUnit
        else:
            return re
Пример #4
0
    def evalf(self, n=15, subs=None, maxn=100, chop=False, strict=False, quad=None, verbose=False):
        """
        Evaluate the given formula to an accuracy of n digits.
        Optional keyword arguments:

            subs=<dict>
                Substitute numerical values for symbols, e.g.
                subs={x:3, y:1+pi}. The substitutions must be given as a
                dictionary.

            maxn=<integer>
                Allow a maximum temporary working precision of maxn digits
                (default=100)

            chop=<bool>
                Replace tiny real or imaginary parts in subresults
                by exact zeros (default=False)

            strict=<bool>
                Raise PrecisionExhausted if any subresult fails to evaluate
                to full accuracy, given the available maxprec
                (default=False)

            quad=<str>
                Choose algorithm for numerical quadrature. By default,
                tanh-sinh quadrature is used. For oscillatory
                integrals on an infinite interval, try quad='osc'.

            verbose=<bool>
                Print debug information (default=False)

        """
        n = n if n is not None else 15

        if subs and is_sequence(subs):
            raise TypeError('subs must be given as a dictionary')

        # for sake of sage that doesn't like evalf(1)
        if n == 1 and isinstance(self, C.Number):
            from sympy.core.expr import _mag
            rv = self.evalf(2, subs, maxn, chop, strict, quad, verbose)
            m = _mag(rv)
            rv = rv.round(1 - m)
            return rv

        if not evalf_table:
            _create_evalf_table()
        prec = dps_to_prec(n)
        options = {'maxprec': max(prec, int(maxn*LG10)), 'chop': chop,
               'strict': strict, 'verbose': verbose}
        if subs is not None:
            options['subs'] = subs
        if quad is not None:
            options['quad'] = quad
        try:
            result = evalf(self, prec + 4, options)
        except NotImplementedError:
            # Fall back to the ordinary evalf
            v = self._eval_evalf(prec)
            if v is None:
                return self
            try:
                # If the result is numerical, normalize it
                result = evalf(v, prec, options)
            except NotImplementedError:
                # Probably contains symbols or unknown functions
                return v
        re, im, re_acc, im_acc = result
        if re:
            p = max(min(prec, re_acc), 1)
            #re = mpf_pos(re, p, rnd)
            re = C.Float._new(re, p)
        else:
            re = S.Zero
        if im:
            p = max(min(prec, im_acc), 1)
            #im = mpf_pos(im, p, rnd)
            im = C.Float._new(im, p)
            return re + im*S.ImaginaryUnit
        else:
            return re
Пример #5
0
    def evalf(self, n=15, subs=None, maxn=100, chop=False, strict=False, quad=None, verbose=False):
        """
        Evaluate the given formula to an accuracy of n digits.
        Optional keyword arguments:

            subs=<dict>
                Substitute numerical values for symbols, e.g.
                subs={x:3, y:1+pi}.

            maxn=<integer>
                Allow a maximum temporary working precision of maxn digits
                (default=100)

            chop=<bool>
                Replace tiny real or imaginary parts in subresults
                by exact zeros (default=False)

            strict=<bool>
                Raise PrecisionExhausted if any subresult fails to evaluate
                to full accuracy, given the available maxprec
                (default=False)

            quad=<str>
                Choose algorithm for numerical quadrature. By default,
                tanh-sinh quadrature is used. For oscillatory
                integrals on an infinite interval, try quad='osc'.

            verbose=<bool>
                Print debug information (default=False)

        """
        if not evalf_table:
            _create_evalf_table()
        prec = dps_to_prec(n)
        options = {'maxprec': max(prec,int(maxn*LG10)), 'chop': chop,
               'strict': strict, 'verbose': verbose}
        if subs is not None:
            options['subs'] = subs
        if quad is not None:
            options['quad'] = quad
        try:
            result = evalf(self, prec+4, options)
        except NotImplementedError:
            # Fall back to the ordinary evalf
            v = self._eval_evalf(prec)
            if v is None:
                return self
            try:
                # If the result is numerical, normalize it
                result = evalf(v, prec, options)
            except:
                # Probably contains symbols or unknown functions
                return v
        re, im, re_acc, im_acc = result
        if re:
            p = max(min(prec, re_acc), 1)
            #re = mpf_pos(re, p, round_nearest)
            re = C.Real._new(re, p)
        else:
            re = S.Zero
        if im:
            p = max(min(prec, im_acc), 1)
            #im = mpf_pos(im, p, round_nearest)
            im = C.Real._new(im, p)
            return re + im*S.ImaginaryUnit
        else:
            return re