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
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
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
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
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