Quantum mechanics and nuclear transitions

Nexus provides a couple of functions to calculate basic quantum mechanical and nuclear parameters. Here a few basic functionalities are shown.

Quantum mechanics

Clebsh-Gordon coefficients

import nexus as nx

print(nx.ClebshGordon(1/2, 1, -1/2, 1, 3/2, 1/2))

0.5773502691896257.

Three J Symbols

import nexus as nx

print(nx.ThreeJSymbol(1/2, 1, 3/2, -1/2, 1, -1/2))

0.28867513459481287.

V coefficient

import nexus as nx

print(nx.VCoefficient(1/2, 1, 3/2, -1/2, 1, -1/2))

0.28867513459481287.

Wigner matrices

import nexus as nx

print(nx.SmallWignerDmatrix(1, 1, 1, nx.pi/2.5))

print(nx.WignerDmatrix(1, 1, 1, nx.pi/2.5, nx.pi/1.5, nx.pi/2))

0.654508497187474

(-0.23776412907378872-0.07725424859373696j)

Vector Spherical Harmonics

These functions calculate the vector spherical harmonics in the polarization base of \(\sigma\) and \(\pi\) polarization for a rotation of the quantization axis by some Euler angles. They return a list of size \(2*L+1\), where \(L\) is the photon angular momentum of the transition. Each entry has a sigma and a pi component

import nexus as nx

# E1 transition, L=1, lambda=1
# obtain 2*L+1 vector components
VSH = nx.VecSpherHarmPolarization(1,1)
print(VSH[0].sigma) # l = -1
print(VSH[0].pi)
print(VSH[1].sigma) # l = 0
print(VSH[1].pi)
print(VSH[2].sigma) # l = +1
print(VSH[2].pi)

output is

(Vector Spherical Harmonics in polarization base - sigma: (-0.24430125595145996-0j) - pi 0.24430125595145996j, Vector Spherical Harmonics in polarization base - sigma: (-0-0j) - pi -0j, Vector Spherical Harmonics in polarization base - sigma: (-0.24430125595145996-0j) - pi -0.24430125595145996j)
(-0.24430125595145996-0j)
0.24430125595145996j
(-0-0j)
-0j
(-0.24430125595145996-0j)
-0.24430125595145996j
# with Euler angles
euler = nx.Eulerangles(nx.pi/2, nx.pi/2, nx.pi/2)

vsh = nx.VecSpherHarmPolarization(1,0,euler)

print(vsh)

print(vsh[0].sigma)
print(vsh[0].pi)

print(vsh[1].sigma)
print(vsh[1].pi)

print(vsh[2].sigma)
print(vsh[2].pi)

output is

(Vector Spherical Harmonics in polarization base - sigma: (2.712288793021544e-17-1.4959137556431694e-17j) - pi (-4.487741266929507e-17-0.24430125595145996j), Vector Spherical Harmonics in polarization base - sigma: (-2.1155415213710417e-17-0.34549414947133555j) - pi 2.1155415213710417e-17j, Vector Spherical Harmonics in polarization base - sigma: (2.712288793021544e-17+1.4959137556431687e-17j) - pi (-1.4959137556431694e-17+0.24430125595145996j))
(2.712288793021544e-17-1.4959137556431694e-17j)
(-4.487741266929507e-17-0.24430125595145996j)
(-2.1155415213710417e-17-0.34549414947133555j)
2.1155415213710417e-17j
(2.712288793021544e-17+1.4959137556431687e-17j)
(-1.4959137556431694e-17+0.24430125595145996j)

Nuclear transitions

Nexus also provides functions to directly calculate the nuclear Hamiltonians and the nuclear transitions.

In order to do so, you need to specify a set of hyperfine parameters via the BareHyperfine class. This class does not support any distributions but you can specify the isotropic parameter.

import nexus as nx

hyperfine = nx.BareHyperfine(magnetic_field = 33,
                             isotropic = False)

This class is then passed to the function to calculate nuclear transition properties.

Hamiltonian

The ground and excited state Hamiltonians can be directly calculated. The isotropic parameter has no influence on the Hamiltonian.

With a spin of \(J\) one obtains a square matrix of dimension \(2J+1\). The matrix elements range from \(-J,...,J\).

# returns the ground state Hamiltonian
hamiltonian = nx.HamiltonianGroundState(hyperfine, nx.lib.moessbauer.Fe57)
print(hamiltonian)

# returns the excited state Hamiltonian
hamiltonian = nx.HamiltonianExcitedState(hyperfine, nx.lib.moessbauer.Fe57)
print(hamiltonian)

and the output is

[[ 20.20721718+0.j   0.        -0.j]
 [  0.        +0.j -20.20721718+0.j]]

[[-34.61800398+0.j   0.        -0.j   0.        -0.j   0.        -0.j]
 [  0.        +0.j -11.53933466+0.j   0.        -0.j   0.        -0.j]
 [  0.        +0.j   0.        +0.j  11.53933466+0.j   0.        -0.j]
 [  0.        +0.j   0.        +0.j   0.        +0.j  34.61800398+0.j]]

The matrix entries give the detuning in units of the linewidth \(\Gamma\) for the different spin states in spin basis with quantization axis along the k-vector.

Because the magnetic field points along the quantization axis, the Hamiltonian is already diagonal. We can directly read the energy detuning for the different spin configurations. In the ground state the \(m=-1/2\) state is shifted by \(20.2 \Gamma\) and the \(m=1/2\) state by \(-20.2 \Gamma\). For the excited state the shifts are: \(m=-3/2\) by \(-34.6 \Gamma\), \(m=-1/2\) by \(-11.5 \Gamma\), \(m=1/2\) by \(11.5 \Gamma\), and \(m=3/2\) by \(34.6 \Gamma\).

If the matrix is not diagonal, the situation is a bit more complicated

hyperfine = nx.BareHyperfine(
  magnetic_field = 33,
  magnetic_theta = nx.DegToRad(90))

hamiltonian = nx.HamiltonianGroundState(hyperfine, nx.lib.moessbauer.Fe57)
print(hamiltonian)

hamiltonian = nx.HamiltonianExcitedState(hyperfine, nx.lib.moessbauer.Fe57)
print(hamiltonian)

to obtain

[[ 20.19962365+0.j   0.55392294-0.j]
 [  0.55392294+0.j -20.19962365+0.j]]

[[-34.60499512+0.j  -0.54787847-0.j   0.        -0.j   0.        -0.j]
 [ -0.54787847+0.j -11.53499837+0.j  -0.63263557-0.j   0.        -0.j]
 [  0.        +0.j  -0.63263557+0.j  11.53499837+0.j  -0.54787847-0.j]
 [  0.        +0.j   0.        +0.j  -0.54787847+0.j  34.60499512+0.j]]

these matrices have to be diagonalized.

Diagonalization

To diagonalize a Hermitian matrix use the DiagonalizeHermitian() function.

import nexus as nx

hyperfine = nx.BareHyperfine(
  magnetic_field = 33,
  magnetic_theta = nx.DegToRad(90))

hamiltonian = nx.HamiltonianGroundState(hyperfine, nx.lib.moessbauer.Fe57)

eigen_system = nx.DiagonalizeHermitian(hamiltonian)

It will return an Eigensystem class object which holds the eigenvectors and the eigenvalues.

# list of eigenvalues
print(eigen_system.eigenvalues)

# list of corresponding eigenvectors
for vector in eigen_system.eigenvectors:
  print(vector)

with the output

[[-34.61800398]
 [-11.53933466]
 [ 11.53933466]
 [ 34.61800398]]

[-9.99718176e-01+0.j -2.37373737e-02-0.j  3.25407171e-04+0.j
  2.57549638e-06-0.j]
[-2.37373737e-02+0.j  9.99342428e-01-0.j -2.74069827e-02+0.j
 -3.25407171e-04-0.j]
[-3.25407171e-04+0.j  2.74069827e-02-0.j  9.99342428e-01+0.j
  2.37373737e-02-0.j]
[-2.57549638e-06+0.j  3.25407171e-04-0.j  2.37373737e-02+0.j
 -9.99718176e-01-0.j]

So we obtain four transitions with the same eigenvalues (energy detunings) as in the previously already diagonal case.

Hyperfine Transitions

To obtain the transitions under the action of hyperfine interactions you can use the function HyperfineTransitions().

The function will return a Transitions class object. It is a vector of Transition objects. Each Transition object has the attributes

  • energy_detuning: Energy detuning from the unsplit nuclear transition energy in units of linewidth.

  • transition_polarisation_matrix: Polarization dependent 2x2 complex transition matrix.

  • weight: Relative weight of the transition in a material.

We will calculate all transitions of the hyperfine site

import nexus as nx

hyperfine = nx.BareHyperfine(
   weight = 1,
   magnetic_field = 33,
   magnetic_theta = nx.DegToRad(90))

# returns a Transitions object
nuclear_transitions = nx.HyperfineTransitions(hyperfine, nx.lib.moessbauer.Fe57)

# a single transition
print(nuclear_transitions[0])

# energy detuning in units of Gamma
print("\ndetuning {}".format(nuclear_transitions[0].energy_detuning))

# a 2x2 matrix with the polarization components
print("\npolarisation matrix\n{}".format(nuclear_transitions[0].transition_polarisation_matrix))

# number of all transitions in the nucleus
print("\nnumber of transitions: {}".format(len(nuclear_transitions)))

# all transitions
for trans in nuclear_transitions:
  print(trans.energy_detuning)

and we get

weight = 1.0
energy_detuning = 8.667882519568264
transition_polarisation_matrix:
[[ 0.125     +0.j         -0.        +0.12495303j]
 [-0.        -0.12495303j  0.12490607+0.j        ]]

detuning 8.667882519568264

polarisation matrix
[[ 0.125     +0.j         -0.        +0.12495303j]
 [-0.        -0.12495303j  0.12490607+0.j        ]]

number of transitions: 6
8.667882519568264
31.746551839648678
54.82522115972908
-54.82522115972908
-31.74655183964868
-8.66788251956827

Please have a look at the API Reference for more information.