Exemplo n.º 1
0
def F(I,J_u,J_l):#returns all the possible transistions Fu->Fl J_u, J_l
	J_us = n.arange(-J_u,J_u+1,1)
	J_ls = n.arange(-J_l,J_l+1,1)
	F_us = I + J_us
	F_ls = I + J_ls
	trans = []
	ntrans = 0
	for u in F_us:
		for l in F_ls:
			ch = n.abs(u-l)
			if ch == 1:
				trans.append(u)
				trans.append(l)
				trans.append(u-I)
				trans.append(l-I)
				amp = (2.0*l+1.0)*(2.0*u+1.0)*(wigner_6j(u,l,1,J_l,J_u,I))**2
				trans.append(amp)
				ntrans = ntrans + 1
			if ch == 0:
				if u != 0:
					trans.append(u)
					trans.append(l)
					trans.append(n.abs(u-I))
					trans.append(n.abs(l-I))
					amp = (2.0*l+1.0)*(2.0*u+1.0)*(wigner_6j(u,l,1,J_l,J_u,I))**2
					trans.append(amp)
					ntrans = ntrans + 1
	Ftemp = n.array(trans)
	F = Ftemp.reshape((ntrans,5))
	F[:,4] = F[:,4]/n.sum(F[:,4])
	return F
Exemplo n.º 2
0
def calculate_microwave_ED_matrix_element(ground_state, excited_state,reduced = True, pol_vec = np.array((0,0,1))):
    #Find quantum numbers for ground state
    J = float(ground_state.J)
    F1 = float(ground_state.F1)
    F = float(ground_state.F)
    mF = float(ground_state.mF)
    I1 = float(ground_state.I1)
    I2 = float(ground_state.I2)
    
    #Find quantum numbers of excited state
    Jprime = float(excited_state.J)
    F1prime = float(excited_state.F1)
    Fprime = float(excited_state.F)
    mFprime = float(excited_state.mF)
    
    #Calculate reduced matrix element
    M_r = (np.sqrt(float((2*F1+1) * (2*F1prime+1) * (2*F+1)* (2*Fprime+1))) * float(wigner_6j(Jprime, F1prime,1/2,F1,J,1))
               * float(wigner_6j(F1prime, Fprime,1/2,F,F1,1)) * np.sqrt(float((2*J+1) * (2*Jprime+1))) 
               *(-1)**(F1prime+J+Fprime+F1+1)
               * float(wigner_3j(J,1,Jprime,0,0,0) * (-1)**J))
    
    if reduced:
        return float(M_r)
    else:
        p_vec = {}
        p_vec[-1] = -1/np.sqrt(2) * (pol_vec[0] + 1j *pol_vec[1])
        p_vec[0] = pol_vec[2]
        p_vec[1] = +1/np.sqrt(2) * (pol_vec[0] - 1j *pol_vec[1])
        
        prefactor = 0
        for p in range(-1,2):
            prefactor +=  (-1)**(p+F-mF) * p_vec[p] *  float(wigner_3j(F,1,Fprime,-mF,-p,mFprime))
        
        
        return prefactor*float(M_r)
Exemplo n.º 3
0
def test_wigner():
    def tn(a, b):
        return abs((a - b).n(64) < S('1e-64'))
    assert tn(wigner_9j(1,1,1, 1,1,1, 1,1,0 ,prec=64), S(1)/18)
    assert wigner_9j(3,3,2, 3,3,2, 3,3,2) == 3221*sqrt(70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105))
    assert wigner_6j(5,5,5,5,5,5) == Rational(1,52)
    assert tn(wigner_6j(8,8,8,8,8,8, prec=64), -S(12219)/965770)
def SetMatrix(I,J,AF,BF,B,gj): #Set values of interaction Hamiltonian matrix
    NMAX = int((2*J+1)*(2*I+1)) #size of matrix
    h_bar = scc.hbar #Plank constant/2pi
    mb = scc.physical_constants['Bohr magneton'][0] #Bohr magneton
    Hint=np.empty([NMAX,NMAX])
    AF = AF * h_bar * 2 * np.pi # magnetic dipole constant
    BF = BF * h_bar * 2 * np.pi # electric quadrupole constant
    sj = wigner_6j(1, J, J, J, 1, 2) * wigner_6j(1, I, I, I, 1, 2)
    m = 0
    n = 0
    for mj1 in np.arange(-J,J+1):
        if n > NMAX or m > NMAX: break #stop if n or m exceed NMAX
        for mi1 in np.arange(-I,I+1):
            if n > NMAX or m > NMAX: break
            n = 0
            for mj2 in np.arange(-J,J+1):
                if n > NMAX or m > NMAX: break
                for mi2 in np.arange(-I,I+1):
                    if n > NMAX or m > NMAX: break
                    Hint[m][n] = Delta(mi1, mi2) * Delta(mj1, mj2) * B * mb * gj * mj1 # first term of Hint

                    if I>0 and J>0 : #contribution if there is a magnetic dipole moment
                       Hint[m][n] = Hint[m][n] + AF * Minus(mj2 + mi1 + J + I)\
                       *np.sqrt(J*(J+1)*(2*J+1)*I*(I+1)*(2*I+1))\
                       *wigner_3j(J, 1, J, mj2, mj1 - mj2, -mj1)\
                       *wigner_3j(I, 1, I, mi2, mj2 - mj1, -mi1)

                    if I>0.5 and J>0.5: #contribution if there is a electric quadrupole moment
                        Hint[m][n] = Hint[m][n] + BF * Minus(mj2 + mi1 - J - I) * 15 / 2\
                        *((2 * J + 1) * (J + 1) * (2 * I + 1) * (I + 1)) / ((2 * J - 1) * (2 * I - 1))\
                        *wigner_3j(J, 2, J, mj2, mj1 - mj2, -mj1)\
                        *wigner_3j(I, 2, I, mi2, mj2 - mj1, -mi1) * sj
                    n += 1
            m += 1
    return(Hint)
Exemplo n.º 5
0
def mu(N_u,J_u,F_u,F_uz,N_l,J_l,F_l,F_lz,I,q):#compute the dipole moment. from eq. 4.33 pg 55 in Laser cooling and Trapping (Metcalf)
	rad_el = Rad(N_u,J_u,N_l,J_l)*a_0 #q is the photon polarization q = +-1 or 0
	exp = c_e*(-1.0)**(1+(J_u-0.5)+0.5+J_l+J_u+I-F_uz)
	sqrt = n.sqrt((2.0*J_u+1.0)*(2.0*J_l+1.0)*(2.0*F_u+1.0)*(2.0*F_l+1.0))
	wig6 = wigner_6j((J_u-0.5),J_u,0.5,J_l,(J_l-0.5),1)*wigner_6j(J_u,F_u,I,F_l,J_l,1)
	wig3 = wigner_3j(F_l,1,F_u,F_lz,q,-F_uz)
	mu = rad_el*exp*sqrt*wig6*wig3
	return mu
Exemplo n.º 6
0
def A_calc(J_u,F_u,F_uz,J_l,F_l,F_lz,I,q):#compute the dipole moment. from eq. 4.33 pg 55 in Laser cooling and Trapping (Metcalf)
	#q is the photon polarization q = +-1 or 0
	exp = c_e*(-1.0)**(1+(J_u-0.5)+0.5+J_l+J_u+I-F_uz)
	sqrt = n.sqrt((2.0*J_u+1.0)*(2.0*J_l+1.0)*(2.0*F_u+1.0)*(2.0*F_l+1.0))
	wig6 = wigner_6j((J_u-0.5),J_u,0.5,J_l,(J_l-0.5),1)*wigner_6j(J_u,F_u,I,F_l,J_l,1)
	wig3 = float(wigner_3j(F_l,1,F_u,F_lz,q,-F_uz))
	A_calc = exp*sqrt*wig6*wig3
	return [A_calc,exp,sqrt,wig6,wig3]
Exemplo n.º 7
0
def test_wigner():
    def tn(a, b):
        return (a - b).n(64) < S('1e-64')
    assert tn(wigner_9j(1, 1, 1, 1, 1, 1, 1, 1, 0, prec=64), S(1)/18)
    assert wigner_9j(3, 3, 2, 3, 3, 2, 3, 3, 2) == 3221*sqrt(
        70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105))
    assert wigner_6j(5, 5, 5, 5, 5, 5) == Rational(1, 52)
    assert tn(wigner_6j(8, 8, 8, 8, 8, 8, prec=64), -S(12219)/965770)
Exemplo n.º 8
0
 def M1_reduced_F(A, B, gI=1.521032e-3):
     """F-reduced matrix element <F|| mu ||F'>"""
     # WOAH NOTE: what is this?
     # Proton magnetic moment, gI = 0.001521032 Bohr magnetons
     return np.sqrt((2 * A.F + 1) * (2 * B.F + 1)) * (
         (-1)**(A.J + A.I + B.F + 1) * delta(A.I, B.I) *
         wigner_6j(A.F, 1, B.F, B.J, A.I, A.J) * M1_reduced_J(A, B) +
         (-1)**(B.J + B.I + A.F + 1) * delta(A.J, B.J) * wigner_6j(
             A.F, 1, B.F, B.I, A.J, A.I) * gI * np.sqrt(A.I * (A.I + 1) *
                                                        (2 * A.I + 1)))
Exemplo n.º 9
0
 def M1_reduced_J(A, B, gL=-0.9995, gS=-2.0023193):
     """J-reduced matrix element <J|| mu ||J'>"""
     if (A.L == B.L) and (A.S == B.S):
         return np.sqrt((2 * A.J + 1) * (2 * B.J + 1)) * (
             (-1)**(A.L + A.S + B.J + 1) * wigner_6j(
                 A.J, 1, B.J, B.L, A.S, A.L) * gL * np.sqrt(A.L *
                                                            (A.L + 1) *
                                                            (2 * A.L + 1)) +
             (-1)**(B.L + B.S + A.J + 1) * wigner_6j(
                 A.J, 1, B.J, B.S, A.L, A.S) * gS * np.sqrt(A.S *
                                                            (A.S + 1) *
                                                            (2 * A.S + 1)))
     else:
         return 0
Exemplo n.º 10
0
def hf_zeeman(states, gJ, gI, Bz=None, units='Joules'):
    """ Return Zeeman Hamiltonian in hyperfine basis |L J I F mF>. Assumes the 
        field is along the z axis, i.e. q = 0.

        'states': list-like, pair of quantum states given by [I,J,F,mF,FF,mFF]
        If Bz is none initially, the sympy free_symbol is the magnetic dipole energy,
        uB*B, not just B. 
        
        'units': 'Joules' (default), 'eV', 'UB' (units of the magnetic dipole 
        energy).
        
        From Mark's notes for the general hf Zeeman matrix elements. Units
        are determined by UB. Could implement decorator function to change
        units.
    """

    ## TODO: build in better unit functionality or remove option to choose units

    I, J, F, mF, FF, mFF = states
    q = 0  # assume B = Bz for now

    elem = 0
    if mF == mFF:  # q=0 => selection rule mF = mF'
        elem += N(clebsch_gordan(F,1,FF,mF,q,mFF) \
                *sqrt(2*F+1)*(-1)**(1+J+I) \
                *(gJ*(-1)**F*sqrt(J*(J+1)*(2*J+1)) \
                *wigner_6j(J,I,F,FF,1,J) \
                +gI*(-1)**FF*sqrt(I*(I+1)*(2*I+1)) \
                *wigner_6j(I,J,F,FF,1,I)))
        # N() is used to ensure diagnolization doesn't get tripped up

    if Bz is not None:
        elem *= uB * Bz  # hmm check the sign
        if units == 'Joules':
            return elem
        elif units == 'eV':
            return JToeV(elem)
        elif units == 'GHz':
            return eVToGHz(JToeV(elem))
        else:
            print(f"invalid unit [{units}] for non-zero Bz. Result in 'J'.")
            return elem
    else:
        if units == 'UB':
            return elem
        else:
            UB = symbols('U_B')  # symbolic B field P.E. for now
            elem *= UB
            return elem
Exemplo n.º 11
0
 def calc_hyperfine_transition_dipole(self, Fg, Fe, mFg, mFe, q):
     dFF = (self.dJJ * (-1)**(Fe + self.Jg + 1 + self.Inuc) * np.sqrt(
         (2 * Fe + 1) * (2 * self.Jg + 1)) *
            wigner_6j(self.Jg, self.Je, 1, Fe, Fg, self.Inuc))  #.evalf())
     d_hf = dFF * (-1)**(Fe - 1 + mFg) * np.sqrt(2 * Fg + 1) * wigner_3j(
         Fe, 1, Fg, mFe, q, -mFg)  #.evalf()
     return d_hf
Exemplo n.º 12
0
def K(j, k_f, k_is, w_l, params):
    '''
    Coefficients in irreducible representation of polarizability as shown in
    equation 5 of PRA reference.
    
    Args:
        j: 0 for scalar, 1 for vector, 2 for tensor coefficient
        k_f: ground state
        k_is: list of all excited states
        w_l: wavelength
        params: spectroscopic Args of all excited states freq., z costant, decay rate
    '''
    w_0s, zs, rates = params[:, 0] * 1e15, params[:, 1], params[:, 2] * 1e6
    summation = 0
    for i, k_i in enumerate(k_is):
        constant = (3 * pi * epsilon_0 * c**3 /
                    (w_0s[i]**3)) * zs[i] * rates[i]
        d = abs(
            float(
                (2 * k_i.F + 1) * B_hfs(k_f, k_i) * B_fs(k_f, k_i) * constant))
        k_j = ((-1)**(k_i.F+k_f.F-j))*np.sqrt((2*j+1)/(2*k_f.F+1))*\
               (wigner_6j(k_f.F, k_f.F, j, 1, 1, k_i.F))*d
        summation += float(k_j) * (1 / (w_0s[i] + w_l) + ((-1)**j) /
                                   (w_0s[i] - w_l))
    return float(summation)
Exemplo n.º 13
0
def safe_wigner_6j(*args):
    """ Wigner 6j symbol, same arguments as in Avoid the ValueError whenever the
     arguments don't fulfill the triangle relation. """
    try:
        return float(wigner_6j(*args, prec=None))
    except ValueError or AttributeError:
        return 0
Exemplo n.º 14
0
def dipole_rme_fs(
        d_l: complex,
        li: moment,
        j: moment,
        lp: moment,
        jp: moment,
        s: moment
) -> complex:
    """
    Computes the reduced dipole matrix element between two levels in the fine structure basis given
        the reduced matrix element between those levels in the orbital basis.
    Args:
        d_l : reduced matrix element between orbital levels li, and lp (Cm). <ap, lp || er ||a, li>
        li : orbital angular momentum quantum number for the initial state. Should be integer or
            half-integer
        j : fine structure angular momentum quantum number for the initial state. Should be
            integer or half-integer
        lp : orbital angular momentum quantum number for the primed state. Should be integer or
            half-integer
        jp : fine structure angular momentum quantum number for the primed state. Should be
            integer or half-integer
        s : electron spin momentum quantum number. Should be integer or half-integer

    Returns:
        d_fs : reduced matrix elements between the fine structure level |a, li, j> and
        |ap, lp, jp> (Cm). Equivalent to <ap, lp, jp|| er ||a, li, j>.
    """
    return N(
        (-1) ** (1+j+lp+s) * np.sqrt((2*j+1)*(2*jp+1)) * wigner_6j(li, s, j, jp, 1, lp) * d_l
    )
Exemplo n.º 15
0
def stark_interaction_Wigner_6j(state_1, state_2, **kwargs):
    """ Stark interaction between two states.

        <n' l' S' J' MJ'| H_S |n l S J MJ>.
    """
    field_angle = kwargs.get('field angle', 0.0)
    if not np.mod(field_angle, 180.0) == 90.0:  # parallel fields
        q_arr = [0]
        tau_arr = [1.]
    elif not np.mod(field_angle, 180.0) == 0.0:  # perpendicular fields
        q_arr = [1, -1]
        tau_arr = [(1. / 2)**0.5, -(1. / 2)**0.5]
    else:
        raise Exception('Arbitrary angles not yet supported!')

    delta_L = state_1.L - state_2.L
    delta_S = state_1.S - state_2.S
    delta_MJ = state_1.M - state_2.M
    if abs(delta_L) == 1 and delta_S == 0:
        S = state_1.S
        sum_q = []
        for q, tau in zip(q_arr, tau_arr):
            sum_q.append( (-1.)**(int(state_1.J - state_1.M)) * \
                        wigner_3j(state_1.J, 1, state_2.J, -state_1.M, -q, state_2.M) * \
                        (-1.)**(int(state_1.L + S + state_2.J + 1.)) * \
                        np.sqrt((2.*state_1.J+1.) * (2.*state_2.J+1.)) * \
                        wigner_6j(state_1.J, 1., state_2.J, state_2.L, S, state_1.L) * \
                        (-1.)**state_1.L * np.sqrt((2.*state_1.L+1.) * (2.*state_2.L+1.)) * \
                        wigner_3j(state_1.L, 1, state_2.L, 0, 0, 0) * tau)

        return np.sum(sum_q) * radial_overlap(state_1.n_eff, state_1.L,
                                              state_2.n_eff, state_2.L)
    return 0.0
Exemplo n.º 16
0
def quadrupole_rme_hf(
        q_fs: complex,
        j: moment,
        f: moment,
        jp: moment,
        fp: moment,
        i: moment,
) -> complex:
    """
    Computes the reduced quadrupole matrix element between two hyperfine levels, given the reduced
    dipole matrix element between those levels in the fine structure basis
    Args:
        q_fs : reduced quadrupole matrix element between the fine structure levels j and jp (Cm**2)
            <ap, jp|| e C_2/sqrt(15) ||a, j>
        j : fine structure angular momentum quantum number for the initial state. Should be
            integer or half-integer
        f : hyperfine structure angular momentum quantum number for the initial state. Should be
            integer or half-integer
        jp : fine structure angular momentum quantum number for the primed state. Should be
            integer or half-integer
        fp : hyperfine structure angular momentum quantum number for the primed state. Should be
            integer or half-integer
        i: nuclear spin quantum number. Should be integer or half-integer

    Returns:
        d_hf : reduced dipole matrix element between the hyperfine levels |a, j,f> and
            |ap, jp,fp> (Cm).
            Equivalent to <ap, jp, fp|| er ||a, j, f>
    """
    return N(
        (-1)**(f+jp+i+2)*np.sqrt((2 * f + 1)*(2 * fp + 1))*wigner_6j(j, i, f, fp, 2, jp)*q_fs
    )
Exemplo n.º 17
0
def _ang_integral(S, L1, J1, MJ1, L2, J2, MJ2):
    """Calculate the angular integral (cached).

    Parameters
    ----------
    S : int
        spin
    L1 : int
        orbital angular momentum, state 1
    J1 : int
        total angular momentum, state 1
    MJ1 : int
        projection of the total angular momentum, state 1
    L2 : int
        orbital angular momentum, state 2
    J2 : int
        total angular momentum, state 2
    MJ2 : int
        projection of the total angular momentum, state 2

    Returns
    -------
    float

    """
    return float(
        (-1.0)**(S + 1 + MJ2) *
        np.sqrt(max(L1, L2) * (2 * J2 + 1) * (2 * J1 + 1)) *
        wigner_3j(J2, 1, J1, -MJ2, 0, MJ1) * wigner_6j(S, L2, J2, 1, J1, L1))
Exemplo n.º 18
0
def dipole_hf_to_fs(
        electric_field: complex,
        q_ar: SphericalVector,
        d_rme: complex,
        j: moment,
        f: moment,
        mf: moment,
        jp: moment,
        mp: moment,
        i: moment
) -> complex:
    """
    Computes rabi frequency for a dipole transition between two zeeman states, the lower
    (un-primed) state being defined in the hyperfine basis and the upper (primed) state being
    defined in the fine structure basis.

    This computation is particularly useful in the case of exciting to Rydberg states, where the
    strength hyperfine interactions become much smaller than the linewidths of the fine structure
    levels.

    The states in this function are described as |a, f, mf> -> |ap, jp, mp> where p represents
    primed states, and a/ap abstract away all unaccounted-for quantum numbers.
    Args:
        electric_field : electric field strength of the oscillating field coupling the two states
        q_ar : SphericalVector object describing the field polarization
        d_rme : reduced dipole matrix element between the two FINE-STRUCTURE levels
        j : fine structure angular momentum quantum number for the initial state. Should be
            integer or half-integer
        f : hyperfine structure angular momentum quantum number for the initial state. Should be
            integer or half-integer
        mf : zeeman state quantum number (in the hyperfine basis) for the initial state. Should be
            integer or half-integer
        jp : fine structure angular momentum quantum number for the final state. Should be
            integer of half-integer
        mp : zeeman state quantum number (in the fine structure basis) for the final state.
            Should be integer or half-integer
        i : nuclear spin quantum number. Should be integer or half-integer

    Returns:
        rabi frequency coupling |a,I,j,f,mf> to |ap,j,mj;I>
    """

    s = 0
    for q in [-1, 0, 1]:
        #print(q, q_ar[q])
        for fp in np.arange(abs(i-jp), i+jp+1):
            mfp = q+mf
            if abs(mfp) > fp:
                # print(f"q = {q} mf = {mf}, fp = {fp} mfp = {mfp}")
                s += 0
                continue
            c1 = clebsch_gordan(jp, i, fp, mp, mfp-mp, mfp)
            c2 = clebsch_gordan(1, f, fp, q, mf, mfp)
            six = wigner_6j(j, i, f, fp, 1, jp)
            cont = c1 * c2 * six * q_ar[q] * (-1) ** (1 + i + jp + fp)
            # if(q_ar[q] != 0):
                # print(f"fr = {fp} mfr = {mfp} c1 = {c1} c2 = {c2}")
            s += cont
    return complex(N(electric_field * s * np.sqrt(2 * f + 1) * d_rme / hb))
Exemplo n.º 19
0
def sjs(j1, j2, j3, j4, j5, j6):
    """
    6-j symbol
    { j1 j2 j3 }
    { j4 j5 j6 }
    """
    #return wigner6j(j1,j2,j3,j4,j5,j6)
    return N(wigner_6j(0.5*j1,0.5*j2,0.5*j3,0.5*j4,0.5*j5,0.5*j6))
Exemplo n.º 20
0
def hf_reduced_f(F,J,FF,JJ,I):
    """
    Returns the coupling constant relating the reduced matrix element 
    in the hyperfine structure basis to that in the fine structure basis
    """

    ## Mark's notes, eq. A-51 
    return (-1)**(1+I+JJ+F)*sqrt((2*F+1)*(2*FF+1))*wigner_6j(J,I,F,FF,1,JJ)
Exemplo n.º 21
0
 def AME(self, state1, state2, p):
     l1, j1, m1 = state1.angular_momentum()
     l2, j2, m2 = state2.angular_momentum()
     res = (-1)**int(j1 + l2 - 0.5) * sqrt((2 * j1 + 1) * (2 * l1 + 1))
     res *= clebsch_gordan(j1, 1, j2, m1, p, m2)
     res *= clebsch_gordan(l1, 1, l2, 0, 0, 0)
     res *= wigner_6j(l1, 0.5, j1, j2, 1, l2)
     return res
Exemplo n.º 22
0
 def AME(self, state1, state2, p):
   l1, j1, m1 = state1.angular_momentum()
   l2, j2, m2 = state2.angular_momentum()
   res =(-1)**int(j1+l2-0.5)*sqrt((2*j1+1)*(2*l1+1))
   res *= clebsch_gordan(j1, 1, j2, m1, p, m2)
   res *= clebsch_gordan(l1, 1, l2, 0, 0, 0)
   res *= wigner_6j(l1,0.5,j1,j2,1,l2)
   return res
Exemplo n.º 23
0
def f_reduced_ls(J,L,JJ,LL):
    """
    Returns the coupling constant relating the reduced matrix element 
    in the fine structure basis to that in the L,S basis
    """

    ## Mark's notes, eq. A-51
    S = 1/2
    return (-1)**(1+S+LL+J)*sqrt((2*J+1)*(2*JJ+1))*wigner_6j(L,I,J,JJ,1,LL)
Exemplo n.º 24
0
def B_hfs(k_i, k_f):
    '''
    Branching ratio of hyperfine structure
    
    Args:
        k_i: excited state
        k_f: ground state
    '''
    return (2 * k_i.F + 1) * (2 * k_f.J + 1) * (wigner_6j(
        k_f.F, 1, k_i.F, k_i.J, k_i.I, k_f.J))**2
Exemplo n.º 25
0
def B_fs(k_i, k_f):
    '''
    Branching ratio for fine structure.
    
    Args:
        k_i: excited state
        k_f: ground state
    '''
    return (2 * k_i.J + 1) * (2 * k_f.L + 1) * (wigner_6j(
        k_f.J, 1, k_i.J, k_i.L, k_i.S, k_f.L))**2
Exemplo n.º 26
0
def test_wigner():
    def tn(a, b):
        return (a - b).n(64) < S('1e-64')

    assert tn(wigner_9j(1, 1, 1, 1, 1, 1, 1, 1, 0, prec=64), S(1) / 18)
    assert wigner_9j(
        3, 3, 2, 3, 3, 2, 3, 3,
        2) == 3221 * sqrt(70) / (246960 * sqrt(105)) - 365 / (3528 * sqrt(70) *
                                                              sqrt(105))
    assert wigner_6j(5, 5, 5, 5, 5, 5) == Rational(1, 52)
    assert tn(wigner_6j(8, 8, 8, 8, 8, 8, prec=64), -S(12219) / 965770)
    # regression test for #8747
    half = Rational(1, 2)
    assert wigner_9j(0, 0, 0, 0, half, half, 0, half, half) == half
    assert (wigner_9j(3, 5, 4, 7 * half, 5 * half, 4, 9 * half, 9 * half,
                      0) == -sqrt(Rational(361, 205821000)))
    assert (wigner_9j(1, 4, 3, 5 * half, 4, 5 * half, 5 * half, 2,
                      7 * half) == -sqrt(Rational(3971, 373403520)))
    assert (wigner_9j(4, 9 * half, 5 * half, 2, 4, 4, 5, 7 * half,
                      7 * half) == -sqrt(Rational(3481, 5042614500)))
Exemplo n.º 27
0
    def test_LF(self):
        """ Check that, in the low-field, our scattering rates match a more
        direct calculation. """
        ion = Ca43(B=1e-8)
        ion.calc_Epole()
        Gamma_ion = ion.Gamma
        I = ion.I
        Idim = int(np.rint(2*I+1))
        Gamma = np.zeros((ion.num_states, ion.num_states))

        for name, transition in ion.transitions.items():
            A = transition.A
            lower = transition.lower
            upper = transition.upper
            Ju = upper.J
            Jl = lower.J
            Jdim_l = int(np.rint(2*Jl+1))
            l_dim = Idim*Jdim_l

            dJ = Ju-Jl
            dL = upper.L - lower.L
            if dJ in [-1, 0, +1] and dL in [-1, 0, +1]:
                order = 1
            elif abs(dJ) in [0, 1, 2] and abs(dL) in [0, 1, 2]:
                order = 2
            else:
                raise ValueError("Unsupported transition order {}"
                                 .format(order))

            subspace = np.r_[ion.slice(lower), ion.slice(upper)]

            for l_ind in list(subspace[:l_dim]):
                for u_ind in list(subspace[l_dim:]):
                    Fl = ion.F[l_ind]
                    Fu = ion.F[u_ind]
                    Ml = ion.M[l_ind]
                    Mu = ion.M[u_ind]
                    q = Mu - Ml
                    if q not in range(-order, order+1):
                        continue

                    Gamma[l_ind, u_ind] = A*(
                        (2*Ju+1)
                        * (2*Fl+1)
                        * (2*Fu+1)
                        * (wigner_3j(Fu, order, Fl, -Mu, q, Ml))**2
                        * (wigner_6j(Ju, I, Fu, Fl, order, Jl)**2))

            subspace = np.ix_(subspace, subspace)
            scale = np.max(np.max(np.abs(Gamma[subspace])))
            eps = np.max(np.max(np.abs(Gamma[subspace]-Gamma_ion[subspace])))
            self.assertTrue(eps/scale < 1e-4)
Exemplo n.º 28
0
def test_wigner():
    def tn(a, b):
        return (a - b).n(64) < S('1e-64')
    assert tn(wigner_9j(1, 1, 1, 1, 1, 1, 1, 1, 0, prec=64), S(1)/18)
    assert wigner_9j(3, 3, 2, 3, 3, 2, 3, 3, 2) == 3221*sqrt(
        70)/(246960*sqrt(105)) - 365/(3528*sqrt(70)*sqrt(105))
    assert wigner_6j(5, 5, 5, 5, 5, 5) == Rational(1, 52)
    assert tn(wigner_6j(8, 8, 8, 8, 8, 8, prec=64), -S(12219)/965770)
    # regression test for #8747
    half = Rational(1, 2)
    assert wigner_9j(0, 0, 0, 0, half, half, 0, half, half) == half
    assert (wigner_9j(3, 5, 4,
                      7 * half, 5 * half, 4,
                      9 * half, 9 * half, 0)
            == -sqrt(Rational(361, 205821000)))
    assert (wigner_9j(1, 4, 3,
                      5 * half, 4, 5 * half,
                      5 * half, 2, 7 * half)
            == -sqrt(Rational(3971, 373403520)))
    assert (wigner_9j(4, 9 * half, 5 * half,
                      2, 4, 4,
                      5, 7 * half, 7 * half)
            == -sqrt(Rational(3481, 5042614500)))
Exemplo n.º 29
0
def zeeman_interaction_MJ(state_1, state_2, **kwargs):
    """ Zeeman interaction between two states.
    """
    delta_S = state_2.S - state_1.S
    delta_L = state_2.L - state_1.L
    delta_J = state_2.J - state_1.J
    delta_MJ = state_2.M - state_1.M
    if delta_MJ == 0 and \
       delta_J in [-1, 0, 1] and \
       delta_S == 0 and \
       delta_L == 0:
        L = state_1.L
        MJ = state_1.M
        S = state_1.S
        g_L2 = g_L * (((2 * L + 1) * L * (L + 1)) / 6)**0.5
        g_S2 = g_s * (((2 * S + 1) * S * (S + 1)) / 6)**0.5
        return (-1)**(1 - MJ) * ((2 * state_1.J + 1) * (2 * state_2.J + 1))**0.5 * \
            wigner_3j(state_2.J, 1, state_1.J, -MJ, 0, MJ) * 6**0.5 * ( \
            wigner_6j(L, state_2.J, S, state_1.J, L, 1) * \
            (-1)**(state_1.J + state_2.J + L + S) * g_L2 + \
            wigner_6j(state_1.J, state_2.J, 1, S, S, L) * \
            (-1)**(L + S) * g_S2)
    else:
        return 0.0
Exemplo n.º 30
0
    def polarizabilities(self, lam):
        """
        Calculate scalar, vector and tensor polarizability in SI units
        for initial state (self.state_i) for
        light with a given wavelength lam in nm.

        Arguments:
            lam (float): wavelength in nm
        Returns:
            (float,float,float) tuple: scalar, vector, tensor polarizability in SI units
        """
        omega = 2 * np.pi * c / lam
        Fi = self.Fi

        p0, p1, p2 = (0, 0, 0)

        for trans in self.transitions:
            state_f = trans['state_f']
            Ji = self._J_from_state(trans['state_i'])
            Jf = self._J_from_state(trans['state_f'])
            Gamma = trans['Gamma']

            for Ff in self._calc_Fs(Jf):
                omega_Ff_Fi = 2 * np.pi * self.transition_frequency_hyperfine(
                    state_f, Ff)
                matel = self.hyperfine_reduced_mat_el_sqd(
                    self.I, self.Fi, Ff, Ji, Jf, omega_Ff_Fi, Gamma)
                f = omega_Ff_Fi * matel / (hbar * (omega_Ff_Fi**2 - omega**2))

                p0 += 2 / 3 * f
                p1 += (-1)**(Fi+Ff+1) * np.sqrt(6*Fi*(2*Fi+1)/(Fi+1))\
                      * np.float(wigner_6j(1,1,1,Fi,Fi,Ff)) * f
                p2 += (-1)**(Fi+Ff) * np.sqrt(40*Fi*(2*Fi+1)*(2*Fi-1)/(3*(Fi+1)*(2*Fi+3)))\
                      * np.float(wigner_6j(1,1,2,Fi,Fi,Ff)) * f

        return p0, p1, p2
Exemplo n.º 31
0
def spectator(a, b, j, k, a1, b1, j1, n=True):
    """
    assuming j = a + b is an angular momentum addition rule,
    and the operator is of spherical vector order k, and 
    if the operator does not act on the b angular moment,
    then remove the effect of b so that the effect may be evaluated
    on a.
    
    See Brown and Carrington 5.174
    """
    if b != b1:
        return 0
    else:
        output = ((-1)**(j1 + a + k + b) * sqrt(
            (2 * j + 1) * (2 * j1 + 1)) * wigner_6j(a1, j1, b, j, a, k))
        return format_output(output, n=n)
Exemplo n.º 32
0
def spectator(a, b, j, k, a1, b1, j1, n=True):
    """
    assuming j = a + b is an angular momentum addition rule,
    and the operator is of spherical vector order k, and 
    if the operator does not act on the b angular moment,
    then remove the effect of b so that the effect may be evaluated
    on a.
    
    See Brown and Carrington 5.174
    """
    if b != b1:
        return 0
    else:
        output = ((-1)**(j1 + a + k + b) * 
                  sqrt((2 * j + 1) * (2 * j1 + 1)) *
                  wigner_6j(a1, j1, b, j, a, k))
        return format_output(output, n=n)
Exemplo n.º 33
0
 def dipole(self, Me, Mg, q):
     """
     Find the q-spherical component of the dipole matrix element between Me and Mg
     :param M1:
     :param M2:
     :param q:
     :return:
     """
     key = "%d%d%d" % (Me, Mg, q)
     if key not in self._cache:
         self._cache[key] = (
             (-1)**(self.Ig + self.Je - Me) * self.reduced_dipole_element *
             sqrt((2*self.Fg+1)*(2*self.Fe+1)) *
             float(wigner_6j(self.Je, self.Fe, self.Ig, self.Fg, self.Jg, 1)) *
             float(wigner_3j(self.Fg, 1, self.Fe, Mg, q, -Me))
         )
     return self._cache[key]
Exemplo n.º 34
0
    def _dipole_coeff(cls, state_i, state_f, parity_selection=True):
        """fine-structure reduced matrix element, Steck 7.274
        modified with additional delta function for unchanged spin
        and selection rule on wave function parity:
        delta_l (small) = +-1 (parity must change)
        """
        S, L, J = cls._parse_term_SLJ(state_i[1])
        Sf, Lf, Jf = cls._parse_term_SLJ(state_f[1])

        if parity_selection:
            if cls.parity(state_i) == cls.parity(state_f): return 0
        if S != Sf:
            return 0
        A = (-1)**(Jf + L + 1 + S)
        B = np.sqrt((2*Jf + 1) * (2*L + 1))
        C = wigner_6j(L, Lf, 1, Jf, J, S)

        return A*B*C
Exemplo n.º 35
0
def hf_coupling(F, mF, J, q, FF, mFF, JJ, I, RME=None):
    """ Returns the matrix element <F,mF,J|T_q|F',mF',J'>. 
        'RME': the reduced matrix element, e.g. the D2 line matrix
        element. If RME=None, the 
        matrix element is in units of [RME].
        
        I is the nuclear spin of the atom.
    """

    rme = 1
    if RME != None:
        rme = RME

    ## From Mark's notes, eqs. A-50,51
    mat_elem = rme*pow(-1,F+JJ+1+I)*sqrt((2*F+1)*(2*JJ+1)) \
                *wigner_6j(J,I,F,FF,1,JJ) \
                *clebsch_gordan(1,F,FF,q,mF,mFF)

    return mat_elem
Exemplo n.º 36
0
def N6j(*args):
    """ gives numerical value of 6-j symbol
    """
    return float(wigner.wigner_6j(*args))
Exemplo n.º 37
0
def dump_w6j(tjmax):
    import sympy.physics.wigner as spw
    for write in dump_output("symw6j", tjmax):
        for tjs in iter_6tjs(tjmax):
            z = spw.wigner_6j(*(Fraction(tj, 2) for tj in tjs))
            write("\t".join(map(str, tjs + (show_signedsqrtfrac(z),))) + "\n")
Exemplo n.º 38
0
 def doit(self, **hints):
     if self.is_symbolic:
         raise ValueError("Coefficients must be numerical")
     return wigner_6j(self.j1, self.j2, self.j12, self.j3, self.j, self.j3)