예제 #1
0
def test_WignerDindex(ell_max_slow):
    k = 0
    for ell_max in range(ell_max_slow + 1):
        r = sf.WignerDrange(0, ell_max)
        for ell in range(ell_max + 1):
            for mp in range(-ell, ell + 1):
                for m in range(-ell, ell + 1):
                    i = sf.WignerDindex(ell, mp, m)
                    assert np.array_equal(r[i], [ell, mp, m]), ((ell, mp, m),
                                                                i, ell_max, r)
                    k += 1
        for ell_min in range(ell_max + 1):
            r = sf.WignerDrange(ell_min, ell_max)
            for ell in range(ell_min, ell_max + 1):
                for mp in range(-ell, ell + 1):
                    for m in range(-ell, ell + 1):
                        i = sf.WignerDindex(ell, mp, m, ell_min)
                        assert np.array_equal(r[i],
                                              [ell, mp, m]), ((ell, mp,
                                                               m), i, ell_min,
                                                              ell_max, r)
                        k += 1
            for mp_max in range(ell_max + 1):
                r = sf.WignerDrange(ell_min, mp_max, ell_max)
                for ell in range(ell_min, ell_max + 1):
                    for mp in range(-min(ell, mp_max), min(ell, mp_max) + 1):
                        for m in range(-ell, ell + 1):
                            i = sf.WignerDindex(ell, mp, m, ell_min, mp_max)
                            assert np.array_equal(
                                r[i], [ell, mp, m]), ((ell, mp, m), i, ell_min,
                                                      mp_max, ell_max, r)
                        k += 1
예제 #2
0
def test_WignerDrange(ell_max_slow):
    def r(ell_min, mp_max, ell_max):
        return [(ℓ, mp, m) for ℓ in range(ell_min, ell_max + 1)
                for mp in range(-min(ℓ, mp_max),
                                min(ℓ, mp_max) + 1) for m in range(-ℓ, ℓ + 1)]

    for ell_max in range(ell_max_slow // 2 + 1):
        for ell_min in range(ell_max + 1):
            a = sf.WignerDrange(ell_min, ell_max)  # Implicitly, mp_max=ell_max
            b = r(ell_min, ell_max, ell_max)
            assert np.array_equal(a, b), ((ell_min, mp_max, ell_max), a, b)
            for mp_max in range(ell_max + 1):
                a = sf.WignerDrange(ell_min, mp_max, ell_max)
                b = r(ell_min, mp_max, ell_max)
                assert np.array_equal(a, b), ((ell_min, mp_max, ell_max), a, b)
예제 #3
0
def test_Wigner_D_underflow(Rs, ell_max, eps):
    # NOTE: This is a delicate test, which depends on the result underflowing exactly when expected.
    # In particular, it should underflow to 0.0 when |mp+m|>32, but should never underflow to 0.0
    # when |mp+m|<32.  So it's not the end of the world if this test fails, but it does mean that
    # the underflow properties have changed, so it might be worth a look.
    epsilon = 1.e-10

    ϵ = 5 * ell_max * eps
    D = np.zeros(sf.WignerDsize(0, ell_max), dtype=complex)
    wigner = sf.Wigner(ell_max)
    ell_mp_m = sf.WignerDrange(0, ell_max)

    # Test |Ra|=1e-10
    R = quaternionic.array(epsilon, 1, 0, 0).normalized
    wigner.D(R, out=D)
    # print(R.to_euler_angles.tolist())
    # print(D.tolist())
    non_underflowing_indices = np.abs(ell_mp_m[:, 1] + ell_mp_m[:, 2]) < 32
    assert np.all(D[non_underflowing_indices] != 0j)
    underflowing_indices = np.abs(ell_mp_m[:, 1] + ell_mp_m[:, 2]) > 32
    assert np.all(D[underflowing_indices] == 0j)

    # Test |Rb|=1e-10
    R = quaternionic.array(1, epsilon, 0, 0).normalized
    wigner.D(R, out=D)
    non_underflowing_indices = np.abs(ell_mp_m[:, 1] - ell_mp_m[:, 2]) < 32
    assert np.all(D[non_underflowing_indices] != 0j)
    underflowing_indices = np.abs(ell_mp_m[:, 1] - ell_mp_m[:, 2]) > 32
    assert np.all(D[underflowing_indices] == 0j)
예제 #4
0
def test_WignerDsize_mpmax_ellmin(ell_max):
    # k = 0
    for ell_max in range(ell_max + 1):
        for ell_min in range(ell_max + 1):
            for mp_max in range(ell_max + 1):
                a = sf.WignerDsize(ell_min, mp_max, ell_max)
                b = len(sf.WignerDrange(ell_min, mp_max, ell_max))
                assert a == b, ((ell_min, mp_max, ell_max), a, b)  #, k)
예제 #5
0
def test_Wigner_D_symmetries(Rs, ell_max, eps):
    # We have two obvious symmetries to test.  First,
    #
    #   D_{mp,m}(R) = (-1)^{mp+m} \bar{D}_{-mp,-m}(R)
    #
    # Second, since D is a unitary matrix, its conjugate transpose is its
    # inverse; because of the representation property, D(R) should equal the
    # matrix inverse of D(R⁻¹).  Thus,
    #
    #   D_{mp,m}(R) = \bar{D}_{m,mp}(\bar{R})

    ϵ = 5 * ell_max * eps
    D1 = np.zeros(sf.WignerDsize(0, ell_max), dtype=complex)
    D2 = np.zeros(sf.WignerDsize(0, ell_max), dtype=complex)
    wigner = sf.Wigner(ell_max)
    ell_mp_m = sf.WignerDrange(0, ell_max)

    flipped_indices = np.array(
        [sf.WignerDindex(ell, -mp, -m) for ell, mp, m in ell_mp_m])
    swapped_indices = np.array(
        [sf.WignerDindex(ell, m, mp) for ell, mp, m in ell_mp_m])
    signs = (-1)**np.abs(np.sum(ell_mp_m[:, 1:], axis=1))
    for R in Rs:
        wigner.D(R, out=D1)
        wigner.D(R.inverse, out=D2)
        # D_{mp,m}(R) = (-1)^{mp+m} \bar{D}_{-mp,-m}(R)
        a = D1
        b = signs * D1[flipped_indices].conjugate()
        assert np.allclose(a, b, rtol=ϵ, atol=ϵ)
        # D_{mp,m}(R) = \bar{D}_{m,mp}(\bar{R})
        b = D2[swapped_indices].conjugate()
        assert np.allclose(a, b, rtol=ϵ, atol=ϵ)

    D1 = wigner.D(Rs)
    D2 = wigner.D(Rs.inverse)
    # D_{mp,m}(R) = (-1)^{mp+m} \bar{D}_{-mp,-m}(R)
    a = D1
    b = signs * D1[..., flipped_indices].conjugate()
    assert np.allclose(a, b, rtol=ϵ, atol=ϵ)
    # D_{mp,m}(R) = \bar{D}_{m,mp}(\bar{R})
    b = D2[..., swapped_indices].conjugate()
    assert np.allclose(a, b, rtol=ϵ, atol=ϵ)
예제 #6
0
def test_Wigner_D_vs_Wikipedia(special_angles, ell_max_slow, eps):
    ell_max = ell_max_slow
    ϵ = 5 * ell_max**6 * eps

    D = np.zeros(sf.WignerDsize(0, ell_max), dtype=complex)
    wigner = sf.Wigner(ell_max)
    ell_mp_m = sf.WignerDrange(0, ell_max)

    print("")
    for alpha in special_angles:
        print("\talpha={0}".format(alpha))  # Need to show some progress for CI
        for beta in special_angles[len(special_angles) // 2:]:  # Skip beta < 0
            print("\t\tbeta={0}".format(beta))
            for gamma in special_angles:
                a = np.conjugate(
                    np.array([
                        Wigner_D_Wikipedia(alpha, beta, gamma, ell, mp, m)
                        for ell, mp, m in ell_mp_m
                    ]))
                b = wigner.D(quaternionic.array.from_euler_angles(
                    alpha, beta, gamma),
                             out=D)
                assert np.allclose(a, b, rtol=ϵ, atol=ϵ)