This page was generated from the Jupyter notebook angular_state.ipynb.

Using AngularKets and AngularStates in different spin coupling schemes

We define two kind of objets:

  • AngularKet objects represent canonical ketstates in a given coupling scheme. For each coupling scheme, the AngularKet objects form a complete orthonormal basis. These objects are immutable and hashable.

  • AngularState objects represent a statevector, which is defined by a coefficient vector and a list of AngularKet objects, which must all be of the same coupling scheme.

[ ]:
from rydstate.angular import AngularKetFJ, AngularKetJJ, AngularKetLS

For AngularKets we always store the following basic angular momentum quantum numbers (qn):

  • the nuclear spin qn i_c (0 if no hyperfine splitting should be considered)

  • the core electron spin qn s_c (0 for Alkali atoms, 1/2 for Alkaline earth atoms)

  • the core electron orbital qn l_c (0 by default)

  • the Rydberg electron spin qn s_r = 0.5 and

  • the Rydberg electron orbital qn l_r.

As well as the total combined qn:

  • the total atom angular momentum qn f_tot

  • Optionally: the magnetic quantum number m, which is the projection of f_tot onto the quantization axis.

These basic angular momentum qns can couple via different coupling schemes to the total atom angular momentum f_tot. The different coupling schemes define in addition the following quantum numbers:

  • AngularKetLS:

    • the total orbital momentum (l_c, l_r)l_tot,

    • the total spin (s_c, s_r)s_tot, and

    • the total angular momentum (l_tot, s_tot)j_tot

  • AngularKetJJ:

    • the angular momentum of the core electron (l_c, s_c)j_c,

    • the angular momentum of the Rydberg electron (s_r, l_r)j_r, and

    • the total angular momentum (j_c, j_r)j_tot

  • AngularKetFJ:

    • the angular momentum of the core electron (l_c, s_c)j_c,

    • the angular momentum of the Rydberg electron (s_r, l_r)j_r, and

    • the total spin momentum of the core electron (j_c, i_c)f_c

Note the notation (a, b)c means that the angular momenta a and b couple to the combined angular momentum c.

To create an angular ket, you can simply call the respective class and specify the needed quantum numbers. Note, that you only have to specify as many quantum numbers as needed to uniquely define the ket, all other quantum numbers will then be determined automatically. Furthermore, you can specify the atomic species to automatically set the nuclear spin i_c and the core electron spin s_c (the core electron orbital l_c will always be set to 0 by default).

The magnetic quantum number m is optional, and only needed if you want to calculate concrete matrix elements. If you don’t specify m, you still can calculate reduced matrix elements as well as reduced overlaps between two AngularKet objects.

[2]:
ket1 = AngularKetLS(s_tot=0, l_r=0, j_tot=0, species="Yb173")
print(f"{ket1=}")
ket2 = AngularKetJJ(j_tot=0, l_r=0, f_tot=2.5, species="Yb173")
print(f"{ket2=}")
ket3 = AngularKetFJ(f_c=2, l_r=0, f_tot=2.5, species="Yb173")
print(f"{ket3=}")
ket1=AngularKetLS(i_c=2.5, s_c=0.5, l_c=0, s_r=0.5, l_r=0, s_tot=0.0, l_tot=0, j_tot=0.0, f_tot=2.5)
ket2=AngularKetJJ(i_c=2.5, s_c=0.5, l_c=0, s_r=0.5, l_r=0, j_c=0.5, j_r=0.5, j_tot=0.0, f_tot=2.5)
ket3=AngularKetFJ(i_c=2.5, s_c=0.5, l_c=0, s_r=0.5, l_r=0, j_c=0.5, f_c=2.0, j_r=0.5, f_tot=2.5)

Calculating overlaps between two angular states of different coupling schemes is as simply as calling the calc_reduced_overlap method. Note, that this method ignores any given magnetic quantum numbers m (if specified). This method will automatically check the coupling schemes of the two states and calculate the needed Wigner6j and Wigner9j symbols.

[3]:
print(f"{ket1.calc_reduced_overlap(ket2)=}")
print(f"{ket1.calc_reduced_overlap(ket3)=}")
print(f"{ket2.calc_reduced_overlap(ket3)=}")
ket1.calc_reduced_overlap(ket2)=1.0
ket1.calc_reduced_overlap(ket3)=np.float64(-0.6454972243679028)
ket2.calc_reduced_overlap(ket3)=-0.6454972243679028

You can also convert the ket objects to state objects of different coupling schemes by using the to_state method with the desired coupling scheme as an argument. This will return a AngularState object, which contains a list of AngularKet objects and the respective coefficients.

[ ]:
print(ket1.to_state("JJ"))
print(ket1.to_state("FJ"))
1.0*JJ(i_c=2.5, s_c=0.5, l_c=0, s_r=0.5, l_r=0, j_c=0.5, j_r=0.5, j_tot=0.0, f_tot=2.5)
-0.6454972243679028*FJ(i_c=2.5, s_c=0.5, l_c=0, s_r=0.5, l_r=0, j_c=0.5, f_c=2.0, j_r=0.5, f_tot=2.5), 0.7637626158259734*FJ(i_c=2.5, s_c=0.5, l_c=0, s_r=0.5, l_r=0, j_c=0.5, f_c=3.0, j_r=0.5, f_tot=2.5)

The AngularState class also provides methods to calculate expectation and standard deviations of quantum numbers:

[ ]:
ket = AngularKetFJ(f_c=2, l_r=1, j_r=1.5, f_tot=2.5, species="Yb173")

ket_as_statefj = ket.to_state("FJ")
exp_f_c = ket_as_statefj.calc_exp_qn("f_c")
std_f_c = ket_as_statefj.calc_std_qn("f_c")

ket_as_statels = ket.to_state("LS")
exp_s_tot = ket_as_statels.calc_exp_qn("s_tot")
std_s_tot = ket_as_statels.calc_std_qn("s_tot")

print(ket)
print(f"{exp_f_c=}, {std_f_c=}")
print(f"{exp_s_tot=}, {std_s_tot=}")
FJ(i_c=2.5, s_c=0.5, l_c=0, s_r=0.5, l_r=1, j_c=0.5, f_c=2.0, j_r=1.5, f_tot=2.5)
exp_f_c=np.float64(2.0), std_f_c=0
exp_s_tot=np.float64(0.7777777777777777), std_s_tot=0.41573970964154916

And we can calculate matrix elements of operators between two AngularState objects by using the calc_matrix_element method.

[ ]:
ket1 = AngularKetFJ(f_c=2, l_r=1, j_r=1.5, f_tot=2.5, species="Yb173")
ket2 = AngularKetFJ(f_c=2, l_r=2, j_r=1.5, f_tot=2.5, species="Yb173")

print(ket1.calc_reduced_matrix_element(ket2, operator="spherical", kappa=1))
print(ket1.calc_reduced_matrix_element(ket1, operator="s_tot", kappa=1))
-0.1753272381496312
0.13801311186847098