Esempio n. 1
0
def test_wigner3j_ignore_invalid():
    N = np.arange(1, 2)
    K = np.arange(-2, 3)[:, np.newaxis]
    with pytest.raises(ValueError):
        # should raise an error
        wigner3j(N * 2, K * 2, 0, 0, 0, 0, ignore_invalid=False)
    # should compute
    wigner3j(N * 2, K * 2, 0, 0, 0, 0, ignore_invalid=True)
Esempio n. 2
0
def test_wigner3j_value():
    # scalar test
    for three_j, expected in THREE_J:
        three_j = (np.array(three_j) * 2).astype(int)
        actual = wigner3j(*three_j)
        assert np.allclose(actual, expected)
    # test vector
    three_j = (np.array([thr for thr, _ in THREE_J]).T * 2).astype(int)
    expected = np.array([value for _, value in THREE_J]).T
    actual = wigner3j(*three_j)
    assert np.allclose(actual, expected)
Esempio n. 3
0
def w3j_vecm(l1, l2, l3, m1, m2, m3):
    l1 = int(2*l1)
    l2 = int(2*l2)
    l3 = int(2*l3)
    m1 = 2*m1
    m2 = 2*m2
    m3 = 2*m3
    wigvals = py3nj.wigner3j(l1, l2, l3, m1, m2, m3)
    return wigvals
Esempio n. 4
0
    def compute_Honl_London_factors(self, freqc):

        ueps = self.map_parity_to_epsilon(freqc[:, 10])
        leps = self.map_parity_to_epsilon(freqc[:, 11])

        uj, lj = freqc[:, 2], freqc[:, 3]
        uomega, lomega = freqc[:, 6], freqc[:, 7]
        ulambda, llambda = freqc[:, 4], freqc[:, 5]

        eps_expr = 1.0 + (ueps * leps * np.power(-1, 1.0 + uj - lj))

        udelta = self.map_quantum_number_to_delta(ulambda)
        udelta *= self.map_quantum_number_to_delta(uomega)

        ldelta = self.map_quantum_number_to_delta(llambda)
        ldelta *= self.map_quantum_number_to_delta(lomega)

        delta_expr = 1.0 + udelta + ldelta - 2.0 * udelta * ldelta
        j_expr = ((2.0 * uj) + 1.0) * ((2.0 * lj + 1.0))

        two_l1 = np.int64(2 * uj)
        two_l2 = 2 * np.ones(freqc.shape[0], dtype=np.int64)
        two_l3 = np.int64(2 * lj)
        two_m1 = np.int64(-2 * uomega)
        two_m2 = np.int64(2 * (ulambda - llambda))
        two_m3 = np.int64(2 * lomega)

        # allows for the ambiguous sign in the 3j symbol when one of the Lambda
        # quantum numbers is zero (Ref: J.K.G. Watson, JMS 252 (2008))

        if (ulambda.any() == 0 and llambda.any() != 0) or \
           (ulambda.any() != 0 and llambda.any() == 0):
            two_m2 = np.int64(2 * (ulambda + llambda))
            two_m3 = np.int64(-2 * lomega)

        # set to zero the qunatum numbers that
        # do not satisfy the following conditions

        if (two_l1 < np.abs(two_m1)).any():
            valid = 1 * ~(two_l1 < np.abs(two_m1))
            two_m1 *= valid

        if (two_l2 < np.abs(two_m2)).any():
            valid = 1 * ~(two_l2 < np.abs(two_m2))
            two_m2 *= valid

        if (two_l3 < np.abs(two_m3)).any():
            valid = 1 * ~(two_l3 < np.abs(two_m3))
            two_m3 *= valid

        wigner_3j = py3nj.wigner3j(two_l1, two_l2, two_l3, two_m1, two_m2,
                                   two_m3)
        wigner_3j_square = wigner_3j**2

        hlf = 0.5 * eps_expr * delta_expr * j_expr * wigner_3j_square

        return hlf
Esempio n. 5
0
def thj(j1, j2, j3, m1, m2, m3):
    """
    3-j symbol
    ( j1 j2 j3 )
    ( m1 m2 m3 )
    """
    #return wigner3j(j1,j2,j3,m1,m2,m3)
    return py3nj.wigner3j(int(2 * j1), int(2 * j2), int(2 * j3), int(2 * m1),
                          int(2 * m2), int(2 * m3))
Esempio n. 6
0
def w3j(l1, l2, l3, m1, m2, m3):
    l1 = int(2*l1)
    l2 = int(2*l2)
    l3 = int(2*l3)
    m1 = int(2*m1)
    m2 = int(2*m2)
    m3 = int(2*m3)
    try:
        wigval = py3nj.wigner3j(l1, l2, l3, m1, m2, m3)
    except ValueError:
        return 0.0
    return wigval
Esempio n. 7
0
def test_wigner3j_value(ignore_invalid):
    # scalar test
    for three_j, expected in THREE_J:
        three_j = (np.array(three_j) * 2).astype(int)
        actual = wigner3j(*three_j, ignore_invalid=ignore_invalid)
        assert np.allclose(actual, expected)
        # broadcast the first argument
        actual = wigner3j(np.array([three_j[0]])[:, np.newaxis],
                          *three_j[1:],
                          ignore_invalid=ignore_invalid)
        assert np.allclose(actual, expected)
        # further broadcasting
        actual = wigner3j(
            np.array([three_j[0]])[:, np.newaxis, np.newaxis], *three_j[1:])
        assert np.allclose(actual, expected)

    # test vector
    three_j = (np.array([thr for thr, _ in THREE_J]).T * 2).astype(int)
    expected = np.array([value for _, value in THREE_J]).T
    actual = wigner3j(*three_j)
    assert np.allclose(actual, expected)
Esempio n. 8
0
def get_RgNl0_coeff_for_zdipole_field(k, R, dist, l):
    ans = 0.0j
    kd = k * (
        R + dist
    )  #dist is distance between dipole and sphere surface, the translation distance d is between the two origins so dipole and sphere center
    #   norm = np.sqrt(rho_N(l,k*R)/k**3) #normalization
    for nu in range(l - 1, l + 2):
        tmp = (1j)**(1 - nu - l) * 0.5 * (2 + l * (l + 1) - nu *
                                          (nu + 1)) * (2 * nu + 1) * np.sqrt(
                                              3 * (2 * l + 1) / 2 / l /
                                              (l + 1))
        tmp *= py3nj.wigner3j(2 * 1, 2 * l, 2 * nu, 0, 0, 0)**2 * (
            sp.spherical_jn(nu, kd) + 1j * sp.spherical_yn(nu, kd))
        ans += tmp
#   print(ans)
    ans *= 1j * k * np.sqrt((1.0 / 6 / np.pi))  #normalization NOT included
    return ans
Esempio n. 9
0
def mp_get_normalized_RgNl0_coeff_for_zdipole_field(k, R, dist, l):
    ans = mpmath.mpc(0.0j)
    kd = k * (
        R + dist
    )  #dist is distance between dipole and sphere surface, the translation distance d is between the two origins so dipole and sphere center
    #   norm = np.sqrt(rho_N(l,k*R)/k**3) #normalization
    for nu in range(l - 1, l + 2):
        tmp = (1j)**(1 - nu - l) * 0.5 * (2 + l * (l + 1) - nu * (nu + 1)) * (
            2 * nu + 1) * mpmath.sqrt(3 * (2 * l + 1) / 2 / l / (l + 1))
        tmp *= py3nj.wigner3j(2 * 1, 2 * l, 2 * nu, 0, 0,
                              0)**2 * mp_spherical_hn(nu, kd)
        ans += tmp

#   print(ans)
    ans *= 1j * k * mpmath.sqrt((1.0 / 6 / mpmath.pi) * mp_rho_N(l, k * R) /
                                k**3)  #normalization included in sqrt
    return ans
Esempio n. 10
0
def wigner3j(jj1, jj2, jj3, mm1, mm2, mm3):
    """
    Calculate the Wigner 3-j symbol,
    
    .. math::
    
       \\left(\\begin{array}{ccc} j_1 & j_2 & j_3 \\\\ m_1 & m_2 & m_3 \\end{array} \\right)

    Parameters
    ----------
    jj1 : integer
        Twice the value of :math:`j_1`.
    jj2 : integer
        Twice the value of :math:`j_2`.
    jj3 : integer
        Twice the value of :math:`j_3`.
    mm1 : integer
        Twice the value of :math:`m_1`.
    mm2 : integer
        Twice the value of :math:`m_2`.
    mm3 : integer
        Twice the value of :math:`m_3`.

    Returns
    -------
    float
        The result.
        
    Notes
    -----
    This currently wraps the `py3nj <https://github.com/fujiisoup/py3nj>`_ 
    implementation. The back-end may change in the future. 
    
    
    Examples
    --------
    >>> n2.angmom.wigner3j(2 * 20, 2 * 21, 2 * 22, 2 * 5, 2 * -15, 2 * 10)
    0.032597617477982975

    """

    result = py3nj.wigner3j(jj1, jj2, jj3, mm1, mm2, mm3)

    return result
Esempio n. 11
0
def test_wigner3j(half_integer):
    n = 10000
    n2 = 10
    l2 = rng.randint(0, 40, size=n) * 2 + half_integer
    l3 = rng.randint(0, 40, size=n) * 2 + half_integer
    m2 = np.zeros(n, dtype=int)
    m3 = np.zeros(n, dtype=int)
    for i in range(n):
        if l2[i] > 0:
            m2[i] = rng.randint(-l2[i], l2[i]+1)
        if l3[i] > 0:
            m3[i] = rng.randint(-l3[i], l3[i]+1)

    l, expected_all = wigner.drc3jj(l2, l3, m2, m3)
    for _ in range(n2):
        lindex = rng.randint(0, 40, n) * 2 - 1 + half_integer
        two_l1 = l[lindex]
        two_m1 = -(m2 + m3)
        actual = wigner3j(two_l1, l2, l3, two_m1, m2, m3)
        expected = expected_all[np.arange(len(lindex)), lindex]
        assert np.allclose(actual, expected)
def find_param(coords, l, l2, L, d):
    myrange = range(-l, l + 1)
    myrange2 = range(-l2, l2 + 1)
    param = []
    neighbours = []
    #find parameter for each particle a
    for i, a in enumerate(coords):
        sph_harm = []
        sph_harm2 = []
        n = []
        #loop over all particles b for each particle a
        for j, b in enumerate(coords):
            #if a==b, don't use particle b
            if i != j:

                r = find_vector(a, b, L)

                #check if particle b is nearest neighbour to a
                if np.dot(r, r) <= d**2:
                    #append nearest neighbours to new list
                    n.append(j)
                    #construct spherical harmonics
                    theta = np.arctan2(r[1], r[0])
                    phi = np.arccos(r[2] / np.linalg.norm(r))
                    new_vec = np.array(
                        [special.sph_harm(m, l, theta, phi) for m in myrange])
                    new_vec2 = np.array([
                        special.sph_harm(m, l2, theta, phi) for m in myrange2
                    ])
                    #append spherical harmonics to new list and carry on loop
                    sph_harm.append(new_vec)
                    sph_harm2.append(new_vec2)
        #find parameter for particle a and append to parameters list
        #append all neighbours to new list
        neighbours.append(n)

        total = sum(sph_harm)
        N = len(sph_harm)
        p1 = total / N

        #make local invariants for l=6
        q6 = A1 * np.linalg.norm(p1)
        combo6 = [seq for seq in combinations(myrange, 3) if sum(seq) == 0]
        combo6_list = [list(elem) for elem in combo6]
        W6 = []
        for u in combo6_list:
            wig = py3nj.wigner3j(2 * l, 2 * l, 2 * l, 2 * u[0], 2 * u[1],
                                 2 * u[2])
            w_l = np.real(wig * p1[u[0] + 6] * p1[u[1] + 6] * p1[u[2] + 6])
            W6.append(w_l)
        w6 = sum(W6) / (np.linalg.norm(p1)**3)

        #make local invariants for l=4
        total2 = sum(sph_harm2)
        N2 = len(sph_harm2)
        p2 = total2 / N2

        q4 = A2 * np.linalg.norm(p2)
        combo4 = [seq for seq in combinations(myrange2, 3) if sum(seq) == 0]
        combo4_list = [list(elem) for elem in combo4]
        W4 = []
        for v in combo4_list:
            wig2 = py3nj.wigner3j(2 * l2, 2 * l2, 2 * l2, 2 * v[0], 2 * v[1],
                                  2 * v[2])
            w_l2 = np.real(wig2 * p2[v[0] + 4] * p2[v[1] + 4] * p2[v[2] + 4])
            W4.append(w_l2)
        w4 = sum(W4) / (np.linalg.norm(p2)**3)

        P = [q6, q4, w6, w4]
        param.append(P)

    #write parameters to seperate file to be used for machine learning
    with open('liquid1.8_q6q4w6w4.txt', 'ab') as file:
        pickle.dump(param, file)
    return param, neighbours
def obtain_parameters(coordinates):
  
    mrange = range(-l,l+1)
    nrange = range(-l2,l2+1)
    parameters = []
    
# gives list of all spherical harmonics for each particle 

# DQ using enumerate is more "pythonic" than that you were doing....
    for a, i in enumerate(coordinates):
        s_harm1 = []
        s_harm2 = []
        
        conc = []
# moved b = 0 outside bracket,put back if it messes things        
    
        for b, j in enumerate(coordinates):
            
            if a != b:
                
                r = reduce_vector(i,j,L)

                if np.dot(r,r) <= neighbour_dist_sqrd:
                    
                    the = np.arctan2(r[1],r[0])
                    phi = np.arccos(r[2]/np.linalg.norm(r))
                    
                    m_vec = np.array([sc.special.sph_harm(m,l,the,phi) for m in mrange ])
            
                    n_vec = np.array([sc.special.sph_harm(m,l2,the,phi) for m in nrange ])
                    
                    # gives q4 spherical harmonic aswell
                    
                    s_harm1.append(m_vec)
                    s_harm2.append(n_vec)

#returns the spherical harmonics particle which are neighbours to the particle the spherical harmonics particle which are neighbours to the particle    
                               
        param1 = (sum(s_harm1))/ (len(s_harm1))
        
        param2 = (sum(s_harm2))/ (len(s_harm2))
            
#param1 and param2 are both 1d arrays (lengths 13 and 9), which contain the q6 and q4 set of vectors respectively, for one particle
#there are 500 q6m values in param1 and param2

        local_inv_q6 = A1sqrt*np.linalg.norm(param1)
        local_inv_q4 = A2sqrt*np.linalg.norm(param2)
        
       #calculate w_descriptor      

        result1 = [seq for i in range(len(mrange), 0, -1) for seq in itertools.combinations(range(-l,l+1), 3) if sum(seq) == 0]
        result2 = [seq for i in range(len(nrange), 0, -1) for seq in itertools.combinations(range(-l2,l2+1), 3) if sum(seq) == 0]

        #produces w(i) matrix as list of tuples, however there are repeating tuples in the list.

        out1 = set([i for i in result1])
        out2 = set([i for i in result2])

        #remove duplicates from list of tuples
        
        

        w_l = list(out1)
        w_l2 = list(out2)

        #coverts set into list of unique tuples
       
        list_of_w_l = []
        list_of_w_l2 = []

 

        for i, j in enumerate(w_l):
    
            m1 = j[0]
            m2 = j[1]
            m3 = j[2]
    
            qlm1 = param1[m1+6]
            qlm2 = param1[m2+6]
            qlm3 = param1[m3+6]
    
    #corrects for index position with m values as it starts from m=-l
    
            x = py.wigner3j(l*2, l*2, l*2, j[0]*2, j[1]*2, j[2]*2)
    
            x1 = x*qlm1*qlm2*qlm3
    
            list_of_w_l.append(x1)
    
# appends each combination of each wl(i)*qlm1*qlm2*qlm3 matrix to a list


        for i, j in enumerate(w_l2):
    
            m1 = j[0]
            m2 = j[1]
            m3 = j[2]
    
            ql2m1 = param2[m1+4]
            ql2m2 = param2[m2+4]
            ql2m3 = param2[m3+4]
    
    #corrects for index position with m values as it starts from m=-l
    
            y = py.wigner3j(l2*2, l2*2, l2*2, j[0]*2, j[1]*2, j[2]*2)
            y1 = y*ql2m1*ql2m2*ql2m3
    
            list_of_w_l2.append(y1)
    
  
# appends each combination of each wl2(i)*qlm1*qlm2*qlm3 matrix to a list

        w_l_loc = sum(list_of_w_l)
        w_l2_loc = sum(list_of_w_l2)

# w_l(i) parameter
        
        w_l_hat_re_im = (w_l_loc)/(np.linalg.norm(param1))**3
        w_l2_hat_re_im = (w_l2_loc)/(np.linalg.norm(param2))**3
        
# get both real and imaginary parts of the w hat loc invaraint descriptor.        
        
        w_l_hat = np.real(w_l_hat_re_im)
        w_l2_hat = np.real(w_l2_hat_re_im)


        li = np.append(local_inv_q6,local_inv_q4)
        
        li_list = li.tolist()
        
        q6q4w6w4 = li_list + [w_l_hat, w_l2_hat]
        
        #appends all 4 descriptors to 1 list for each particle
        
        parameters.append(q6q4w6w4)
        
    
#appends all descriptors to 1 list with 4 descriptors for each of the 500 particles


    with open('q6q4w6w4_loc_inv_misaligned_quench.txt', 'ab') as filehandle:

        # store the data as binary data stream
#ab instead of wb, so it doesnt overwrite parameters
           
        pickle.dump(parameters, filehandle)
  
    return parameters
Esempio n. 14
0
#if os.path.exists(ovr_fileName):
#  sys.exit(0)
for l1 in np.arange(maxJ + 1):
    for m1_ in np.arange(-1 * l1, l1 + 1):
        m1 = -1 * m1_
        m2 = -1 * (m1 + M)
        if np.amax(np.abs(np.array([m2, l1 - L]))) > np.amin([maxJ, l1 + L]):
            continue
        for l2 in np.arange(np.amax(np.abs(np.array([m2, l1 - L]))),
                            np.amin([maxJ, l1 + L]) + 1):
            if np.abs(m2) > l2:
                continue

            integral = ((-1)**m1)*np.sqrt((2*l1+1)*(2*L+1)*(2*l2+1)/(4*np.pi))\
                *py3nj.wigner3j(2*l1,2*L,2*l2,0,0,0)\
                *py3nj.wigner3j(2*l1,2*L,2*l2,2*m1,2*M,2*m2)

            if integral:
                overlap.append(integral)
                indices.append(np.array([[l1, m1, l2, m2]]))

ovr = np.real(np.array(overlap)).astype(np.double)
ind = np.concatenate(indices, axis=0).astype(np.int32)

#for o,i in zip(ovr,ind):
#  print(o,i)

ovr.tofile(ovr_fileName)
ind_fileName += "_bins[" + str(ind.shape[0]) + "," + str(
    ind.shape[1]) + "].dat"
Esempio n. 15
0
def gaunt_for(two_l1, two_l2, two_l3, two_m1, two_m2, two_m3):
	return ((two_l1+1)*(two_l2+1)*(two_l3+1)/(4*np.pi))**0.5*wigner3j(two_l1,two_l2,two_l3,two_m1,two_m2,two_m3)*wigner3j(two_l1,two_l2,two_l3,0,0,0)