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

Effective Hamiltonian

This notebook demonstrates how to calculate an effective Hamiltonian with the pairinteraction.perturbative module. We use https://arxiv.org/pdf/2410.21424 as a reference and try to reproduce figure 2c) and d) from the paper. Note that the paper used a Schrieffer-Wolff transformation to calculate the effective Hamiltonian, while here we use perturbation theory up to third order.

[2]:
import logging

import matplotlib.pyplot as plt
import numpy as np
import pairinteraction.real as pi
from pairinteraction import perturbative

logging.basicConfig(level=logging.ERROR)
[3]:
if pi.Database.get_global_database() is None:
    pi.Database.initialize_global_database(download_missing=True)
[4]:
kets = {
    "+": pi.KetAtom("Rb", n=81, l=0, j=0.5, m=0.5),
    "0": pi.KetAtom("Rb", n=80, l=1, j=1.5, m=1.5),
    "-": pi.KetAtom("Rb", n=80, l=0, j=0.5, m=0.5),
}
pair_energy = kets["0"].get_energy("GHz") * 2

basis = pi.BasisAtom(
    species="Rb",
    n=(78, 83),
    l=(0, 2),
    j=(0.5, 4.5),
)

system = pi.SystemAtom(basis=basis)
system.set_diamagnetism_enabled(True)
system.set_magnetic_field([0, 0, 60.7], "gauss")
system.diagonalize()

delta_energy = 5  # GHZ
basis_pair = pi.BasisPair(
    [system, system],
    energy=(pair_energy - delta_energy, pair_energy + delta_energy),
    energy_unit="GHz",
)
system_pair = pi.SystemPair(basis_pair)
system_pair.set_interaction_order(3)
[4]:
SystemPairReal(BasisPairReal(|Rb:78,S_1/2,-1/2; Rb:83,S_1/2,-1/2⟩ ... |Rb:83,P_3/2,3/2; Rb:78,S_1/2,1/2⟩), is_diagonal=True)
[5]:
theta_list = np.linspace(0, 90, 20)  # degree
R_list = np.linspace(8, 14, 20)  # mum

theta_default = 35.1  # rad
R_default = 11.6  # mum

order = 3
[6]:
kets_list = [(kets["+"], kets["-"]), (kets["0"], kets["0"]), (kets["-"], kets["+"])]
H_eff = {"theta": [], "R": []}

for theta in theta_list:
    system_pair.set_distance_vector(
        R_default * np.array([np.sin(theta * np.pi / 180), 0, np.cos(theta * np.pi / 180)]),
        "micrometer",
    )
    h_eff, _ = perturbative.get_effective_hamiltonian_from_system(
        kets_list, system_pair, order, unit="MHz"
    )
    H_eff["theta"].append(h_eff)

for R in R_list:
    system_pair.set_distance_vector(
        R
        * np.array(
            [np.sin(theta_default * np.pi / 180), 0, np.cos(theta_default * np.pi / 180)]
        ),
        "micrometer",
    )
    h_eff, _ = perturbative.get_effective_hamiltonian_from_system(
        kets_list, system_pair, order, unit="MHz"
    )
    H_eff["R"].append(h_eff)
[7]:
pair_energy = kets["+"].get_energy("GHz") + kets["0"].get_energy("GHz")
basis_pair = pi.BasisPair(
    [system, system],
    energy=(pair_energy - delta_energy, pair_energy + delta_energy),
    energy_unit="GHz",
)
system_pair = pi.SystemPair(basis_pair)
system_pair.set_interaction_order(3)

kets_list = [(kets["+"], kets["0"]), (kets["0"], kets["+"])]
H_eff_p0 = {"theta": [], "R": []}

for theta in theta_list:
    system_pair.set_distance_vector(
        R_default * np.array([np.sin(theta * np.pi / 180), 0, np.cos(theta * np.pi / 180)]),
        "micrometer",
    )
    h_eff, _ = perturbative.get_effective_hamiltonian_from_system(
        kets_list, system_pair, order, unit="MHz"
    )
    H_eff_p0["theta"].append(h_eff)

for R in R_list:
    system_pair.set_distance_vector(
        R
        * np.array(
            [np.sin(theta_default * np.pi / 180), 0, np.cos(theta_default * np.pi / 180)]
        ),
        "micrometer",
    )
    h_eff, _ = perturbative.get_effective_hamiltonian_from_system(
        kets_list, system_pair, order, unit="MHz"
    )
    H_eff_p0["R"].append(h_eff)
[10]:
H_eff = {key: np.array(value) for key, value in H_eff.items()}
H_eff_p0 = {key: np.array(value) for key, value in H_eff_p0.items()}

fig, axs = plt.subplots(2, 1, figsize=(6, 6))

axs[0].plot(theta_list, H_eff_p0["theta"][:, 0, 1], "C0-", label=r"$J^{+0}$")
axs[0].plot(theta_list, H_eff["theta"][:, 0, 1], "C1-", label=r"$J^{00}$")
axs[0].plot(theta_list, H_eff["theta"][:, 0, 2], "C2-", label=r"$V^\text{offd}$")
axs[0].set_xlabel(r"$\theta$ (degree)")

axs[1].plot(R_list, H_eff_p0["R"][:, 0, 1], "C0-", label=r"$J^{+0}$")
axs[1].plot(R_list, H_eff["R"][:, 0, 1], "C1-", label=r"$J^{00}$")
axs[1].plot(R_list, H_eff["R"][:, 0, 2], "C2-", label=r"$V^\text{offd}$")
axs[1].set_xlabel(r"$R$ ($\mu$m)")

for ax in axs:
    ax.legend()
    ax.set_ylabel(r"(MHz)")

fig.tight_layout()
plt.show()
../../_images/tutorials_examples_python_perturbative_h_eff_8_0.png