LCOV - code coverage report
Current view: top level - tests - test_lifetime.py (source / functions) Coverage Total Hit
Test: coverage.info Lines: 79.1 % 43 34
Test Date: 2026-11-02 09:44:19 Functions: 100.0 % 4 4

            Line data    Source code
       1              : # SPDX-FileCopyrightText: 2025 PairInteraction Developers
       2              : # SPDX-License-Identifier: LGPL-3.0-or-later
       3              : 
       4            1 : from __future__ import annotations
       5              : 
       6            1 : from typing import TYPE_CHECKING
       7              : 
       8            1 : import numpy as np
       9            1 : import pytest
      10            1 : from pairinteraction import ureg
      11            1 : from scipy.optimize import curve_fit
      12              : 
      13              : if TYPE_CHECKING:
      14              :     from pairinteraction.units import NDArray
      15              : 
      16              :     from .utils import PairinteractionModule
      17              : 
      18            1 : from .utils import no_log_propagation, skip_value_check_if_shrunk_database
      19              : 
      20              : # The shrunk database that comes with the repository only contains a few low-lying states,
      21              : # so that the decay of a Rydberg state is only captured partially and the calculated lifetimes are far off.
      22              : # The tests are run nevertheless so that all code is executed, but the checks of the resulting values are skipped
      23              : 
      24              : 
      25            1 : def test_lifetime(pi_module: PairinteractionModule) -> None:
      26              :     """Test calculating the lifetime of a state."""
      27            1 :     ket = pi_module.KetAtom("Yb174_mqdt", n=64, l=0, j=0, m=0)
      28              : 
      29            1 :     lifetime1 = ket.get_lifetime(temperature=300, temperature_unit="K", unit="us")
      30            1 :     lifetime2 = ket.get_lifetime(temperature=300 * ureg.K, unit="us")
      31            1 :     lifetime3 = ket.get_lifetime(temperature=300 * ureg.K)
      32            1 :     lifetime4 = ket.get_lifetime(unit="us")
      33              : 
      34            1 :     assert lifetime1 == lifetime2 == lifetime3.to(ureg.us).magnitude < lifetime4
      35              : 
      36            1 :     skip_value_check_if_shrunk_database()
      37            0 :     assert pytest.approx(lifetime1, rel=0.05) == 45.7  # NOSONAR
      38            0 :     assert pytest.approx(lifetime4, rel=0.05) == 59.3  # NOSONAR
      39              : 
      40              : 
      41            1 : def test_lifetime_scaling(pi_module: PairinteractionModule) -> None:
      42              :     """Test the scaling of the lifetime with the principal quantum number."""
      43              : 
      44            1 :     def fit_function(x: NDArray, a: float, b: float) -> NDArray:
      45            1 :         return a * x + b
      46              : 
      47            1 :     n_list = list(range(58, 68, 1))
      48              : 
      49              :     # S states
      50            1 :     kets = [pi_module.KetAtom("Rb", n=n, l=0, j=0.5, m=0.5) for n in n_list]
      51            1 :     nu = [ket.nu for ket in kets]
      52            1 :     with no_log_propagation("cpp"):  # surpress low n state warnings from lifetime calculation
      53            1 :         lifetimes = [ket.get_lifetime(unit="us") for ket in kets]
      54            1 :     popt, _ = curve_fit(fit_function, np.log(nu), np.log(lifetimes))
      55              : 
      56            1 :     skip_value_check_if_shrunk_database()
      57            0 :     assert np.isclose(popt[0], 3, atol=0.02)
      58              : 
      59              :     # Circular states
      60              :     # In contrast to the states above, they cannot be obtained from the shrunk database at all
      61              :     # because the shrunk database only contains states with a small quantum number l_ryd.
      62            0 :     kets = [pi_module.KetAtom("Rb", n=n, l=n - 1, j=n - 0.5, m=n - 0.5) for n in n_list]
      63            0 :     nu = [ket.nu for ket in kets]
      64            0 :     with no_log_propagation("cpp"):  # surpress low n state warnings from lifetime calculation
      65            0 :         lifetimes = [ket.get_lifetime(unit="us") for ket in kets]
      66            0 :     popt, _ = curve_fit(fit_function, np.log(nu), np.log(lifetimes))
      67            0 :     assert np.isclose(popt[0], 5, atol=0.02)
      68              : 
      69              : 
      70            1 : def test_transition_rates(pi_module: PairinteractionModule) -> None:
      71              :     """Test calculating transition rates to other states."""
      72            1 :     ket = pi_module.KetAtom("Yb174_mqdt", n=60, l=0, j=0, m=0)
      73              : 
      74            1 :     with no_log_propagation("cpp"):  # surpress low n state warnings from lifetime calculation
      75            1 :         lifetime = ket.get_lifetime(temperature=300, temperature_unit="K", unit="us")
      76            1 :         kets_sp, rates_sp = ket.get_spontaneous_transition_rates(unit="MHz")
      77            1 :         kets_bbr, rates_bbr = ket.get_black_body_transition_rates(temperature=300, temperature_unit="K", unit="MHz")
      78              : 
      79            1 :     assert len(rates_sp) == len(kets_sp)
      80            1 :     assert len(rates_bbr) == len(kets_bbr)
      81            1 :     assert np.isclose(1 / (sum(rates_sp) + sum(rates_bbr)), lifetime)
        

Generated by: LCOV version 2.0-1