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

Quick Start

The pairinteraction software allows for calculation properties of Rydberg atoms and Rydberg pair potentials, optionally considering electric and magnetic fields in arbitrary directions. The software is written so that it works for atoms with a single valence electron as well as for atoms which require multi-channel quantum defect theory. To achieve a high performance, the backend of the software is written in C++ and wrapped with nanobind, providing a Python interface and graphical user interface. The software can be installed via pip with the following command on Linux, MacOS 13+, and Windows:

pip install pairinteraction

The construction of Hamiltonians is accelerated by using pre-calculated matrix elements, which are stored in database tables. These tables are automatically downloaded from GitHub when needed [1,2]. Once the tables are downloaded, they are cached locally and the software can be used without an internet connection. To download tables manually, for example, the tables for Rubdium and Yb171 (for a full list of supported species, see the “Identifier” column in the “quantum defect references” table of pairinteraction’s README), run:

pairinteraction download Rb Yb171_mqdt

To test the software, run:

pairinteraction --log-level INFO test

To start the graphical user interface, run:

pairinteraction --log-level INFO gui

Using the Python Interface

Import the necessary libraries and initialize pairinteraction’s database that contains pre-calculated atomic states and matrix elements. By setting download_missing=True, database tables are automatically downloaded from GitHub when needed.

[1]:
import matplotlib.pyplot as plt
import numpy as np
import pairinteraction.real as pi  # Use "import pairinteraction.complex as pi" if complex
from pairinteraction.visualization.colormaps import alphamagma

if pi.Database.get_global_database() is None:
    pi.Database.initialize_global_database(download_missing=True)

The library is structured around Python classes that can be used to model systems of Rydberg atoms. In the following, we describe a system of a single Rydberg atom and calculate the energy shift due to an electric and magnetic field.

[2]:
# Construct and diagonalize the Hamiltonian of a single Rydberg atom in an electric and
# magnetic field
ket = pi.KetAtom("Rb", n=60, l=0, m=0.5)
basis = pi.BasisAtom("Rb", n=(ket.n - 3, ket.n + 3), l=(ket.l - 3, ket.l + 3))
system = (
    pi.SystemAtom(basis)
    .set_electric_field([0, 0, 0.5], unit="V/cm")
    .set_magnetic_field([0, 0, 10], unit="gauss")
)
pi.diagonalize(
    [system], diagonalizer="lapacke_evd", float_type="float64"
)  # Use "float32" for faster calculations

# Obtain the eigenenergies and the index of the eigenstate having the largest overlap with
# the ket we are interested in
eigenenergies = system.get_eigenenergies(unit="GHz")
overlaps = system.get_eigenbasis().get_overlaps(ket)
index = np.argmax(overlaps)

# Calculate the energy shift
energy_shift = eigenenergies[index] - ket.get_energy(unit="GHz")
print(f"Energy shift: {energy_shift:.3f} GHz")
Energy shift: -0.009 GHz

Two single-atom systems can be combined to model a pair of atoms. In the following, we show how to calculate the pair potential for the ket state that we have specified above.

[ ]:
# Construct and diagonalize the Hamiltonian for a pair of Rydberg atoms at different distances
distances = np.linspace(1, 7, 100)  # in micrometers
pair_energy = 2 * (ket.get_energy(unit="GHz") + energy_shift)
pair_basis = pi.BasisPair(
    [system, system],
    energy=(pair_energy - 10, pair_energy + 10),
    energy_unit="GHz",
    m=(2 * ket.m, 2 * ket.m),
)
print(f"Number of states in the pair basis: {pair_basis.number_of_states}")

pair_systems = [
    pi.SystemPair(pair_basis).set_distance_vector([0, 0, d], unit="micrometer")
    for d in distances
]
pi.diagonalize(
    pair_systems,
    diagonalizer="lapacke_evr",
    float_type="float64",
    energy_range=(pair_energy, pair_energy + 0.5),
    energy_unit="GHz",
)

# Obtain the eigenenergies and the overlaps with the ket we are interested in
pair_eigenenergies = [s.get_eigenenergies(unit="GHz") for s in pair_systems]
pair_overlaps = [s.get_eigenbasis().get_overlaps([ket, ket]) for s in pair_systems]

# Plot the pair potentials
distances_repeated = np.hstack(
    [d * np.ones_like(e) for d, e in zip(distances, pair_eigenenergies)]
)
pair_eigenenergies_flattened = np.hstack(pair_eigenenergies)
pair_overlaps_flattened = np.hstack(pair_overlaps)
sorter = np.argsort(pair_eigenenergies_flattened)

scat = plt.scatter(
    distances_repeated[sorter],
    pair_eigenenergies_flattened[sorter] - pair_energy,
    c=pair_overlaps_flattened[sorter],
    s=10,
    cmap=alphamagma,
    vmin=0,
    vmax=1,
)
plt.colorbar(scat, label=f"Overlap with 2x{ket}")
plt.xlabel("Distance (μm)")
plt.ylabel("Eigenenergy (GHz)")
plt.show()
Number of states in the pair basis: 343
../../_images/tutorials_examples_python_quick_start_8_1.png

In addition to these basic functionalities, the pairinteraction library comes with methods for the perturbative calculation of effective Hamiltonians and the calculation of properties of Rydberg atoms, such as lifetimes. For examples, see the corresponding tutorials.