# -*- coding: utf-8 -*-
"""
Created on Thu Aug 10 12:43:11 2017
@author: spe
"""
import scipy.constants as cts
import numpy as np
from numpy import pi
[docs]class state():
"""
The quantum state and its parameters for an atom.
Parameters
----------
n : integer
Principal quantum number of the state.
S : integer or float
Total spin angular momentum of the state.
L : integer or float
Total orbital angular momentum of the state.
J : integer or float
Total electronic angular momentum of the state.
lam : float, optional
Wavelength, in meters, of the photon necessary to excite the state
from the ground state. electronic angular momentum of the state.
E : float, optional
Energy of the state above the ground state in :math:`\\text{cm}^{-1}`.
tau : float, optioanl
Lifetime of the state in s. If not specified, it is assumed to
be infinite (the ground state).
gJ : float
Total angular momentum Lande g-factor.
Ahfs : float
A hyperfine coefficient.
Bhfs : float
B hyperfine coefficient.
Chfs : float
C hyperfine coefficient.
Attributes
----------
gamma : float
Lifetime in :math:`\\text{s}^{-1}`
gammaHz : float
Corresponding linewidth in Hz, given by :math:`\gamma/2\pi`.
energy : float
The energy in :math:`\\text{cm}^{-1}`
Notes
-----
All the parameters passed to the class on creation are stored as attrributes,
with the exception of `lam` and `E`, one of which defines the stored
attribute `energy`. One of these two optional variable must be specified.
This construction of the state assumes L-S coupling.
"""
def __init__(self, n=None, S=None, L=None, J=None, lam=None, E=None,
tau=np.inf, gJ=1, Ahfs=0, Bhfs=0, Chfs=0):
self.n = n
self.L = L
self.S = S
self.J = J
self.gJ = gJ
if lam:
self.energy = 0.01/lam # cm^-1
elif E:
self.energy = E
else:
raise ValueError("Need to specify energy of the state somehow.")
self.tau = tau # s
self.gamma = 1/self.tau # s^{-1}
self.gammaHz = self.gamma/2/pi # Hz
self.Ahfs = Ahfs
self.Bhfs = Bhfs
self.Chfs = Chfs
[docs]class transition():
"""
Reference numbers for transitions.
Parameters
----------
state1 : pylcp.atom.state
The lower state of the transition.
state2 : pylcp.atom.state
The upper state of the transition.
mass : float
Mass of the atom in kg
Attributes
----------
k : float
Wavevector in :math:`\\text{cm}^{-1}`.
lam : float
Wavelength in m.
nu : float
Frequency in Hz of the transition.
omega : float
Angular frequency in rad/s of the transition.
Isat : float
Saturation intensity of the transition in :math:`\\text{mW/cm}^2`.
a0 : float
Maximum acceleration :math:`a_0 = \hbar k/2\Gamma` in :math:`\\text{cm/s}^2`.
v0 : float
Doppler velocity :math:`v_0 = k/\Gamma` in cm/s.
x0 : float
Length scale :math:`x_0 = v_0^2/a_0` in cm.
t0 : float
Time scale :math:`t_0 = v_0/a_0` in s.
"""
def __init__(self, state1, state2, mass):
self.k = state2.energy - state1.energy # cm^{-1}
self.lam = 0.01/self.k # m
self.nu = cts.c/self.lam # Hz
self.omega = 2*np.pi*self.nu
# Typical definition from Fermi's Golden rule:
self.Isat = cts.hbar*self.omega**3*state2.gamma/(12*np.pi*cts.c**2) # W/m^2
self.Isat *= 1000/1e4
# Maximum acceleration on this transition:
self.a0 = cts.hbar*(2*np.pi*100*self.k)*state2.gamma/2/mass # cm/s^2 ->
self.v0 = state2.gamma/(2*np.pi*100*self.k) # cm/s
self.x0 = self.v0**2/self.a0
self.t0 = self.v0/self.a0
# Save B gamma:
self.Bgamma = state2.gammaHz/cts.value('Bohr magneton in Hz/T')/1e-4
[docs]class atom():
"""
A class containing reference data for select laser-coolable alkali atoms
Parameters
----------
species : string
The isotope number and species of alkali atom. For lithium-7,
species can be eiter "7Li" or "Li7", for example. Supported species
are "6Li", "7Li", "23Na", "39K", "40K", "41K", "85Rb", "87Rb",
and "133Cs".
Attributes
----------
I : float
Nuclear spin of the isoptope
gI : float
Nuclear g-factor of the isotope. Note that the nuclear g-factor
is specified relative to the Bohr magneton, not the nuclear
magneton.
mass : float
Mass, in kg, of the atom.
states : list of pylcp.atom.state
States of the atom useful for laser cooling, in order of increasing
energy.
transitions : list of pylcp.atom.transition
Transitions in the atom useful for laser cooling. All transitions
are from the ground state.
"""
def __init__(self, species):
# Prepare to add in some useful electronic states:
self.state = []
if species == "6Li" or species == "Li6":
self.I = 1 # nuclear spin
self.gI = -0.0004476540 # nuclear magnetic moment
self.mass = 6.0151214*cts.value('atomic mass constant') # kg
# TODO: FIX all of these numbers so they are actually lithium 6:
# Ground state:
self.state.append(state(n=2, L=0, S=1/2, J=1/2, lam=np.inf,
tau=np.inf, gJ=-2.0023010,
Ahfs=152.1368407e6))
# D1 line (2P_{1/2})
self.state.append(state(n=2, L=1, S=1/2, J=1/2,
lam=670.976658173e-9, tau=27.109e-9,
gJ=-0.6668, Ahfs=17.375e6))
# D2 line (2P_{3/2})
self.state.append(state(n=2, L=1, S=1/2, J=3/2,
lam=670.961560887e-9, tau=27.102e-9,
gJ=-1.335, Ahfs=-1.155e6, Bhfs=-0.40e6))
elif species == "7Li" or species == "Li7":
self.I = 3/2 # nuclear spin
self.gI = -0.0011822130 # nuclear magnetic moment
self.mass = 7.0160045*cts.value('atomic mass constant') # kg
# Ground state:
self.state.append(state(n=2, L=0, J=1/2, lam=np.inf, tau=np.inf,
gJ=2.0023010, Ahfs=401.7520433e6, S=1/2))
# D1 line (2P_{1/2})
self.state.append(state(n=2, L=1, J=1/2, lam=670.976658173e-9,
tau=27.109e-9, gJ=0.6668, Ahfs=45.914e6,
S=1/2))
# D2 line (2P_{3/2})
self.state.append(state(n=2, L=1, J=3/2, lam=670.961560887e-9,
tau=27.102e-9, gJ=1.335, Ahfs=-3.055e6,
Bhfs=-0.221e6, S=1/2))
# 3P_{1/2}
self.state.append(state(n=3, L=1, J=1/2, lam=323.3590e-9,
tau=998.4e-9, gJ=2/3, Ahfs=13.5e6, S=1/2))
# 3P_{1/2}
self.state.append(state(n=3, L=1, J=3/2, lam=323.3590e-9,
tau=998.4e-9, gJ=4/3, Ahfs=-0.965e6,
Bhfs=-0.019e6, S=1/2))
elif species == "23Na" or species == "Na23":
self.I = 3/2 # nuclear spin
self.gI = -0.00080461080 # nuclear magnetic moment
self.mass = 22.9897692807*cts.value('atomic mass constant') # kg
# Ground state:
self.state.append(state(n=3, L=0, J=1/2, lam=np.inf, tau=np.inf,
gJ=2.00229600, Ahfs=885.81306440e6, S=1/2))
# D1 line (2P_{1/2})
self.state.append(state(n=3, L=1, J=1/2, lam=589.7558147e-9,
tau=16.299e-9, gJ=0.66581, Ahfs=94.44e6,
S=1/2))
# D2 line (2P_{3/2})
self.state.append(state(n=3, L=1, J=3/2, lam=589.1583264e-9,
tau=16.2492e-9, gJ=1.33420, Ahfs=18.534e6,
Bhfs=2.724e6, S=1/2))
elif species == "39K" or species == "K39":
self.I = 3/2 # nuclear spin
self.gI = -0.00014193489 # nuclear magnetic moment
self.mass = 38.96370668*cts.value('atomic mass constant')
# Ground state:
self.state.append(state(n=4, L=0, J=1/2, lam=np.inf, tau=np.inf,
gJ=2.00229421, Ahfs=230.8598601e6,
S=1/2))
# D1 line (6P_{1/2})
self.state.append(state(n=4, L=1, J=1/2, lam=770.108385049e-9,
tau=26.72e-9, gJ=2/3, Ahfs=27.775e6,
S=1/2))
# D2 line (6P_{3/2})
self.state.append(state(n=4, L=1, J=3/2, lam=766.700921822e-9,
tau=26.37e-9, gJ=4/3, Ahfs=6.093e6,
Bhfs=2.786e6, S=1/2))
elif species == "40K" or species == "K40":
self.I = 4 # nuclear spin
self.gI = 0.000176490 # nuclear magnetic moment
self.mass = 39.96399848*cts.value('atomic mass constant')
# Ground state:
self.state.append(state(n=4, L=0, J=1/2, lam=np.inf, tau=np.inf,
gJ=2.00229421, Ahfs=-285.7308e6,
S=1/2))
# D1 line (6P_{1/2})
self.state.append(state(n=4, L=1, J=1/2, lam=770.108136507e-9,
tau=26.72e-9, gJ=2/3, Ahfs=-34.523e6,
S=1/2))
# D2 line (6P_{3/2})
self.state.append(state(n=4, L=1, J=3/2, lam=766.700674872e-9,
tau=26.37e-9, gJ=4/3, Ahfs=-7.585e6,
Bhfs=-3.445e6, S=1/2))
elif species == "41K" or species == "K41":
self.I = 3/2 # nuclear spin
self.gI = -0.00007790600 # nuclear magnetic moment
self.mass = 40.96182576*cts.value('atomic mass constant')
# Ground state:
self.state.append(state(n=4, L=0, J=1/2, lam=np.inf, tau=np.inf,
gJ=2.00229421, Ahfs=127.0069352e6,
S=1/2))
# D1 line (6P_{1/2})
self.state.append(state(n=4, L=1, J=1/2, lam=770.107919192e-9,
tau=26.72e-9, gJ=2/3, Ahfs=15.245e6,
S=1/2))
# D2 line (6P_{3/2})
self.state.append(state(n=4, L=1, J=3/2, lam=766.70045870e-9,
tau=26.37e-9, gJ=4/3, Ahfs=3.363e6,
Bhfs=3.351e6, S=1/2))
elif species == "85Rb" or species == "Rb85":
self.I = 5/2 # nuclear spin
self.gI = -0.00029364000 # nuclear magnetic moment
self.mass = 84.911789732*cts.value('atomic mass constant')
# Ground state:
self.state.append(state(n=5, L=0, J=1/2, lam=np.inf, tau=np.inf,
gJ=2.0023010, Ahfs=1.0119108130e9, S=1/2))
# D1 line (2P_{1/2})
self.state.append(state(n=5, L=1, J=1/2, lam=780.241e-9,
tau=27.679e-9, gJ=0.6668, Ahfs=120.527e6,
S=1/2))
# D2 line (2P_{1/2})
self.state.append(state(n=5, L=1, J=3/2, lam=780.241e-9,
tau=26.2348e-9, gJ=1.335, Ahfs=25.0020e6,
Bhfs=25.79e6, S=1/2))
elif species == "87Rb" or species == "Rb87":
self.I = 3/2 # nuclear spin
self.gI = -0.0009951414 # nuclear magnetic moment
self.mass = 86.909180527*cts.value('atomic mass constant')
# Ground state:
self.state.append(state(n=5, L=0, J=1/2, lam=np.inf, tau=np.inf,
gJ=2.00233113, Ahfs=3.417341305452145e9,
S=1/2))
# D1 line (5P_{1/2})
self.state.append(state(n=5, L=1, J=1/2, lam=794.978851156e-9,
tau=27.679e-9, gJ=0.666, Ahfs=407.24e6,
S=1/2))
# D2 line (5P_{3/2})
self.state.append(state(n=5, L=1, J=3/2, lam=780.241209686e-9,
tau=26.2348e-9, gJ=1.3362, Ahfs=84.7185e6,
Bhfs=12.4965e6, S=1/2))
elif species == "133Cs" or species == "Cs133":
self.I = 7/2 # nuclear spin
self.gI = -0.00039885395 # nuclear magnetic moment
self.mass = 132.905451931*cts.value('atomic mass constant')
# Ground state:
self.state.append(state(n=6, L=0, J=1/2, lam=np.inf, tau=np.inf,
gJ=2.00254032, Ahfs=2.2981579425e9,
S=1/2))
# D1 line (6P_{1/2})
self.state.append(state(n=6, L=1, J=1/2, lam=894.59295986e-9,
tau=34.791e-9, gJ=0.665900, Ahfs=291.9201e6,
S=1/2))
# D2 line (6P_{3/2})
self.state.append(state(n=6, L=1, J=3/2, lam=852.34727582e-9,
tau=30.405e-9, gJ=1.33400, Ahfs=50.28827e6,
Bhfs=-0.4934e6, Chfs=0.560e3, S=1/2))
else:
raise ValueError("Atom {0:s} not recognized.".format(species))
# Take the states and make transitions:
self.__make_transitions()
def __sort_states(self):
"""
Sorts the states by energy.
"""
# TODO: implement
pass
def __make_transitions(self):
"""
Take subtractions of energies to generate transitions from ground
state
"""
self.transition = []
for ii, state_i in enumerate(self.state):
if ii > 0:
self.transition.append(transition(self.state[0], state_i,
self.mass))