From 2615dd58738bc85c810c8656cd40fd71e41731cf Mon Sep 17 00:00:00 2001 From: johannes-moegerle Date: Thu, 27 Aug 2026 14:29:48 +0200 Subject: [PATCH] database states include all quantum numbers --- .../generate_states_table.py | 56 ++++++++++++------- tests/test_generate_database.py | 22 ++++++-- 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/rydstate/generate_database/generate_states_table.py b/src/rydstate/generate_database/generate_states_table.py index a293cf58..7a8376aa 100644 --- a/src/rydstate/generate_database/generate_states_table.py +++ b/src/rydstate/generate_database/generate_states_table.py @@ -20,20 +20,29 @@ "nu": float, "f": float, "exp_nui": float, - "exp_l": float, - "exp_j": float, - "exp_s": float, + "exp_i_core": float, + "exp_s_core": float, + "exp_l_core": float, + "exp_j_core": float, + "exp_f_core": float, + "exp_s_ryd": float, "exp_l_ryd": float, "exp_j_ryd": float, + "exp_s": float, + "exp_l": float, + "exp_j": float, "std_nui": float, - "std_l": float, - "std_j": float, - "std_s": float, + "std_i_core": float, + "std_s_core": float, + "std_l_core": float, + "std_j_core": float, + "std_f_core": float, + "std_s_ryd": float, "std_l_ryd": float, "std_j_ryd": float, - "is_j_total_momentum": bool, - "is_calculated_with_mqdt": bool, - "underspecified_channel_contribution": float, + "std_s": float, + "std_l": float, + "std_j": float, } @@ -58,8 +67,6 @@ def generate_states_table( def get_state_data(ids: int, state: RydbergState) -> tuple[float | int | str | bool, ...]: """Get the data for a given state as a tuple.""" - underspecified_channel_contribution = sum(abs(coeff) ** 2 for coeff, ket in state if ket.angular.contains_unknown) - state_ls = state.to_coupling_scheme("LS") state_fj = state.to_coupling_scheme("FJ") @@ -71,19 +78,28 @@ def get_state_data(ids: int, state: RydbergState) -> tuple[float | int | str | b state.nu, # nu state.f_tot, # f_tot state.calc_exp_qn("nui"), # exp_nui - state_ls.calc_exp_qn("l_tot"), # exp_l - state_ls.calc_exp_qn("j_tot"), # exp_j - state_ls.calc_exp_qn("s_tot"), # exp_s + state.calc_exp_qn("i_c"), # exp_i_core + state.calc_exp_qn("s_c"), # exp_s_core + state.calc_exp_qn("l_c"), # exp_l_core + state_fj.calc_exp_qn("j_c"), # exp_j_core + state_fj.calc_exp_qn("f_c"), # exp_f_core + state.calc_exp_qn("s_r"), # exp_s_ryd state.calc_exp_qn("l_r"), # exp_l_ryd state_fj.calc_exp_qn("j_r"), # exp_j_ryd = j for sqdt only one valence electron + state_ls.calc_exp_qn("s_tot"), # exp_s + state_ls.calc_exp_qn("l_tot"), # exp_l + state_ls.calc_exp_qn("j_tot"), # exp_j state.calc_std_qn("nui"), # std_nui = 0 - state_ls.calc_std_qn("l_tot"), # std_l - state_ls.calc_std_qn("j_tot"), # std_j - state_ls.calc_std_qn("s_tot"), # std_s + state.calc_std_qn("i_c"), # std_i_core = 0 + state.calc_std_qn("s_c"), # std_s_core = 0 + state.calc_std_qn("l_c"), # std_l_core + state_fj.calc_std_qn("j_c"), # std_j_core + state_fj.calc_std_qn("f_c"), # std_f_core + state.calc_std_qn("s_r"), # std_s_ryd = 0 state.calc_std_qn("l_r"), # std_l_ryd state_fj.calc_std_qn("j_r"), # std_j_ryd - bool(state.element_properties.i_c == 0), # is_j_total_momentum - bool(len(state.rydberg_kets) > 1), # is_calculated_with_mqdt - underspecified_channel_contribution, # underspecified_channel_contribution = 0 for sqdt + state_ls.calc_std_qn("s_tot"), # std_s + state_ls.calc_std_qn("l_tot"), # std_l + state_ls.calc_std_qn("j_tot"), # std_j ) return tuple(x.item() if isinstance(x, np.generic) else x for x in data) diff --git a/tests/test_generate_database.py b/tests/test_generate_database.py index 9b76ad1f..3316daca 100644 --- a/tests/test_generate_database.py +++ b/tests/test_generate_database.py @@ -13,7 +13,7 @@ generate_matrix_elements_tables, ) from rydstate.generate_database.generate_misc_table import generate_wigner_table -from rydstate.generate_database.generate_states_table import generate_states_table, get_state_data +from rydstate.generate_database.generate_states_table import COLUMNS, generate_states_table, get_state_data from rydstate.units import MatrixElementOperatorRanks TEST_SPECIES_SPECIFIER = [ @@ -39,11 +39,18 @@ def test_generate_wigner_table_returns_rows() -> None: def test_get_state_data_for_sqdt_alkali_state() -> None: state = RydbergStateSQDTAlkali("H", n=1, l=0, j=0.5) - row = get_state_data(7, state) - assert row[0] == 7 - assert row[2:6] == (1, 1, 1.0, 0.5) - assert row[6:12] == (1.0, 0, 0.5, 0.5, 0, 0.5) - assert row[12:] == (0, 0, 0, 0, 0, 0, True, False, 0) + row = dict(zip(COLUMNS, get_state_data(7, state), strict=True)) + + assert row["id"] == 7 + assert (row["parity"], row["n"], row["nu"], row["f"]) == (1, 1, 1.0, 0.5) + assert row["exp_nui"] == 1.0 + # the hydrogen core is a bare proton, i.e. all its quantum numbers vanish + assert (row["exp_i_core"], row["exp_s_core"], row["exp_l_core"]) == (0, 0, 0) + assert (row["exp_j_core"], row["exp_f_core"]) == (0, 0) + assert (row["exp_s_ryd"], row["exp_l_ryd"], row["exp_j_ryd"]) == (0.5, 0, 0.5) + assert (row["exp_s"], row["exp_l"], row["exp_j"]) == (0.5, 0, 0.5) + # a single ket, so all standard deviations vanish + assert all(row[column] == 0 for column in COLUMNS if column.startswith("std_")) @pytest.mark.parametrize("species_specifier", TEST_SPECIES_SPECIFIER) @@ -64,6 +71,9 @@ def test_generate_states_table(species_specifier: str) -> None: assert np.allclose(table["nu"], basis.calc_exp_qn("nu")) assert np.allclose(table["exp_l_ryd"], basis.calc_exp_qn("l_r")) assert np.allclose(table["exp_s"], basis.calc_exp_qn("s_tot")) + # quantum numbers that are only good in the FJ scheme + assert np.allclose(table["exp_j_core"], basis.calc_exp_qn("j_c")) + assert np.allclose(table["exp_f_core"], basis.calc_exp_qn("f_c")) @pytest.mark.parametrize("species_specifier", TEST_SPECIES_SPECIFIER)