Пример #1
0
def test_manualintegrate_orthogonal_poly():
    n = symbols('n')
    a, b = 7, Rational(5, 3)
    polys = [jacobi(n, a, b, x), gegenbauer(n, a, x), chebyshevt(n, x),
        chebyshevu(n, x), legendre(n, x), hermite(n, x), laguerre(n, x),
        assoc_laguerre(n, a, x)]
    for p in polys:
        integral = manualintegrate(p, x)
        for deg in [-2, -1, 0, 1, 3, 5, 8]:
            # some accept negative "degree", some do not
            try:
                p_subbed = p.subs(n, deg)
            except ValueError:
                continue
            assert (integral.subs(n, deg).diff(x) - p_subbed).expand() == 0

        # can also integrate simple expressions with these polynomials
        q = x*p.subs(x, 2*x + 1)
        integral = manualintegrate(q, x)
        for deg in [2, 4, 7]:
            assert (integral.subs(n, deg).diff(x) - q.subs(n, deg)).expand() == 0

        # cannot integrate with respect to any other parameter
        t = symbols('t')
        for i in range(len(p.args) - 1):
            new_args = list(p.args)
            new_args[i] = t
            assert isinstance(manualintegrate(p.func(*new_args), t), Integral)
Пример #2
0
def wigner_d_naive_v2(l, m, n, beta):
    """
    Wigner d functions as defined in the SOFT 2.0 documentation.
    When approx_lim is set to a high value, this function appears to give
    identical results to Johann Goetz' wignerd() function.

    However, integration fails: does not satisfy orthogonality relations everywhere...
    """
    from scipy.special import jacobi

    if n >= m:
        xi = 1
    else:
        xi = (-1)**(n - m)

    mu = np.abs(m - n)
    nu = np.abs(n + m)
    s = l - (mu + nu) * 0.5

    sq = np.sqrt((np.math.factorial(s) * np.math.factorial(s + mu + nu)) /
                 (np.math.factorial(s + mu) * np.math.factorial(s + nu)))
    sinb = np.sin(beta * 0.5)**mu
    cosb = np.cos(beta * 0.5)**nu
    P = jacobi(s, mu, nu)(np.cos(beta))
    return xi * sq * sinb * cosb * P
Пример #3
0
def wigner_d_naive(l, m, n, beta):
    """
    Numerically naive implementation of the Wigner-d function.
    This is useful for checking the correctness of other implementations.

    :param l: the degree of the Wigner-d function. l >= 0
    :param m: the order of the Wigner-d function. -l <= m <= l
    :param n: the order of the Wigner-d function. -l <= n <= l
    :param beta: the argument. 0 <= beta <= pi
    :return: d^l_mn(beta) in the TODO: what basis? complex, quantum(?), centered, cs(?)
    """
    from scipy.special import eval_jacobi
    try:
        from scipy.misc import factorial
    except:
        from scipy.special import factorial

    from sympy.functions.special.polynomials import jacobi, jacobi_normalized
    from sympy.abc import j, a, b, x
    from sympy import N
    #jfun = jacobi_normalized(j, a, b, x)
    jfun = jacobi(j, a, b, x)
    # eval_jacobi = lambda q, r, p, o: float(jfun.eval(int(q), int(r), int(p), float(o)))
    # eval_jacobi = lambda q, r, p, o: float(N(jfun, int(q), int(r), int(p), float(o)))
    eval_jacobi = lambda q, r, p, o: float(
        jfun.subs({
            j: int(q),
            a: int(r),
            b: int(p),
            x: float(o)
        }))

    mu = np.abs(m - n)
    nu = np.abs(m + n)
    s = l - (mu + nu) / 2
    xi = 1 if n >= m else (-1)**(n - m)

    # print(s, mu, nu, np.cos(beta), type(s), type(mu), type(nu), type(np.cos(beta)))
    jac = eval_jacobi(s, mu, nu, np.cos(beta))
    z = np.sqrt((factorial(s) * factorial(s + mu + nu)) /
                (factorial(s + mu) * factorial(s + nu)))

    # print(l, m, n, beta, np.isfinite(mu), np.isfinite(nu), np.isfinite(s), np.isfinite(xi), np.isfinite(jac), np.isfinite(z))
    assert np.isfinite(mu) and np.isfinite(nu) and np.isfinite(
        s) and np.isfinite(xi) and np.isfinite(jac) and np.isfinite(z)
    assert np.isfinite(xi * z * np.sin(beta / 2)**mu * np.cos(beta / 2)**nu *
                       jac)
    return xi * z * np.sin(beta / 2)**mu * np.cos(beta / 2)**nu * jac
Пример #4
0
def test_jacobi():
    n = Symbol("n")
    a = Symbol("a")
    b = Symbol("b")

    assert jacobi(0, a, b, x) == 1
    assert jacobi(1, a, b, x) == a / 2 - b / 2 + x * (a / 2 + b / 2 + 1)

    assert jacobi(n, a, a, x) == RisingFactorial(a + 1, n) * gegenbauer(
        n, a + S.Half, x) / RisingFactorial(2 * a + 1, n)
    assert jacobi(n, a, -a,
                  x) == ((-1)**a * (-x + 1)**(-a / 2) * (x + 1)**(a / 2) *
                         assoc_legendre(n, a, x) * factorial(-a + n) *
                         gamma(a + n + 1) / (factorial(a + n) * gamma(n + 1)))
    assert jacobi(n, -b, b, x) == ((-x + 1)**(b / 2) * (x + 1)**(-b / 2) *
                                   assoc_legendre(n, b, x) *
                                   gamma(-b + n + 1) / gamma(n + 1))
    assert jacobi(n, 0, 0, x) == legendre(n, x)
    assert jacobi(n, S.Half, S.Half, x) == RisingFactorial(Rational(
        3, 2), n) * chebyshevu(n, x) / factorial(n + 1)
    assert jacobi(
        n, Rational(-1, 2), Rational(-1, 2),
        x) == RisingFactorial(S.Half, n) * chebyshevt(n, x) / factorial(n)

    X = jacobi(n, a, b, x)
    assert isinstance(X, jacobi)

    assert jacobi(n, a, b, -x) == (-1)**n * jacobi(n, b, a, x)
    assert jacobi(n, a, b, 0) == 2**(-n) * gamma(a + n + 1) * hyper(
        (-b - n, -n), (a + 1, ), -1) / (factorial(n) * gamma(a + 1))
    assert jacobi(n, a, b, 1) == RisingFactorial(a + 1, n) / factorial(n)

    m = Symbol("m", positive=True)
    assert jacobi(m, a, b, oo) == oo * RisingFactorial(a + b + m + 1, m)
    assert unchanged(jacobi, n, a, b, oo)

    assert conjugate(jacobi(m, a, b, x)) == \
        jacobi(m, conjugate(a), conjugate(b), conjugate(x))

    _k = Dummy('k')
    assert diff(jacobi(n, a, b, x), n) == Derivative(jacobi(n, a, b, x), n)
    assert diff(jacobi(n, a, b, x), a).dummy_eq(
        Sum((jacobi(n, a, b, x) + (2 * _k + a + b + 1) *
             RisingFactorial(_k + b + 1, -_k + n) * jacobi(_k, a, b, x) /
             ((-_k + n) * RisingFactorial(_k + a + b + 1, -_k + n))) /
            (_k + a + b + n + 1), (_k, 0, n - 1)))
    assert diff(jacobi(n, a, b, x), b).dummy_eq(
        Sum(((-1)**(-_k + n) * (2 * _k + a + b + 1) *
             RisingFactorial(_k + a + 1, -_k + n) * jacobi(_k, a, b, x) /
             ((-_k + n) * RisingFactorial(_k + a + b + 1, -_k + n)) +
             jacobi(n, a, b, x)) / (_k + a + b + n + 1), (_k, 0, n - 1)))
    assert diff(jacobi(n, a, b, x), x) == \
        (a/2 + b/2 + n/2 + S.Half)*jacobi(n - 1, a + 1, b + 1, x)

    assert jacobi_normalized(n, a, b, x) == \
           (jacobi(n, a, b, x)/sqrt(2**(a + b + 1)*gamma(a + n + 1)*gamma(b + n + 1)
                                    /((a + b + 2*n + 1)*factorial(n)*gamma(a + b + n + 1))))

    raises(ValueError, lambda: jacobi(-2.1, a, b, x))
    raises(ValueError,
           lambda: jacobi(Dummy(positive=True, integer=True), 1, 2, oo))

    assert jacobi(n, a, b, x).rewrite("polynomial").dummy_eq(
        Sum((S.Half - x / 2)**_k * RisingFactorial(-n, _k) *
            RisingFactorial(_k + a + 1, -_k + n) *
            RisingFactorial(a + b + n + 1, _k) / factorial(_k),
            (_k, 0, n)) / factorial(n))
    raises(ArgumentIndexError, lambda: jacobi(n, a, b, x).fdiff(5))
Пример #5
0
def wigner_d_naive_v3(l, m, n, approx_lim=1000000):
    """
    Wigner "small d" matrix. (Euler z-y-z convention)
    example:
        l = 2
        m = 1
        n = 0
        beta = linspace(0,pi,100)
        wd210 = wignerd(l,m,n)(beta)

    some conditions have to be met:
         l >= 0
        -l <= m <= l
        -l <= n <= l

    The approx_lim determines at what point
    bessel functions are used. Default is when:
        l > m+10
          and
        l > n+10

    for integer l and n=0, we can use the spherical harmonics. If in
    addition m=0, we can use the ordinary legendre polynomials.
    """
    from scipy.special import jv, legendre, sph_harm, jacobi
    from scipy.misc import factorial, comb
    from numpy import floor, sqrt, sin, cos, exp, power
    from math import pi
    from scipy.special import jacobi

    if (l < 0) or (abs(m) > l) or (abs(n) > l):
        raise ValueError("wignerd(l = {0}, m = {1}, n = {2}) value error.".format(l, m, n) \
            + " Valid range for parameters: l>=0, -l<=m,n<=l.")

    if (l > (m + approx_lim)) and (l > (n + approx_lim)):
        #print 'bessel (approximation)'
        return lambda beta: jv(m - n, l * beta)

    if (floor(l) == l) and (n == 0):
        if m == 0:
            #print 'legendre (exact)'
            return lambda beta: legendre(l)(cos(beta))
        elif False:
            #print 'spherical harmonics (exact)'
            a = sqrt(4. * pi / (2. * l + 1.))
            return lambda beta: a * sph_harm(m, l, beta, 0.).conj()

    jmn_terms = {
        l + n: (m - n, m - n),
        l - n: (n - m, 0.),
        l + m: (n - m, 0.),
        l - m: (m - n, m - n),
    }

    k = min(jmn_terms)
    a, lmb = jmn_terms[k]

    b = 2. * l - 2. * k - a

    if (a < 0) or (b < 0):
        raise ValueError("wignerd(l = {0}, m = {1}, n = {2}) value error.".format(l, m, n) \
            + " Encountered negative values in (a,b) = ({0},{1})".format(a,b))

    coeff = power(-1., lmb) * sqrt(comb(2. * l - k,
                                        k + a)) * (1. / sqrt(comb(k + b, b)))

    #print 'jacobi (exact)'
    return lambda beta: coeff \
        * power(sin(0.5*beta),a) \
        * power(cos(0.5*beta),b) \
        * jacobi(k,a,b)(cos(beta))