This page was generated from the Jupyter notebook state_object.ipynb. Open in Google Colab.

State object

[1]:
import matplotlib.pyplot as plt
import numpy as np
import pairinteraction.real as pi
from pairinteraction.visualization.colormaps import alphamagma
[2]:
if pi.Database.get_global_database() is None:
    pi.Database.initialize_global_database(download_missing=True)

Create superposition state objects

[3]:
# First create a ket of interest and a basis around this ket
ket = pi.KetAtom("Sr88_singlet", n=60, l=59, m=58)
print(f"Ket of interest: {ket}")
ket_energy = ket.get_energy(unit="GHz")
basis = pi.BasisAtom("Sr88_singlet", n=(ket.n - 3, ket.n + 3), l=(57, 60), m=(56, 60))
print(f"Number of basis states: {basis.number_of_states}")

# now with the ket and the basis we can define a state
state1 = pi.StateAtom(ket, basis)
# this state only has one entry in its coefficient vector
print(f"{state1.get_coefficients()=}")
# this can also be seen by just printing the state
print(f"State1: {state1}")

# To showcase addition, ... of two states we also define a second state
ket2 = pi.KetAtom("Sr88_singlet", n=60, l=58, m=58)
state2 = pi.StateAtom(ket2, basis)
print(f"State2: {state2}")
Ket of interest: |Sr88_singlet:60,59_59,58⟩
Number of basis states: 58
state1.get_coefficients()=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
       0., 0., 0., 0., 0., 0., 0.])
State1: StateAtom(1.00 |Sr88_singlet:60,59_59,58⟩)
State2: StateAtom(1.00 |Sr88_singlet:60,58_58,58⟩)
[4]:
# now we can create a symmetric and anti-symmetric superposition of these two states
state_plus = (state1 + state2).normalize()
state_minus = (state1 - state2).normalize()
print(f"State plus: {state_plus}")
print(f"State minus: {state_minus}")

# and you can create any linear combination of as many states as you want
ket3 = pi.KetAtom("Sr88_singlet", n=60, l=57, m=57)
state3 = pi.StateAtom(ket3, basis)
print(f"{1.1 * state1 + 0.6 * state2 - 0.4 * state3 = }")
State plus: StateAtom(0.71 |Sr88_singlet:60,59_59,58⟩ + 0.71 |Sr88_singlet:60,58_58,58⟩)
State minus: StateAtom(0.71 |Sr88_singlet:60,59_59,58⟩ + -0.71 |Sr88_singlet:60,58_58,58⟩)
1.1 * state1 + 0.6 * state2 - 0.4 * state3 = StateAtomReal(1.10 |Sr88_singlet:60,59_59,58⟩ + 0.60 |Sr88_singlet:60,58_58,58⟩ + -0.40 |Sr88_singlet:60,57_57,57⟩)

Use state objects to calculate overlaps and expectation values

[5]:
ov = state_plus.get_overlap(ket)
print(f"Overlap of state_plus with ket: {ov}")

d = state_plus.get_matrix_element(state_plus, "electric_dipole", q=0)
print(f"Matrix element of state_plus with state_plus: {d}")
Overlap of state_plus with ket: 0.4999999999999999
Matrix element of state_plus with state_plus: -90.00056153827039 atomic_unit_of_current * atomic_unit_of_time * bohr

Example of Stark map with overlap of superposition state objects

[6]:
electric_fields = np.linspace(0, 10, 50)
systems = [
    pi.SystemAtom(basis).set_electric_field([0, 0, e], unit="V/cm") for e in electric_fields
]

# Diagonalize the systems in parallel
pi.diagonalize(systems, diagonalizer="eigen", float_type="float32")

eigenenergies = [system.get_eigenenergies(unit="GHz") - ket_energy for system in systems]
overlaps_plus = [system.get_eigenbasis().get_overlaps(state_plus) for system in systems]
overlaps_minus = [system.get_eigenbasis().get_overlaps(state_minus) for system in systems]
[7]:
fig, axs = plt.subplots(1, 2, figsize=(10, 4), sharey=True)

x_repeated = np.hstack(
    [val * np.ones_like(es) for val, es in zip(electric_fields, eigenenergies)]
)
energies_flattened = np.hstack(eigenenergies)

for i, ax in enumerate(axs):
    try:
        ax.plot(electric_fields, np.array(eigenenergies), c="0.5", lw=0.25, zorder=-10)
    except ValueError:  # inhomogeneous shape -> no simple line plot possible
        for x, es in zip(electric_fields, eigenenergies):
            ax.plot([x] * len(es), es, c="0.5", ls="None", marker=".", zorder=-10)

    if i == 0:
        ax.set_title("Overlap with state plus")
        overlaps_flattened = np.hstack(overlaps_plus)
    else:
        ax.set_title("Overlap with state minus")
        overlaps_flattened = np.hstack(overlaps_minus)

    sorter = np.argsort(overlaps_flattened)

    scat = ax.scatter(
        x_repeated[sorter],
        energies_flattened[sorter],
        c=overlaps_flattened[sorter],
        s=15,
        vmin=0,
        vmax=1,
        cmap=alphamagma,
    )

fig.colorbar(scat, ax=axs[1], label="Overlap with state of interest")

for ax in axs:
    ax.set_xlabel("Electric Field [V/cm]")
    ax.set_ylim(-20, 20)
axs[0].set_ylabel("Energy [GHz]")

plt.show()
../../_images/tutorials_examples_python_state_object_10_0.png