def compareKien(): """compare Kien 2013 Fig 4,5""" bprop =[880e-9,20e-3,1e-6] Cs = atom(atm = 'Cs133') Cs880 = dipole(Cs, (0,1/2.,3,3), bprop) CsP = dipole(Cs, (1,3/2.,3,3), bprop) wls = [np.linspace(680, 690, 200)*1e-9, np.linspace(930, 940, 200)*1e-9] ylims = [(-1200, 300), (-3000, 6000)] for ii in range(2): plt.figure() plt.title("Cs Polarisabilities. Red: 6S$_{1/2}$, Blue: 6P$_{3/2}$.\nscalar: solid, vector: dashed, tensor: dotted") a1 = Cs880.polarisability(wls[ii],mj=0.5,split=True) a2 = 0.5*(np.array(CsP.polarisability(wls[ii],mj=1.5, split=True))+ np.array(CsP.polarisability(wls[ii],mj=0.5, split=True))) ls = ['-', '--', ':'] for i in range(3): plt.plot(wls[ii]*1e9, a1[i]/au, 'r', linestyle=ls[i], label="Cs") plt.plot(wls[ii]*1e9, a2[i]/au, 'b', linestyle=ls[i], label="$P_{3/2}$") #plt.legend() plt.ylim(ylims[ii]) plt.xlabel("Wavelength (nm)") plt.ylabel("Polarisablity (a.u.)") plt.show()
def vmfSS(ATOM): """Return the Stark shifts of the MF states for Cs cooling/repump transitions""" plt.figure() if ATOM.atm == 'Cs133': Cs = ATOM F = 5 bprop = [938e-9, 8e-3, 1.7e-6] # wavelength, beam power, beam waist for MFp in range(-F, F+1, 1): P = dipole(Cs, (1,3/2.,F,MFp), bprop) Pshift = P.acStarkShift(0,0,0, bprop[0], HF=True)/h/1e6 # interested in how the EStates shift relative to each other plt.plot(MFp, Pshift, '_', markersize=15, linewidth=10, color = '#7E317B') print("|F' = "+str(F)+", m_F' = "+str(MFp)+"> : %.5g MHz"%Pshift) elif ATOM.atm == 'Rb87': Rb = ATOM F = 3 bprop = [940e-9, 35e-3, 1.7e-6] # wavelength, beam power, beam waist for MFp in range(-F, F+1, 1): P = dipole(Rb, (1,3/2.,F,MFp), bprop) Pshift = P.acStarkShift(0,0,0, bprop[0], HF=True)/h/1e6 # interested in how the EStates shift relative to each other s, v, t = P.polarisability(bprop[0], mj=3/2, HF=False, split=True) # print('split ',s/au, t/au) s, v, t = P.polarisability(bprop[0], mj=3/2, HF=True, split=True) # print('avrge ',s/au, t/au) plt.plot(MFp, Pshift, '_', markersize=15, linewidth=10, color = '#7E317B') print("|F' = "+str(F)+", m_F' = "+str(MFp)+"> : %.5g MHz"%Pshift) plt.title('Stark Shifts of ' + ATOM.atm + " |F' = " + str(F) + ', $M_F$> states' ) plt.xlabel("$M_F$") plt.ylabel("AC Stark Shift (MHz)") plt.show()
def getMFStarkShifts( wavelength=1064e-9, # laser wavelength in m power=0.00906143, # laser power in W beamwaist=1e-6, # beam waist in m plotit=False): # toggle to plot the results """Return the Stark shifts of the MF states for cooling/repump transitions. Units are MHz""" bprop = [wavelength, power, beamwaist] # collect beam properties Fs = [1, 2] numstates = sum(2 * np.array(Fs) + 1) * 3 # total number of hyperfine transitions l1 = [6, 12] # index of lines for making legend # states = np.zeros((numstates, 3), dtype=int) # F, MF, MFprime shifts = np.zeros(numstates) # differential ac Stark shifts i = 0 # index for F in Fs: for MF in range(-F, F + 1): for MFp in range(MF - 1, MF + 2): S = dipole(Rb, (0, 1 / 2., F, MF), bprop) P = dipole(Rb, (1, 3 / 2., F + 1, MFp), bprop) # states[i] = (F, MF, MFp) # units are MHz shifts[i] = ( S.acStarkShift(0, 0, 0, bprop[0], HF=True) - P.acStarkShift(0, 0, 0, bprop[0], HF=True)) / h / 1e6 i += 1 # if plotit: plt.figure() colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] i = 0 for F, MF, MFp in states: if MF != 0: deltaMF = (MFp - MF) * np.sign(MF) else: deltaMF = (MFp - MF) plt.plot(MF, shifts[i], '_', color=colors[F - 1], alpha=0.33 * (2 + deltaMF), markersize=15, linewidth=10) i += 1 plt.xlabel("$M_F$") plt.ylabel("AC Stark Shift (MHz)") lines = plt.gca().lines plt.legend(lines[l1[0]:l1[1]], [ 'F=' + str(f) + r', $\Delta M_F=$' + str(-dmf) for f in range(min(Fs), max(Fs) + 1) for dmf in range(-1, 2) ]) plt.show() # return states, shifts
def getMFStarkShifts(): """Return the Stark shifts of the MF states for Cs cooling/repump transitions""" print( "stark shift of Cs 6S1/2 -> 6P3/2 for different MF states at 1064nm for beam power 6 mW, beam waist 1 micron, giving trap depth 1 mK" ) bprop = [1064e-9, 6e-3, 1e-6] # wavelength, beam power, beam waist plt.figure() # colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] colors = ['k', 'r'] for F in [3, 4]: for MF in range(-F, F + 1): print(" ----- |F = " + str(F) + ", m_F = " + str(MF) + ">") for MFp in range(MF - 1, MF + 2): S = dipole(Cs.m, (0, 1 / 2., F, MF), bprop, Cs.D0S, Cs.w0S, Cs.lwS, Cs.nljS, nuclear_spin=Cs.I, symbol=Cs.X) P = dipole(Cs.m, (1, 3 / 2., F + 1, MFp), bprop, Cs.D0P3, Cs.w0P3, Cs.lwP3, Cs.nljP3, nuclear_spin=Cs.I, symbol=Cs.X) shift = (S.acStarkShift(0, 0, 0, bprop[0], HF=True) - P.acStarkShift(0, 0, 0, bprop[0], HF=True)) / h / 1e6 if MF != 0: deltaMF = (MFp - MF) * np.sign(MF) else: deltaMF = (MFp - MF) plt.plot(MF, shift, '_', color=colors[F - 3], alpha=0.33 * (2 + deltaMF), markersize=15, linewidth=10) print("|F' = " + str(F + 1) + ", m_F' = " + str(MFp) + "> : %.5g MHz" % shift) plt.xlabel("$M_F$") plt.ylabel("AC Stark Shift (MHz)") lines = plt.gca().lines plt.legend(lines[18:24], [ 'F=' + str(f) + ', $\Delta M_F=$' + str(-dmf) for f in range(3, 5) for dmf in range(-1, 2) ]) plt.show()
def compareArora(): """Plot Fig. 5 - 8 in Arora et al 2007 to show that the polarisabilities of Rb and Cs without hyperfine levels are correct""" # beam properties: wavelength, power, beam waist # intensity set to 1e10 MW/cm^2 bprop = [1064e-9, np.pi*0.5e-2, 1e-6] for ATOM in [atom(atm = 'Rb87'), atom(atm = 'Cs133')]: if ATOM.X == 'Rb87': wavel1 = np.linspace(780, 800, 200)*1e-9 Ylim1 = (-8000, 8000) wavel2 = np.linspace(787,794, 200)*1e-9 Ylim2 = (-1000, 1000) FS, FP = 1, 3 elif ATOM.X == 'Cs133': wavel1 = np.linspace(925, 1000, 200)*1e-9 Ylim1 = (-1000, 5000) wavel2 = np.linspace(927, 945, 200)*1e-9 Ylim2 = (-100, 100) FS, FP = 3, 5 S = dipole(ATOM, (0,1/2.,FS,FS), bprop) P3 = dipole(ATOM, (1,3/2.,FP,FP), bprop) # compare polarisability of excited states plt.figure() plt.title("Polarisability of "+ATOM.X) plt.plot(wavel1*1e9, S.polarisability(wavel1)/au, 'r', label='s') plt.plot(wavel1*1e9, P3.polarisability(wavel1,mj=0.5)/au, 'g--', label='p$_{3/2}$, mj=1/2') plt.plot(wavel1*1e9, P3.polarisability(wavel1,mj=1.5)/au, 'm:', label='p$_{3/2}$, mj=3/2') plt.legend() plt.xlabel("Wavelength (nm)") plt.ylabel("Polarisability (a.u.)") plt.ylim(Ylim1) plt.xlim(wavel1[0]*1e9, wavel1[-1]*1e9) # calculate stark shifts between F, MF states mfLS = ['r', 'g--', 'm:', 'c-.', 'k-.', 'y'] # line styles plt.figure() plt.title("AC Stark Shifts for transitions from P$_{3/2}$ m$_F$ to \nthe groundstate in "+ATOM.X) dES = S.acStarkShift(0,0,0, wavel2, HF=True) # ground state stark shift for MF in range(FP+1): P3.MF = MF dEPMF = P3.acStarkShift(0,0,0, wavel2, HF=True) # excited MF state stark shift plt.plot(wavel2*1e9, (dEPMF - dES)/h/1e6, mfLS[MF], label=r'm$_F$ = $\pm$'+str(MF)) xlims = [wavel2[0]*1e9, wavel2[-1]*1e9] plt.plot(xlims, [0,0], 'k:', alpha=0.4) # show where zero is plt.ylim(Ylim2) plt.xlim(xlims) plt.xlabel("Wavelength (nm)") plt.ylabel("Stark Shift (MHz)") plt.legend() plt.show()
def plotPolarisability(): """Plot the polarisability of Rb 5S and Cs 6S states highlighting our laser wavelengths""" bprop = [1064e-9, 6e-3, 1e-6] # wavelength, beam power, beam waist wavelengths = np.linspace(700, 1100, 500) * 1e-9 # in m ymax = 5000 # groundstate rubidium Rb5S = dipole(Rb, (0, 1 / 2., 1, 1), bprop) alphaRb = Rb5S.polarisability( wavelengths) / au # polarisability in atomic units # groundstate caesium Cs6S = dipole(Cs, (0, 1 / 2., 4, 4), bprop) alphaCs = Cs6S.polarisability( wavelengths) / au # polarisability in atomic units plt.figure() # split up the plotting so as not to have lines at resonances: for v in [[alphaRb, DUsea_blue, 'Rb 5S$_{1/2}$'], [alphaCs, DUcherry_red, 'Cs 6S$_{1/2}$']]: plus = np.where(v[0] > 0)[0] # where polarisability is positive ind1 = plus[np.where(plus > np.arange(len(plus)) + plus[0])[0][0]] # second positive region plt.plot(wavelengths[:plus[0] - 1] * 1e9, v[0][:plus[0] - 1], color=v[1], label=v[2]) plt.plot(wavelengths[plus[0] + 1:ind1 - 1] * 1e9, v[0][plus[0] + 1:ind1 - 1], color=v[1]) plt.plot(wavelengths[ind1 + 1:] * 1e9, v[0][ind1 + 1:], color=v[1]) # plot dotted lines to show where the resonances are plt.plot([780] * 2, [-ymax, ymax], '--', color=DUsea_blue) plt.plot([795] * 2, [-ymax, ymax], '--', color=DUsea_blue) plt.plot([852.3] * 2, [-ymax, ymax], '--', color=DUcherry_red) plt.plot([894.6] * 2, [-ymax, ymax], '--', color=DUcherry_red) # show zero crossing plt.plot([wavelengths[0] * 1e9, wavelengths[-1] * 1e9], [0, 0], 'k--', alpha=0.4) # show laser wavelengths # plt.fill_between([1060,1070], ymax, -ymax, color=DUcherry_red, alpha=0.3) # plt.fill_between([935,945], ymax, -ymax, color=DUcherry_red, alpha=0.3) # plt.fill_between([878, 882], ymax, -ymax, color=DUsea_blue, alpha=0.3) # plt.fill_between([805,825], ymax, -ymax, color=DUsea_blue, alpha=0.3) plt.ylim((-ymax, ymax)) plt.ylabel('Polarisability ($a_0^3$)') plt.xlim((wavelengths[0] * 1e9, wavelengths[-1] * 1e9)) plt.xlabel('Wavelength (nm)') plt.legend() plt.tight_layout() plt.show()
def getMFStarkShifts( wavelength=1064e-9, # laser wavelength in m power=0.00906143, # laser power in W beamwaist=1e-6, # beam waist in m ATOM=Cs): """Return the Stark shifts of the MF states for cooling/repump transitions""" bprop = [wavelength, power, beamwaist] # collect beam properties if ATOM == Cs: # assign the relevant hyperfine transitions Fs = [3, 4] l1 = [18, 24] # index of lines for making legend elif ATOM == Rb: Fs = [1, 2] l1 = [6, 12] # index of lines for making legend # print("Stark shift of "+ATOM.X+" S1/2 F = %s, %s -> P3/2 F' = %s, %s for different MF states."%(Fs[0],Fs[0]+1,Fs[1],Fs[1]+1)) plt.figure() colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] for F in Fs: for MF in range(-F, F + 1): print(" ----- |F = " + str(F) + ", m_F = " + str(MF) + ">") for MFp in range(MF - 1, MF + 2): S = dipole(ATOM, (0, 1 / 2., F, MF), bprop) P = dipole(ATOM(1, 3 / 2., F + 1, MFp), bprop) shift = (S.acStarkShift(0, 0, 0, bprop[0], HF=True) - P.acStarkShift(0, 0, 0, bprop[0], HF=True)) / h / 1e6 if MF != 0: deltaMF = (MFp - MF) * np.sign(MF) else: deltaMF = (MFp - MF) plt.plot(MF, shift, '_', color=colors[F - 1], alpha=0.33 * (2 + deltaMF), markersize=15, linewidth=10) print("|F' = " + str(F + 1) + ", m_F' = " + str(MFp) + "> : %.5g MHz" % shift) plt.xlabel("$M_F$") plt.ylabel("Differential AC Stark Shift (MHz)") lines = plt.gca().lines plt.legend(lines[l1[0]:l1[1]], [ 'F=' + str(f) + r', $\Delta M_F=$' + str(-dmf) for f in range(min(Fs), max(Fs) + 1) for dmf in range(-1, 2) ]) plt.show()
def showResult(): wavelength = float(entrystrings[0].get()) # laser wavelength in nm beamwaist = float(entrystrings[1].get()) # beam waist in m power = float(entrystrings[2].get()) # power in Watts bprop = [wavelength, power, beamwaist] # collect beam properties atomSymbol = entrystrings[3].get() # choose Rb or Cs L = int(entrystrings[4].get()) # orbital angular momentum J = float(entrystrings[5].get()) # total angular momentum # choose element if atomSymbol == "Rb": atomObj = Rb F = 1 elif atomSymbol == "Cs": atomObj = Cs F = 3 else: messagebox.showinfo("Error", "You must choose Rb or Cs") return 0 # get transition data for the given state if L == 0: D0, w0, lw, nlj = atomObj.D0S, atomObj.w0S, atomObj.lwS, atomObj.nljS elif L == 1 and J == 0.5: D0, w0, lw, nlj = atomObj.D0P1, atomObj.w0P1, atomObj.lwP1, atomObj.nljP1 elif L == 1 and J == 1.5: D0, w0, lw, nlj = atomObj.D0P3, atomObj.w0P3, atomObj.lwP3, atomObj.nljP3 # construct the instance of the dipole class dipoleObj = dipole(atomObj, (L, J, F, F), bprop) messagebox.showinfo("Calculation Result", getStarkShift(dipoleObj))
def heatRate(wl, P, w0, trapfreq, X=Rb): """heating rate in units of vibrational quanta per second wl - wavelength (m) P - beam power (W) w0 - beam waist (m) trapfreq - atomic trap frequency (rad/s) X - instance of atom() class from AtomFieldInt_V3""" atom = dipole(X, (0,1/2.,1,1), [wl, P, w0]) return atom.scatRate() * hbar * (2*np.pi/wl)**2 / 2 / X.m / trapfreq
# compare trapping frequencies and Rabi frequencies between Rb/Cs def wz(atom): """Axial trapping freq""" return np.sqrt( 2 * np.abs(atom.acStarkShift(0, 0, 0) / atom.m / atom.field.zR**2)) def wr(atom): """Radial trap freq""" return np.sqrt( 4 * np.abs(atom.acStarkShift(0, 0, 0) / atom.m / atom.field.w0**2)) rb5s = dipole(Rb, (0, 1 / 2., 1, 1), [814e-9, 1.46e-3, 1e-6]) print(rb5s.acStarkShift(0, 0, 0) / h / 1e6 / 20.7) cs6s = dipole(Cs, (0, 1 / 2., 3, 3), [940e-9, 5.02e-3, 1.1e-6]) print(cs6s.acStarkShift(0, 0, 0) / h / 1e6 / 20.7) print((wz(rb5s) / wz(cs6s))**2) wl = 780.241209686e-9 # wavelength of D2 line in m 852.347065e-9 power = 100e-6 # in W waist = 100e-6 # in m # # calculate differential stark shifts for Raman transition # X = Rb # F, mF, Fp, mFp = 1, 1, 2, 2 # wl = 780.241209686e-9 # wavelength of D2 line in m 852.347065e-9
Rbwl = 814e-9 # wavelength of the Rb tweezer trap in m power = 8e-3 # power of Cs tweezer beam in W Cswaist = 1.5e-6 # beam waist for Cs in m Rbpower = power*0.43 # power of Rb tweezer beam in W Rbwaist = 1.5e-6 # beam waist fir Rb in m minU0 = -0.6e-3*kB # min acceptable combined trap depth for Cs factorRb = 2 # how much deeper the Rb must be in its own trap factorCs = 2 # how much deeper the Cs must be in its own trap wavels = np.linspace(800, 840, 400) * 1e-9 # wavelengths to consider for Rb trap, in m # For the 1064nm trap: at Cs wavelength with Cs power and Cs beam waist # mass, (L,J,F,MF), bprop, dipole matrix elements (Cm), resonant frequencies (rad/s), # linewidths (rad/s), state labels, nuclear spin, atomic symbol. # groundstate rubidium 5 S 1/2 Rb1064 = dipole(Rb, (0,1/2.,1,1), [Cswl, power, Cswaist]) # groundstate caesium 6 S 1/2 Cs1064 = dipole(Cs, (0,1/2.,4,4), [Cswl, power, Cswaist]) print("Rb tweezer wavelength: %.0f nm\t\tCs tweezer wavelength: %.0f nm\n"%(Cswl*1e9, Rbwl*1e9)) # set the power of the traps so that the trap depth experienced by each # species in the overlapping trap is the same: # Rbpower = (Cs1064.polarisability(Cswl,mj=0.5) - Rb1064.polarisability(Cswl, mj=0.5) # )/ (Rb1064.polarisability(Rbwl, mj=0.5) - Cs1064.polarisability(Rbwl, mj=0.5)) * power # Stability condition 1: def P1Rb(wlCs, wlRb, U0min=minU0, Cspower=power): """Condition 1: The combined trap depth must be > 0.6mK for Cs.""" return abs((U0min*np.pi*eps0*c + Cs1064.polarisability(wlCs)*Cspower/Cswaist**2)
def combinedTrap(Cswl = 1064e-9, # wavelength of the Cs tweezer trap in m Rbwl = 880e-9, # wavelength of the Rb tweezer trap in m power = 6e-3, # power of Cs tweezer beam in W Rbpower = -1, # power of Rb tweezer beam in W beamwaist = 1e-6): # beam waist in m """Model tweezer traps for Rb and Cs and find the potential each experiences when they're overlapping. Should fix the separate tweezer trap depths to >1mK. We also want Rb to experience a deeper trap from its tweezer than from the Cs tweezer so that there isn't too much heating during merging. args: Cswl = 1064e-9, # wavelength of the Cs tweezer trap in m Rbwl = 880e-9, # wavelength of the Rb tweezer trap in m power = 6e-3, # power of Cs tweezer beam in W Rbpower = -1, # power of Rb tweezer beam in W (if < 0 then choose a power such that both species experience the same trap depth when the tweezers are overlapping) beamwaist = 1e-6 # beam waist in m """ bprop = [Cswl, power, beamwaist] # collect beam properties # For the 1064nm trap: # mass, (L,J,F,MF), bprop, dipole matrix elements (Cm), resonant frequencies (rad/s), # linewidths (rad/s), state labels, nuclear spin, atomic symbol. # groundstate rubidium Rb = atom(atm = 'Rb87') Rb1064 = dipole(Rb, (0,1/2.,1,1), bprop) # groundstate caesium Cs = atom(atm = 'Cs133') Cs1064 = dipole(Cs, (0,1/2.,4,4), bprop) CsP = dipole(Cs, (1,3/2.,5,5), bprop) # set the power of the traps so that the trap depth experienced by each # species in the overlapping trap is the same: if Rbpower < 0: Rbpower = (Cs1064.polarisability(Cswl,mj=0.5) - Rb1064.polarisability(Cswl, mj=0.5)) / (Rb1064.polarisability(Rbwl, mj=0.5) - Cs1064.polarisability(Rbwl, mj=0.5)) * power # for the 880nm trap: bprop = [Rbwl, abs(Rbpower), beamwaist] Rb880 = dipole(Rb, (0,1/2.,1,1), bprop) Cs880 = dipole(Cs, (0,1/2.,3,3), bprop) # in the trap with both tweezers overlapping: U0 = abs(Rb1064.acStarkShift(0,0,0) + Rb880.acStarkShift(0,0,0)) wrRb = np.sqrt(4*U0 / Rb.m / beamwaist**2) /2. /np.pi /1e3 wrCs = np.sqrt(4*U0 / Cs.m / beamwaist**2) /2. /np.pi /1e3 print("%.0f beam power: %.3g mW\t\t%.0f beam power: %.3g mW"%(Cswl*1e9, power*1e3, Rbwl*1e9, Rbpower*1e3)) print("""In the combined %.0fnm and %.0fnm trap with a depth of %.3g mK the radial trapping frequencies are: Rubidium: %.0f kHz \nCaesium: %.0f kHz"""%(Rbwl*1e9, Cswl*1e9, U0/kB*1e3, wrRb, wrCs)) # with just the Cs tweezer trap: URb =abs(Rb1064.acStarkShift(0,0,0)) wrRb1064 = np.sqrt(4*URb / Rb.m / beamwaist**2) /2. /np.pi /1e3 UCs = abs(Cs1064.acStarkShift(0,0,0)) wrCs1064 = np.sqrt(4*UCs / Cs.m / beamwaist**2) /2. /np.pi /1e3 print("""\nIn just the %.0fnm trap: Rubidium has trap depth %.3g mK radial trapping frequency %.0f kHz Caesium has trap depth %.3g mK radial trapping frequency %.0f kHz"""%(Cswl*1e9, URb/kB*1e3, wrRb1064, UCs/kB*1e3, wrCs1064)) print(getStarkShift(Cs1064)) print(getStarkShift(CsP)) # plot merging traps: n = 5 # number of time steps in merging to plot sep = np.linspace(0, 10e-6, n) # initial separation of the tweezer traps zs = np.linspace(-2, 10, 200)*1e-6 # positions along the beam axis for atoms in [[Rb1064, Rb880], [Cs1064, Cs880]]: plt.figure() plt.subplots_adjust(hspace=0.01) for i in range(n): ax = plt.subplot2grid((n,1), (i,0)) U = (atoms[0].acStarkShift(0,0,zs) + atoms[1].acStarkShift(0,0,zs-sep[n-i-1]))/kB*1e3 # combined potential along the beam axis U1064 = atoms[0].acStarkShift(0,0,zs)/kB*1e3 # potential in the 1064 trap U880 = atoms[1].acStarkShift(0,0,zs-sep[n-i-1])/kB*1e3 # potential in the 880 trap plt.plot(zs*1e6, U, 'k') plt.plot(zs*1e6, U1064, color='tab:orange', alpha=0.6) plt.plot(zs*1e6, U880, color='tab:blue', alpha=0.6) plt.plot([0]*2, [min(U),0], color='tab:orange', linewidth=10, label='%.0f'%(Cswl*1e9), alpha=0.4) plt.plot([sep[n-i-1]*1e6]*2, [min(U),0], color='tab:blue', linewidth=10, label='%.0f'%(Rbwl*1e9), alpha=0.4) ax.set_xticks([]) ax.set_yticks([]) if i == 0: ax.set_title("Optical potential experienced by "+atoms[0].X +"\n%.0f beam power: %.3g mW %.0f beam power: %.3g mW"%(Cswl*1e9, power*1e3, Rbwl*1e9, Rbpower*1e3), pad = 25) plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3, ncol=2, mode="expand", borderaxespad=0.) plt.xlabel(r'Position ($\mu$m)') ax.set_xticks(sep*1e6) plt.ylabel('Trap Depth (mK)') ax.yaxis.set_major_locator(AutoLocator()) plt.show()
def plotStarkShifts( wavelength=880e-9, # laser wavelength in nm beamwaist=1e-6, # beam waist in m power=20e-3): # power in Watts """Find the ac Stark Shifts in Rb, Cs""" # typical optical tweezer parameters: bprop = [wavelength, power, beamwaist] # collect beam properties # mass, (L,J,F,MF), bprop, dipole matrix elements (Cm), resonant frequencies (rad/s), # linewidths (rad/s), state labels, nuclear spin, atomic symbol. Rb5S = dipole(Rb.m, (0, 1 / 2., 1, 1), bprop, Rb.D0S, Rb.w0S, Rb.lwS, Rb.nljS, nuclear_spin=Rb.I, symbol=Rb.X) Rb5P = dipole(Rb.m, (1, 3 / 2., 1, 1), bprop, Rb.D0P3, Rb.w0P3, Rb.lwP3, Rb.nljP3, nuclear_spin=Rb.I, symbol=Rb.X) Cs6S = dipole(Cs.m, (0, 1 / 2., 3, 3), bprop, Cs.D0S, Cs.w0S, Cs.lwS, Cs.nljS, nuclear_spin=Cs.I, symbol=Cs.X) Cs6P = dipole(Cs.m, (1, 3 / 2., 3, 3), bprop, Cs.D0P3, Cs.w0P3, Cs.lwP3, Cs.nljP3, nuclear_spin=Cs.I, symbol=Cs.X) # need a small spacing to resolve the magic wavelengths - so it will run slow # to resolve magic wavelengths, take about 10,000 points. wavels = np.linspace(700e-9, 1100e-9, 500) # ac Stark Shift in Joules: dE6S = Cs6S.acStarkShift(0, 0, 0, wavels, mj=0.5, HF=False) dE6P = Cs6P.acStarkShift(0, 0, 0, wavels, mj=1.5, HF=False) dif6P = dE6P - dE6S magic6P = getMagicWavelengths(dif6P, dE6P, wavels) plt.figure() plt.title("AC Stark Shift in $^{133}$Cs") plt.plot(wavels * 1e9, dE6S / h * 1e-6, 'b--', label='Ground S$_{1/2}$') plt.plot(wavels * 1e9, dE6P / h * 1e-6, 'r-.', label='Excited P$_{3/2}$') plt.plot(wavels * 1e9, (dif6P) / h * 1e-6, 'k', label='Difference') plt.plot([magic6P[0] * 1e9] * 2, [min(dif6P / h / 1e6), max(dif6P / h / 1e6)], 'm:', label='Magic Wavelength') plt.legend() for mw in magic6P[1:]: plt.plot( [mw * 1e9] * 2, [min(dif6P / h / 1e6), max(dif6P / h / 1e6)], 'm:') plt.ylabel("Stark Shift (MHz)") plt.xlabel("Wavelength (nm)") plt.xlim(wavels[0] * 1e9, wavels[-1] * 1e9) plt.ylim(-2200, 2200) plt.plot(wavels * 1e9, np.zeros(len(wavels)), 'k', alpha=0.25) # show zero crossing plt.show() print("Magic wavelengths at:\n", magic6P) # ac Stark Shift in Joules: dE5S = Rb5S.acStarkShift(0, 0, 0, wavels, mj=0.5, HF=False) dE5P = Rb5P.acStarkShift(0, 0, 0, wavels, mj=1.5, HF=False) dif5P = dE5P - dE5S plt.figure() plt.title("AC Stark Shift in $^{87}$Rb") plt.plot(wavels * 1e9, dE5S / h * 1e-6, 'b--', label='Ground S$_{1/2}$') plt.plot(wavels * 1e9, dE5P / h * 1e-6, 'r-.', label='Excited P$_{3/2}$') plt.plot(wavels * 1e9, (dif5P) / h * 1e-6, 'k', label='Difference') plt.legend() plt.ylabel("Stark Shift (MHz)") plt.xlabel("Wavelength (nm)") plt.ylim(-500, 500) plt.plot(wavels * 1e9, np.zeros(len(wavels)), 'k', alpha=0.25) # show zero crossing plt.show()
def combinedTrap( Cswl=1064e-9, # wavelength of the Cs tweezer trap in m Rbwl=880e-9, # wavelength of the Rb tweezer trap in m power=20e-3, # power in W beamwaist=1e-6): # beam waist in m """Model tweezer traps for Rb and Cs and find the potential each experiences when they're overlapping""" bprop = [Cswl, power, beamwaist] # collect beam properties # For the 1064nm trap: # mass, (L,J,F,MF), bprop, dipole matrix elements (Cm), resonant frequencies (rad/s), # linewidths (rad/s), state labels, nuclear spin, atomic symbol. # groundstate rubidium Rb1064 = dipole(Rb.m, (0, 1 / 2., 1, 1), bprop, Rb.D0S, Rb.w0S, Rb.lwS, Rb.nljS, nuclear_spin=Rb.I, symbol=Rb.X) # groundstate caesium Cs1064 = dipole(Cs.m, (0, 1 / 2., 4, 4), bprop, Cs.D0S, Cs.w0S, Cs.lwS, Cs.nljS, nuclear_spin=Cs.I, symbol=Cs.X) CsP = dipole(Cs.m, (1, 3 / 2., 5, 5), bprop, Cs.D0P3, Cs.w0P3, Cs.lwP3, Cs.nljP3, nuclear_spin=Cs.I, symbol=Cs.X) # set the power of the traps so that the trap depth experienced by each # species in the overlapping trap is the same: P880 = (Cs1064.polarisability(Cswl, mj=0.5) - Rb1064.polarisability( Cswl, mj=0.5)) / (Rb1064.polarisability(Rbwl, mj=0.5) - Cs1064.polarisability(Rbwl, mj=0.5)) * power # for the 880nm trap: bprop = [Rbwl, abs(P880), beamwaist] Rb880 = dipole(Rb.m, (0, 1 / 2., 1, 1), bprop, Rb.D0S, Rb.w0S, Rb.lwS, Rb.nljS, nuclear_spin=Rb.I, symbol=Rb.X) Cs880 = dipole(Cs.m, (0, 1 / 2., 3, 3), bprop, Cs.D0S, Cs.w0S, Cs.lwS, Cs.nljS, nuclear_spin=Cs.I, symbol=Cs.X) # in the trap with both tweezers overlapping: U0 = abs(Rb1064.acStarkShift(0, 0, 0) + Rb880.acStarkShift(0, 0, 0)) wrRb = np.sqrt(4 * U0 / Rb.m / beamwaist**2) / 2. / np.pi / 1e3 wrCs = np.sqrt(4 * U0 / Cs.m / beamwaist**2) / 2. / np.pi / 1e3 print("%.0f beam power: %.3g mW\t\t%.0f beam power: %.3g mW" % (Cswl * 1e9, power * 1e3, Rbwl * 1e9, P880 * 1e3)) print( """In the combined %.0fnm and %.0fnm trap with a depth of %.3g mK the radial trapping frequencies are: Rubidium: %.0f kHz \nCaesium: %.0f kHz""" % (Rbwl * 1e9, Cswl * 1e9, U0 / kB * 1e3, wrRb, wrCs)) # with just the Cs tweezer trap: URb = abs(Rb1064.acStarkShift(0, 0, 0)) wrRb1064 = np.sqrt(4 * URb / Rb.m / beamwaist**2) / 2. / np.pi / 1e3 UCs = abs(Cs1064.acStarkShift(0, 0, 0)) wrCs1064 = np.sqrt(4 * UCs / Cs.m / beamwaist**2) / 2. / np.pi / 1e3 print("""\nIn just the %.0fnm trap: Rubidium has trap depth %.3g mK radial trapping frequency %.0f kHz Caesium has trap depth %.3g mK radial trapping frequency %.0f kHz""" % (Cswl * 1e9, URb / kB * 1e3, wrRb1064, UCs / kB * 1e3, wrCs1064)) print(getStarkShift(Cs1064)) print(getStarkShift(CsP)) # plot merging traps: n = 5 # number of time steps in merging to plot sep = np.linspace(0, 10e-6, n) # initial separation of the tweezer traps zs = np.linspace(-2, 10, 200) * 1e-6 # positions along the beam axis for atoms in [[Rb1064, Rb880], [Cs1064, Cs880]]: plt.figure() plt.subplots_adjust(hspace=0.01) for i in range(n): ax = plt.subplot2grid((n, 1), (i, 0)) if i == 0: ax.set_title( "Optical potential experienced by " + atoms[0].X + "\n%.0f beam power: %.3g mW %.0f beam power: %.3g mW" % (Cswl * 1e9, power * 1e3, Rbwl * 1e9, P880 * 1e3)) U = (atoms[0].acStarkShift(0, 0, zs) + atoms[1].acStarkShift(0, 0, zs - sep[n - i - 1]) ) / kB * 1e3 # combined potential along the beam axis U1064 = atoms[0].acStarkShift( 0, 0, zs) / kB * 1e3 # potential in the 1064 trap U880 = atoms[1].acStarkShift( 0, 0, zs - sep[n - i - 1]) / kB * 1e3 # potential in the 880 trap plt.plot(zs * 1e6, U, 'k') plt.plot(zs * 1e6, U1064, color='tab:orange', alpha=0.6) plt.plot(zs * 1e6, U880, color='tab:blue', alpha=0.6) plt.plot([0] * 2, [min(U), 0], color='tab:orange', linewidth=10, label='%.0f' % (Cswl * 1e9), alpha=0.4) plt.plot([sep[n - i - 1] * 1e6] * 2, [min(U), 0], color='tab:blue', linewidth=10, label='%.0f' % (Rbwl * 1e9), alpha=0.4) ax.set_xticks([]) ax.set_yticks([]) plt.xlabel('Position ($\mu$m)') ax.set_xticks(sep * 1e6) plt.ylabel('Trap Depth (mK)') ax.yaxis.set_major_locator(AutoLocator()) plt.show()
'F=' + str(f) + ', $\Delta M_F=$' + str(-dmf) for f in range(3, 5) for dmf in range(-1, 2) ]) plt.show() if __name__ == "__main__": wavelength = 1064e-9 # wavelength in m power = 6e-3 # beam power in W beamwaist = 1e-6 # beam waist in m bprop = [wavelength, power, beamwaist] Rb5P1 = dipole(Rb.m, (1, 1 / 2., 1, 1), bprop, Rb.D0P1, Rb.w0P1, Rb.lwP1, Rb.nljP1, nuclear_spin=Rb.I, symbol=Rb.X) Rb5P3 = dipole(Rb.m, (1, 3 / 2., 1, 1), bprop, Rb.D0P3, Rb.w0P3, Rb.lwP3, Rb.nljP3, nuclear_spin=Rb.I, symbol=Rb.X) # print(getStarkShift(Rb5P1)) print(getStarkShift(Rb5P3)) print(np.array(Rb5P3.polarisability(795e-9, HF=True, split=True)) / au)
from AtomFieldInt_V3 import (dipole, atom, c, eps0, h, hbar, a0, e, me, kB, amu, Eh, au, atom) Rb = atom(atm='Rb87') Cs = atom(atm='Cs133') Na = atom(atm='Na23') Cswl = 976e-9 # wavelength of the Cs tweezer trap in m Nawl = 700e-9 # wavelength of the Rb tweezer trap in m Cspower = 5e-3 # power of Cs tweezer beam in W Napower = 5e-3 # power of Rb tweezer beam in W Cswaist = 0.8e-6 # beam waist for Cs in m Nawaist = 0.7e-6 # beam waist fir Na in m # Cs in its own tweezer Cs976 = dipole(Cs, (0, 1 / 2., 4, 4), [Cswl, Cspower, Cswaist]) # Cs in the Na tweezer Cs700 = dipole(Cs, (0, 1 / 2., 4, 4), [Nawl, Napower, Nawaist]) # Na in the Cs tweezer Na976 = dipole(Na, (0, 1 / 2., 1, 1), [Cswl, Cspower, Cswaist]) # Na in its own tweezer Na700 = dipole(Na, (0, 1 / 2., 1, 1), [Nawl, Napower, Nawaist]) # separated tweezer trap depths in mK: U_cs_976 = Cs976.acStarkShift(0, 0, 0) / kB * 1e3 U_cs_700 = Cs700.acStarkShift(0, 0, 0) / kB * 1e3 U_na_976 = Na976.acStarkShift(0, 0, 0) / kB * 1e3 U_na_700 = Na700.acStarkShift(0, 0, 0) / kB * 1e3 # combined trap depths in mK: U_cs = U_cs_976 + U_cs_700
def plotScatRate(): """Plot the polarisability of Rb 5S and Cs 6S states and the scattering rates within a given wavelength range (given in metres)""" bprop = [1064e-9, 6e-3, 1e-6] # wavelength, beam power, beam waist wl1 = np.linspace(795e-9, Cs.rwS[0], 200) # wavelength below Cs D1 line (m) wl2 = np.linspace(Cs.rwS[0], 1100e-9, 200) # wavelength below Cs D1 line (m) # groundstate rubidium Rb5S = dipole(Rb, (0, 1 / 2., 1, 1), bprop) # below Cs D1 line, use intensities such that the Rb trap depth is 1mK I1 = 2 * kB * 1e-3 * eps0 * c / Rb5S.polarisability(wl1) # groundstate caesium Cs6S = dipole(Cs, (0, 1 / 2., 4, 4), bprop) # above Cs D1 line, use intensities such that the Cs trap depth is 1mK I2 = 2 * kB * 1e-3 * eps0 * c / Cs6S.polarisability(wl2) fig, ax = plt.subplots(2, 2, gridspec_kw={ 'height_ratios': [3, 2], 'hspace': 0, 'wspace': 0.02 }, sharex='col') for i, wl, I in [[0, wl1, I1], [1, wl2, I2]]: # plot scattering rates for fixed trap depth ax[0][i].semilogy(wl * 1e9, Rb5S.scatRate(wl, I), color=DUsea_blue, label='Rb 5S$_{1/2}$') # Rb ax[0][i].semilogy(wl * 1e9, Cs6S.scatRate(wl, I), color=DUcherry_red, label='Cs 6S$_{1/2}$') # Cs ax[0][i].plot([min(wl) * 1e9, max(wl) * 1e9], [100] * 2, 'k:') # show acceptable limit ax[0][i].set_ylim((2, 10000)) # plot polarisability in the same wavelength range ax[1][i].plot(wl * 1e9, Rb5S.polarisability(wl) / au, color=DUsea_blue, label='Rb 5S$_{1/2}$') ax[1][i].plot(wl * 1e9, Cs6S.polarisability(wl) / au, color=DUcherry_red, label='Cs 6S$_{1/2}$') ax[1][i].set_ylim((-6000, 6000)) if not i: # only have y label on the lhs ax[0][i].set_ylabel('Scattering Rate (s$^{-1}$)') ax[1][i].set_ylabel('Polarisability ($a_0^3$)') else: # remove ticks ax[0][i].set_yticks([]) ax[1][i].set_yticks([]) ax[1][i].set_xlim((wl[0] * 1e9, wl[-1] * 1e9)) ax[1][i].set_xlabel('Wavelength (nm)') # calculate trap depth # Rbdepths, Csdepths = np.zeros(len(wavelengths)), np.zeros(len(wavelengths)) # for i in range(len(wavelengths)): # power changes to keep trap depth fixed # Rb5S.field.E0 = np.sqrt(2 * abs(Is[i]) / eps0 / c) # Cs6S.field.E0 = np.sqrt(2 * abs(Is[i]) / eps0 / c) # Rbdepths[i] = Rb5S.acStarkShift(0,0,0, wavelengths[i])/kB*1e3 # in mK # Csdepths[i] = Cs6S.acStarkShift(0,0,0, wavelengths[i])/kB*1e3 # in mK # # ax1 = ax[0].twinx() # plot trap depth # l3 = ax1.plot(wavelengths*1e9, Rbdepths, '--', color=DUsea_blue, label='Trap Depth', alpha=0.5) # l4 = ax1.plot(wavelengths*1e9, Csdepths, '--', color=DUcherry_red, label='Trap Depth', alpha=0.5) # ax1.set_ylabel('Trap Depth (mK)') # ax1.set_ylim((-3, 3)) # lines = l1+l2+l3+l4 # order lines so that they appear next to each other in the legend # ax[0].legend(lines, [l.get_label() for l in lines], ncol=2, fontsize=11) plt.subplots_adjust(left=0.17, right=0.95, top=0.93, bottom=0.13) ax[0][1].legend() ax[0][0].set_title('Rb Trap Depth 1 mK') ax[0][1].set_title('Cs Trap Depth 1 mK') plt.show()
def check880Trap(wavelength = 880e-9, # wavelength in m wavels = np.linspace(795,930,500)*1e-9, # wavelengths in m to plot power = 5e-3, # beam power in W beamwaist = 1e-6, # beam waist in m species = 'Rb'): # which species to set a 1mK trap for """Plot graphs of the trap depth experienced by Cs around 880nm when the ground state Rb trap depth is fixed at 1mK. Look at the scattering rates and hence trap lifetimes that are possible.""" bprop = [wavelength, power, beamwaist] Rb = atom(atm = 'Rb87') Rb5S = dipole(Rb, (0,1/2.,1,1), bprop) Rb5P = dipole(Rb, (1,3/2.,1,1), bprop) Cs = atom(atm = 'Cs133') Cs6S = dipole(Cs, (0,1/2.,3,3), bprop) Cs6P = dipole(Cs, (1,3/2.,3,3), bprop) # choose power so that Rb trap depth is fixed at 1 mK: if species == Cs.X: Powers = abs(1e-3*kB * np.pi * eps0 * c * beamwaist**2 / Cs6S.polarisability(wavels)) # in Watts else: Powers = abs(1e-3*kB * np.pi * eps0 * c * beamwaist**2 / Rb5S.polarisability(wavels)) # in Watts _, ax1 = plt.subplots() ax1.set_title('Fixing the trap depth of ground state '+species+' at 1 mK') ax1.set_xlabel('Wavelength (nm)') ax1.plot(wavels*1e9, Powers*1e3, color='tab:blue') ax1.set_ylabel('Power (mW)', color='tab:blue') ax1.tick_params(axis='y', labelcolor='tab:blue') ax1.set_xlim(wavels[0]*1e9, wavels[-1]*1e9) # ax1.set_ylim(min(Powers)*1e3-0.5, 15) ax2 = ax1.twinx() # now the power and the wavelength are varied: Llabels = ['$S_{1/2}$', '$P_{3/2}$'] if species == Cs.X: colors = ['k', 'tab:orange', 'tab:orange', 'tab:orange'] linestyles = ['--', '-.', '-', ':'] else: colors = ['tab:orange', 'tab:orange', 'k', 'tab:orange'] linestyles = ['-', '-.', '--', ':'] trapdepths = [] for obj in [Cs6S, Cs6P, Rb5S, Rb5P]: res = np.zeros(len(Powers)) for i in range(len(Powers)): obj.field.E0 = 2 * np.sqrt(Powers[i] / eps0 / c / np.pi)/beamwaist # average mj states (doesn't have any effect on j=1/2 states) res[i] = 0.5*(obj.acStarkShift(0,0,0, wavels[i], mj=1.5) + obj.acStarkShift(0,0,0, wavels[i], mj=0.5)) color = colors.pop(0) ls = linestyles.pop(0) ax2.plot(wavels*1e9, res*1e3/kB, color=color, label=obj.X+" "+Llabels[obj.L], linestyle=ls) trapdepths.append(res) ax2.plot(wavels*1e9, np.zeros(len(wavels)), 'k', alpha=0.1) # show zero crossing ax2.set_ylabel('Trap Depth (mK)', color='tab:orange') ax2.legend() ax2.set_ylim(-3, 3) ax2.tick_params(axis='y', labelcolor='tab:orange') plt.tight_layout() I = 2*Powers / np.pi / beamwaist**2 # scattering rate of Cs from the D2 line: deltaCsD1 = 2*np.pi*c * (1/wavels - 1/Cs.rwS[0]) # detuning from D1 (rad/s) deltaCsD2 = 2*np.pi*c * (1/wavels - 1/Cs.rwS[35]) # detuning from D2 (rad/s) IsatCsD1 = 2.4981 *1e-3 *1e4 # saturation intensity for D1 transition, sigma polarised IsatCsD2 = 1.1023 *1e-3 *1e4 # saturation intensity for D2 transition, pi polarised CsRsc = 0 for vals in [[Cs.lwS[0], deltaCsD1, IsatCsD1], [Cs.lwS[35], deltaCsD2, IsatCsD2]]: CsRsc += vals[0]/2. * I/vals[2] / (1 + 4*(vals[1]/vals[0])**2 + I/vals[2]) # Cstau = 1e-3*kB / (hbar*(2*np.pi/wavels))**2 * 2.*Cs.m / CsRsc # the lifetime is the trap depth / recoil energy / scattering rate Cst = 4*np.sqrt(Cs.m*abs(trapdepths[0])) / (2*np.pi/wavels)**2 /hbar /beamwaist /CsRsc # duration in vibrational ground state (s) = 1/Lamb-Dicke^2 /Rsc # scattering rate of Rb from the D1 line: deltaRbD1 = 2*np.pi*c * (1/wavels - 1/Rb.rwS[0]) # detuning from D1 (rad/s) IsatRbD1 = 4.484 *1e-3 *1e4 # saturation intensity for D1 transition, pi polarised RbRsc = Rb.lwS[0]/2. * I/IsatRbD1 / (1 + 4*(deltaRbD1/Rb.lwS[0])**2 + I/IsatRbD1) # per second # Rbtau = 1e-3*kB / (hbar*(2*np.pi/wavels))**2 * 2.*Rb.m / RbRsc # the lifetime is the trap depth / recoil energy / scattering rate Rbt = 4*np.sqrt(Rb.m*abs(trapdepths[2])) / (2*np.pi/wavels)**2 /hbar /beamwaist /RbRsc # duration in vibrational ground state (s) = 1/Lamb-Dicke^2 /Rsc # plot lifetime and scattering rate on the same axis: for Rsc, ts, X in [[RbRsc, Rbt, Rb.X], [CsRsc, Cst, Cs.X]]: fig, ax3 = plt.subplots() ax3.set_title('Scattering rate and lifetime of ground state '+X+' in a 1 mK trap (for '+species+')') ax3.set_xlabel('Wavelength (nm)') ax3.semilogy(wavels*1e9, Rsc, color='tab:blue') ax3.plot(wavels*1e9, np.zeros(len(wavels))+100, '--', color='tab:blue', alpha=0.25) # show acceptable region ax3.set_ylabel('Scattering rate ($s^{-1}$)', color='tab:blue') ax3.tick_params(axis='y', labelcolor='tab:blue') ax3.set_xlim(wavels[0]*1e9, wavels[-1]*1e9) ax3.set_ylim(1, 1e5) ax4 = ax3.twinx() ax4.semilogy(wavels*1e9, ts, color='tab:orange') ax4.plot(wavels*1e9, np.ones(len(wavels))/2., '--', color='tab:orange', alpha=0.25) # show acceptable region ax4.set_ylabel('Time in the vibrational ground state (s)', color='tab:orange') ax4.tick_params(axis='y', labelcolor='tab:orange') ax4.set_ylim(0.001,10) plt.tight_layout() plt.show()
# ax[0].legend(lines, [l.get_label() for l in lines], ncol=2, fontsize=11) plt.subplots_adjust(left=0.17, right=0.95, top=0.93, bottom=0.13) ax[0][1].legend() ax[0][0].set_title('Rb Trap Depth 1 mK') ax[0][1].set_title('Cs Trap Depth 1 mK') plt.show() if __name__ == "__main__": wavelength = 1064e-9 # wavelength in m power = 6e-3 # beam power in W beamwaist = 1e-6 # beam waist in m bprop = [wavelength, power, beamwaist] Rb5P1 = dipole(Rb, (1, 1 / 2., 1, 1), bprop) Rb5P3 = dipole(Rb, (1, 3 / 2., 1, 1), bprop) # print(getStarkShift(Rb5P1)) # print(getStarkShift(Rb5P3)) # print(np.array(Rb5P3.polarisability(795e-9, HF=True, split=True))/au) # combinedTrap(power=6e-3) # getMFStarkShifts() # plotPolarisability() plotScatRate() # compare Kien 2013 Fig 4,5: # wls = [np.linspace(680, 690, 200)*1e-9, np.linspace(930, 940, 200)*1e-9] # ylims = [(-1200, 300), (-3000, 6000)] # for ii in range(2):
import matplotlib.pyplot as plt import sys sys.path.append(r'Y:\Tweezer\Code\Python 3.5\polarisability') sys.path.append(r'Z:\Tweezer\Code\Python 3.5\polarisability') from AtomFieldInt_V3 import dipole, atom, c, eps0, h, hbar, a0, e, me, kB, amu, Eh, au Rb = atom(atm='Rb87') Cs = atom(atm='Cs133') # from scipy.constants import physical_constants # muB = physical_constants['Bohr magneton'] wavelength = 1064e-9 # wavelength in m power = 5e-3 # beam power in W waist = 1.2e-6 # beam waist of tweezer in m ehat = (2**(-0.5), 1j * 2**(-0.5), 0) # E field circular polarisation # create dipole objects for ground state Rb / Cs bprop = [wavelength, power, waist, ehat] Rb5S = dipole(Rb, (0, 1 / 2., 1, 1), bprop) # Rb5S.gJ = 2.00233113 # Fine structure Lande g-factor (from Steck) Cs6S = dipole(Cs, (0, 1 / 2., 3, 3), bprop) # Cs6S.gJ = 2.00254032 # Fine structure Lande g-factor (from Steck) def get_sep(atom=Rb5S, wl=wavelength): """Calculate the displacement of the trap centre due to the fictitious field""" aS, aV, aT = atom.polarisability( wl, split=True, HF=True) # vector polarisability for |F,MF> return aV / aS * atom.MF / atom.F * wl / 4. / np.pi # displacement of potential min.
Fs, occs = np.unique(states[:, 0], return_counts=True) # F states if not weights: # probability of being in each MF state weights = np.concatenate([np.ones(o) / o for o in occs]) # equal distribution weighted_shift = shifts * weights aveShifts = [np.sum(weighted_shift[np.where(Fs == F)]) for F in Fs] # average return aveShifts if __name__ == "__main__": # calculate the stark shifts for trap depths 0 - 2 mK beamwaist = 1.2e-6 # beam waist of tweezer in m wavelength = 1064e-9 # wavelength of tweezer beam in m # make an object to calculate the groundstate polarisability G = dipole(Rb, (0, 1 / 2., 1, 1), [wavelength, 1e-3, beamwaist]) powers = abs( np.linspace(0, 2, 200) * 1e-3 * kB / G.polarisability(wavelength) * np.pi * eps0 * c * beamwaist**2) shifts = np.zeros((len(powers), 2)) # AC Stark shifts in MHz for i in range(len(powers)): mfstates, mfshifts = getMFStarkShifts(wavelength, powers[i], beamwaist) shifts[i] = aveShift(mfstates, mfshifts) plt.figure() ax1 = plt.gca() ax2 = ax1.twiny() plt.title('Averaging over the hyperfine transitions of Rb D2 line') ax1.plot(powers * 1e3, shifts[:, 0], label="F=1 $\rightarrow$ F'=2") ax1.plot(powers * 1e3, shifts[:, 1], label="F=2 $\rightarrow$ F'=3")