Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of Black-body radiation shift to atomic state #172

Merged
merged 4 commits into from
Aug 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions arc/alkali_atom_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,111 @@ def updateDipoleMatrixElementsFile(self):
)
print(e)

def getFarleyWing(self, n1, l1, j1, n2, l2, j2, temperature=0.0):
"""
Calculates the Farley Wing function in the context of a BBR shift, uses a closed
form for the integral (which has a singularity, need Cauchy principal value)

References:
(Farley, John W., and William H. Wing. Physical Review A 23.5 (1981): 2397
doi = {10.1103/PhysRevA.23.2397}

(A.A. Kamenski et al 2019 Quantum Electron. 49 464, DOI:10.1070/QEL17000 )

"""
if temperature == 0:
temperature = 1e-10 ###avoid zero error

transition_frequency = self.getTransitionFrequency(n1, l1, j1, n2, l2, j2)
y = scipy.constants.h * transition_frequency / (scipy.constants.Boltzmann * temperature)


z = 1j * y
a = 0.5 * (np.log(z / (2 * np.pi)) - np.pi / z - mpmath.digamma(z / (2 * np.pi)))
return float(-(np.pi**2) * y / 3 - 2 * y**3 * mpmath.re(a))

def getBBRshift(self, n, l, j, includeLevelsUpTo=0, temperature=0.0, s=0.5):
"""
Frequency shift of an atomic state induced by black-body radiation
using the Farley-Wing function.
Uses getFarleyWing as part of the calculation.

n, l, j (int,int,float): specifies state whose shift we are
calculating
temperature : optional. Temperature at which the atom
environment is, measured in K. If this parameter
is non-zero, user has to specify transitions up to
which state (due to black-body decay) should be included
in calculation.
includeLevelsUpTo (int): optional and not needed for atom
lifetimes calculated at zero temperature. At non zero
temperatures, this specify maximum principal quantum number
of the state to which black-body induced transitions will
be included. Minimal value of the parameter in that case is
:math:`n+1`

Returns:
float:
Energy shift in units of frequency (Hz)

See also:
:obj:`getFarleyWing` which is used in calculation.

References:
(Farley, John W., and William H. Wing. Physical Review A 23.5 (1981): 2397
doi = {10.1103/PhysRevA.23.2397}
)

"""

n = int(n)
l = int(l)

DeltaE = 0

factor = (-(physical_constants["Bohr radius"][0] * scipy.constants.e) ** 2 /
(6 * scipy.constants.epsilon_0 * np.pi ** 2 * scipy.constants.c ** 3) *
(scipy.constants.Boltzmann * temperature / scipy.constants.hbar) ** 3 /
scipy.constants.h)

# Precompute commonly used values
max_ground_state_n = max(self.groundStateN, l)

def compute_deltaE(n, l, j, nto, lto, jto):
prefactor = (2*jto + 1)*Wigner6j(l,j,s,jto,lto,1)**2
radial_matrix_element = self.getRadialMatrixElement(n, l, j, nto, lto, jto)
farley_wing = self.getFarleyWing(n, l, j, nto, lto, jto, temperature)
max_l = max(l, lto)
return prefactor*(max_l) * (radial_matrix_element ** 2) * farley_wing

# Sum over all l-1
if l > 0:
lto = l - 1
for nto in range(max_ground_state_n, includeLevelsUpTo + 1):
if lto > j - s - 0.1:
jto = j
DeltaE += compute_deltaE(n, l, j, nto, lto, jto)
jto = j - 1.0
if jto > 0:
DeltaE += compute_deltaE(n, l, j, nto, lto, jto)

# Sum over all l+1
lto = l + 1
for nto in range(max(self.groundStateN, l + 2), includeLevelsUpTo + 1):
if lto - s - 0.1 < j:
jto = j
DeltaE += compute_deltaE(n, l, j, nto, lto, jto)
jto = j + 1

DeltaE += compute_deltaE(n, l, j, nto, lto, jto)

# Sum over additional states
for state in self.extraLevels:
if (abs(j - state[2]) < 1.1 and abs(state[1] - l) < 1.1 and abs(state[1] - l) > 0.9):
DeltaE += compute_deltaE(n, l, j, state[0], state[1], state[2])

return factor * DeltaE

def getTransitionRate(self, n1, l1, j1, n2, l2, j2, temperature=0.0, s=0.5):
"""
Transition rate due to coupling to vacuum modes
Expand Down
Loading