Пример #1
0
def test_LMpM_range(ell_max):
    for l_max in range(ell_max + 1):
        assert np.array_equal(
            sf.LMpM_range(l_max, l_max),
            np.array([[l_max, mp, m] for mp in range(-l_max, l_max + 1)
                      for m in range(-l_max, l_max + 1)]))
        for l_min in range(l_max + 1):
            assert np.array_equal(
                sf.LMpM_range(l_min, l_max),
                np.array([[ell, mp, m] for ell in range(l_min, l_max + 1)
                          for mp in range(-ell, ell + 1)
                          for m in range(-ell, ell + 1)]))
Пример #2
0
def test_Wigner_D_matrices_representation_property(Rs, ell_max):
    # Test the representation property for special and random angles
    # Can't try half-integers because Wigner_D_matrices doesn't accept them
    ell_max = min(8, ell_max)
    LMpM = sf.LMpM_range(0, ell_max)
    print("")
    D1 = np.empty((LMpM.shape[0], ), dtype=complex)
    D2 = np.empty((LMpM.shape[0], ), dtype=complex)
    D12 = np.empty((LMpM.shape[0], ), dtype=complex)
    for i, R1 in enumerate(Rs):
        print("\t{0} of {1}: R1 = {2}".format(i + 1, len(Rs), R1))
        for j, R2 in enumerate(Rs[i:]):
            # print("\t\t{0} of {1}: R2 = {2}".format(j+1, len(Rs), R2))
            R12 = R1 * R2
            sf._Wigner_D_matrices(R1.a, R1.b, 0, ell_max, D1)
            sf._Wigner_D_matrices(R2.a, R2.b, 0, ell_max, D2)
            sf._Wigner_D_matrices(R12.a, R12.b, 0, ell_max, D12)
            M12 = np.array([
                np.sum([
                    D1[sf.LMpM_index(ell, mp, mpp, 0)] *
                    D2[sf.LMpM_index(ell, mpp, m, 0)]
                    for mpp in range(-ell, ell + 1)
                ]) for ell in range(ell_max + 1)
                for mp in range(-ell, ell + 1) for m in range(-ell, ell + 1)
            ])
            assert np.allclose(M12,
                               D12,
                               atol=ell_max * precision_Wigner_D_element)
Пример #3
0
def test_Wigner_D_element_symmetries(Rs, ell_max):
    LMpM = sf.LMpM_range(0, ell_max)
    # D_{mp,m}(R) = (-1)^{mp+m} \bar{D}_{-mp,-m}(R)
    MpPM = np.array([
        mp + m for ell in range(ell_max + 1) for mp in range(-ell, ell + 1)
        for m in range(-ell, ell + 1)
    ])
    LmMpmM = np.array([[ell, -mp, -m] for ell in range(ell_max + 1)
                       for mp in range(-ell, ell + 1)
                       for m in range(-ell, ell + 1)])
    print()
    for R in Rs:
        print("\t", R)
        assert np.allclose(sf.Wigner_D_element(R, LMpM), (-1.)**MpPM *
                           np.conjugate(sf.Wigner_D_element(R, LmMpmM)),
                           atol=ell_max**2 * precision_Wigner_D_element,
                           rtol=ell_max**2 * precision_Wigner_D_element)
    # D is a unitary matrix, so its conjugate transpose is its
    # inverse.  D(R) should equal the matrix inverse of D(R^{-1}).
    # So: D_{mp,m}(R) = \bar{D}_{m,mp}(\bar{R})
    LMMp = np.array([[ell, m, mp] for ell in range(ell_max + 1)
                     for mp in range(-ell, ell + 1)
                     for m in range(-ell, ell + 1)])
    for R in Rs:
        print("\t", R)
        assert np.allclose(sf.Wigner_D_element(R, LMpM),
                           np.conjugate(sf.Wigner_D_element(R.inverse(),
                                                            LMMp)),
                           atol=ell_max**4 * precision_Wigner_D_element,
                           rtol=ell_max**4 * precision_Wigner_D_element)
def test_Wigner_D_element_roundoff(Rs, ell_max):
    LMpM = sf.LMpM_range(0, ell_max)
    # Test rotations with |Ra|<1e-15
    expected = [((-1.) ** ell if mp == -m else 0.0) for ell in range(ell_max + 1) for mp in range(-ell, ell + 1) for m in
                range(-ell, ell + 1)]
    assert np.allclose(sf.Wigner_D_element(quaternion.x, LMpM), expected,
                       atol=ell_max * precision_Wigner_D_element, rtol=ell_max * precision_Wigner_D_element)
    expected = [((-1.) ** (ell + m) if mp == -m else 0.0) for ell in range(ell_max + 1) for mp in range(-ell, ell + 1)
                for m in range(-ell, ell + 1)]
    assert np.allclose(sf.Wigner_D_element(quaternion.y, LMpM), expected,
                       atol=ell_max * precision_Wigner_D_element, rtol=ell_max * precision_Wigner_D_element)
    for theta in np.linspace(0, 2 * np.pi):
        expected = [((-1.) ** (ell + m) * (np.cos(theta) + 1j * np.sin(theta)) ** (2 * m) if mp == -m else 0.0)
                    for ell in range(ell_max + 1) for mp in range(-ell, ell + 1) for m in range(-ell, ell + 1)]
        assert np.allclose(sf.Wigner_D_element(np.cos(theta) * quaternion.y + np.sin(theta) * quaternion.x, LMpM),
                           expected,
                           atol=ell_max * precision_Wigner_D_element, rtol=ell_max * precision_Wigner_D_element)
    # Test rotations with |Rb|<1e-15
    expected = [(1.0 if mp == m else 0.0) for ell in range(ell_max + 1) for mp in range(-ell, ell + 1) for m in
                range(-ell, ell + 1)]
    assert np.allclose(sf.Wigner_D_element(quaternion.one, LMpM), expected,
                       atol=ell_max * precision_Wigner_D_element, rtol=ell_max * precision_Wigner_D_element)
    expected = [((-1.) ** m if mp == m else 0.0) for ell in range(ell_max + 1) for mp in range(-ell, ell + 1) for m in
                range(-ell, ell + 1)]
    assert np.allclose(sf.Wigner_D_element(quaternion.z, LMpM), expected,
                       atol=ell_max * precision_Wigner_D_element, rtol=ell_max * precision_Wigner_D_element)
    for theta in np.linspace(0, 2 * np.pi):
        expected = [((np.cos(theta) + 1j * np.sin(theta)) ** (2 * m) if mp == m else 0.0)
                    for ell in range(ell_max + 1) for mp in range(-ell, ell + 1) for m in range(-ell, ell + 1)]
        assert np.allclose(sf.Wigner_D_element(np.cos(theta) * quaternion.one + np.sin(theta) * quaternion.z, LMpM),
                           expected,
                           atol=ell_max * precision_Wigner_D_element, rtol=ell_max * precision_Wigner_D_element)
Пример #5
0
def test_Wigner_D_matrices_negative_argument(Rs, ell_max):
    # For integer ell, D(R)=D(-R)
    LMpM = sf.LMpM_range(0, ell_max)
    a = np.empty((LMpM.shape[0], ), dtype=complex)
    b = np.empty((LMpM.shape[0], ), dtype=complex)
    for R in Rs:
        sf._Wigner_D_matrices(R.a, R.b, 0, ell_max, a)
        sf._Wigner_D_matrices(-R.a, -R.b, 0, ell_max, b)
        assert np.allclose(a, b, rtol=ell_max * precision_Wigner_D_element)
Пример #6
0
def test_LMpM_index(ell_max):
    for ell_min in range(ell_max + 1):
        LMpM = sf.LMpM_range(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):
                    assert np.array_equal(
                        np.array([ell, mp, m]),
                        LMpM[sf.LMpM_index(ell, mp, m, ell_min)])
Пример #7
0
def test_Wigner_D_element_overflow(Rs, ell_max):
    assert sf.ell_max >= 15  # Test can't work if this has been set lower
    ell_max = max(sf.ell_max, ell_max)
    LMpM = sf.LMpM_range(0, ell_max)
    # Test |Ra|=1e-10
    R = np.quaternion(1.e-10, 1, 0, 0).normalized()
    assert np.all(np.isfinite(sf.Wigner_D_element(R, LMpM)))
    # Test |Rb|=1e-10
    R = np.quaternion(1, 1.e-10, 0, 0).normalized()
    assert np.all(np.isfinite(sf.Wigner_D_element(R, LMpM)))
Пример #8
0
def test_Wigner_D_signatures(Rs):
    """There are two ways to call the WignerD function: with an array of Rs, or with an array of (ell,mp,m) values.
    This test ensures that the results are the same in both cases."""
    # from spherical_functions.WignerD import _Wigner_D_elements
    ell_max = 6
    ell_mp_m = sf.LMpM_range(0, ell_max)
    Ds1 = np.zeros((Rs.size, ell_mp_m.shape[0]), dtype=np.complex)
    Ds2 = np.zeros_like(Ds1)
    for i, R in enumerate(Rs):
        Ds1[i, :] = sf.Wigner_D_element(R, ell_mp_m)
    for i, (ell, mp, m) in enumerate(ell_mp_m):
        Ds2[:, i] = sf.Wigner_D_element(Rs, ell, mp, m)
    assert np.allclose(Ds1, Ds2, rtol=3e-15, atol=3e-15)
def test_Wigner_D_matrix(Rs, ell_max):
    for l_min in [0, 1, 2, ell_max // 2, ell_max - 1]:
        print("")
        for l_max in range(l_min + 1, ell_max + 1):
            print("\tWorking on (l_min,l_max)=({0},{1})".format(l_min, l_max))
            LMpM = sf.LMpM_range(l_min, l_max)
            for R in Rs:
                elements = sf.Wigner_D_element(R, LMpM)
                matrix = np.empty(LMpM.shape[0], dtype=complex)
                sf._Wigner_D_matrices(R.a, R.b, l_min, l_max, matrix)
                assert np.allclose(elements, matrix,
                                   atol=1e3 * l_max * ell_max * precision_Wigner_D_element,
                                   rtol=1e3 * l_max * ell_max * precision_Wigner_D_element)
def test_Wigner_D_input_types(Rs, special_angles, ell_max):
    LMpM = sf.LMpM_range(0, ell_max // 2)
    # Compare with more explicit forms given in Euler angles
    print("")
    for alpha in special_angles:
        print("\talpha={0}".format(alpha))  # Need to show some progress to Travis
        for beta in special_angles:
            for gamma in special_angles:
                a = sf.Wigner_D_element(alpha, beta, gamma, LMpM)
                b = sf.Wigner_D_element(quaternion.from_euler_angles(alpha, beta, gamma), LMpM)
                assert np.allclose(a, b,
                                   atol=ell_max ** 6 * precision_Wigner_D_element,
                                   rtol=ell_max ** 6 * precision_Wigner_D_element)
    for R in Rs:
        a = sf.Wigner_D_element(R, LMpM)
        b = sf.Wigner_D_element(R.a, R.b, LMpM)
        assert np.allclose(a, b,
                           atol=ell_max ** 6 * precision_Wigner_D_element,
                           rtol=ell_max ** 6 * precision_Wigner_D_element)
Пример #11
0
def test_Wigner_D_linear_indices(ell_max):
    for l_min in range(ell_max):
        for l_max in range(l_min + 1, ell_max + 1):
            LMpM = sf.LMpM_range(l_min, l_max)

            assert len(LMpM) == sf._total_size_D_matrices(l_min, l_max)

            for ell in range(l_min, l_max + 1):
                assert list(LMpM[sf._linear_matrix_offset(ell, l_min)]) == [ell, -ell, -ell]

            for ell in range(l_min, l_max + 1):
                for mp in range(-ell, ell + 1):
                    i = sf._linear_matrix_diagonal_index(ell, mp)
                    o = sf._linear_matrix_offset(ell, l_min)
                    assert list(LMpM[i + o]) == [ell, mp, mp]
                    for m in range(-ell, ell + 1):
                        i = sf._linear_matrix_index(ell, mp, m)
                        o = sf._linear_matrix_offset(ell, l_min)
                        assert list(LMpM[i + o]) == [ell, mp, m]