Source code for sim.hamiltonian.terms.jahn_teller
# ==============================================================================
# QUSIM - Quantum Simulator for NV Centers
# Leon Kaiser, MSQC Goethe University, Frankfurt, Germany
# https://msqc.cgi-host6.rz.uni-frankfurt.de
# I.kaiser[at]em.uni-frankfurt.de
#
# This software is provided for scientific and educational purposes.
# Free to use, modify, and distribute with attribution.
# ==============================================================================
"""
Jahn-Teller coupling in the NV center excited state.
The excited state (³E) of the NV center is orbitally degenerate and
couples to vibrational modes through the dynamic Jahn-Teller effect.
This causes mixing between the orbital states and affects the
optical properties.
Physics
-------
The Jahn-Teller Hamiltonian describes electron-phonon coupling:
H_JT = ω(a†a + 1/2) + λ(a + a†) · O_orbital
where:
- ω is the phonon mode frequency
- a, a† are phonon creation/annihilation operators
- λ is the electron-phonon coupling strength
- O_orbital is an orbital operator
For the E-symmetry modes coupling to the ³E state:
H_JT = ωx(ax†ax + 1/2) + ωy(ay†ay + 1/2)
+ λx(ax + ax†)(Sx² - Sy²)
+ λy(ay + ay†){Sx, Sy}
Typical Values
--------------
- Phonon frequency: ω ~ 65 meV (~ 16 THz)
- Coupling strength: λ ~ 0.5 (dimensionless)
- Huang-Rhys factor: S ~ λ²/2
Simplified Model
----------------
For the 18D Hilbert space, we use an effective model that captures
the main effects without explicit phonon states. This is valid when:
- Temperature is low (kT << ℏω)
- Phonon dynamics are fast compared to spin dynamics
References
----------
[1] Fu et al., Phys. Rev. Lett. 103, 256404 (2009)
[2] Abtew et al., Phys. Rev. Lett. 107, 146403 (2011)
"""
import numpy as np
from typing import Optional
from .base import HamiltonianTerm
from ...core.operators import spin1_operators
from ...core.constants import MHZ
[docs]
class JahnTeller(HamiltonianTerm):
"""
Jahn-Teller vibronic coupling in excited state (simplified model).
This is a simplified effective model that captures the main effects
of Jahn-Teller coupling without explicit phonon states.
Parameters
----------
omega_x : float
Phonon mode frequency (x-mode) in MHz. Default: 1000 (1 GHz)
omega_y : float
Phonon mode frequency (y-mode) in MHz. Default: 1200 (1.2 GHz)
lambda_x : float
Coupling strength (x-mode), dimensionless. Default: 0.05
lambda_y : float
Coupling strength (y-mode), dimensionless. Default: 0.04
temperature : float
Temperature in Kelvin. Default: 300 K
name : str, optional
Custom name for the term
Attributes
----------
omega_x, omega_y : float
Phonon frequencies in MHz
lambda_x, lambda_y : float
Coupling strengths (dimensionless)
temperature : float
Temperature in Kelvin
Examples
--------
>>> from sim import HamiltonianBuilder
>>> from sim.hamiltonian.terms import ZFS, JahnTeller
>>>
>>> H = HamiltonianBuilder()
>>> H.add(ZFS(D=2.87))
>>> H.add(JahnTeller()) # Default parameters
>>>
>>> # Low temperature (cryogenic)
>>> H.add(JahnTeller(temperature=4.0))
Notes
-----
The Jahn-Teller effect is primarily important for:
- Understanding the excited state fine structure
- Calculating optical transition rates
- Modeling temperature dependence
At room temperature, the JT effect averages out due to fast
phonon dynamics. At low temperature, it can cause strain-like
splitting in the excited state.
This simplified model only acts on the excited state manifold.
"""
[docs]
def __init__(
self,
omega_x: float = 1000.0, # MHz (~1 GHz)
omega_y: float = 1200.0, # MHz
lambda_x: float = 0.05, # dimensionless
lambda_y: float = 0.04, # dimensionless
temperature: float = 300.0, # Kelvin
name: Optional[str] = None
):
super().__init__(name=name)
self.omega_x = omega_x
self.omega_y = omega_y
self.lambda_x = lambda_x
self.lambda_y = lambda_y
self.temperature = temperature
# Cache for the static Hamiltonian
self._cache: Optional[np.ndarray] = None
@property
def is_time_dependent(self) -> bool:
"""Jahn-Teller coupling is time-independent (effective model)."""
return False
def _thermal_occupation(self, omega_mhz: float) -> float:
"""
Calculate thermal phonon occupation number.
Parameters
----------
omega_mhz : float
Phonon frequency in MHz
Returns
-------
float
Average phonon occupation <n>
"""
from ...core.constants import KB, HBAR
if self.temperature <= 0:
return 0.0
# ω in rad/s
omega = omega_mhz * MHZ
# Bose-Einstein distribution: <n> = 1 / (exp(ℏω/kT) - 1)
x = HBAR * omega / (KB * self.temperature)
if x > 40: # Avoid overflow
return 0.0
return 1.0 / (np.exp(x) - 1)
def _build_excited_3x3(self) -> np.ndarray:
"""
Build effective 3×3 JT Hamiltonian for excited state electron spin.
Returns
-------
np.ndarray
3×3 complex Hermitian matrix in rad/s
"""
S = spin1_operators()
# Effective coupling strength includes thermal averaging
# <Q²> = ℏ/(2mω) × (2<n> + 1) ~ (2<n> + 1)
n_x = self._thermal_occupation(self.omega_x)
n_y = self._thermal_occupation(self.omega_y)
# Effective strain-like terms from JT coupling
# H_eff ~ λ² × ω × (Sx² - Sy²) for x-mode
# H_eff ~ λ² × ω × {Sx, Sy} for y-mode
# At low temperature: static JT distortion
# At high temperature: dynamic averaging
eff_x = self.lambda_x**2 * self.omega_x * MHZ * (2 * n_x + 1)
eff_y = self.lambda_y**2 * self.omega_y * MHZ * (2 * n_y + 1)
H = (
eff_x * (S.Sx @ S.Sx - S.Sy @ S.Sy) +
eff_y * (S.Sx @ S.Sy + S.Sy @ S.Sx)
)
return H
[docs]
def build(self, t: float = 0.0) -> np.ndarray:
"""
Build the 18×18 Jahn-Teller Hamiltonian.
Parameters
----------
t : float
Time in seconds (not used)
Returns
-------
np.ndarray
18×18 complex Hermitian matrix in rad/s
Notes
-----
The JT effect only acts on the excited state manifold
(indices 9-17). The ground state is not affected.
"""
if self._cache is None:
H_3x3 = self._build_excited_3x3()
# Extend to 9×9 (electron spin ⊗ N14 nuclear spin)
I3_nuclear = np.eye(3, dtype=np.complex128)
H_9x9 = np.kron(H_3x3, I3_nuclear)
# Embed in 18×18, only in excited state (indices 9-17)
H_18x18 = np.zeros((18, 18), dtype=np.complex128)
H_18x18[9:, 9:] = H_9x9
self._cache = H_18x18
return self._cache.copy()
[docs]
def huang_rhys_factor(self) -> tuple:
"""
Calculate the Huang-Rhys factors for both modes.
Returns
-------
tuple
(S_x, S_y) Huang-Rhys factors (dimensionless)
Notes
-----
The Huang-Rhys factor S = λ²/2 characterizes the strength
of electron-phonon coupling. S ~ 0.5 corresponds to moderate
coupling where the Stokes shift equals the phonon energy.
"""
S_x = self.lambda_x**2 / 2
S_y = self.lambda_y**2 / 2
return (S_x, S_y)
def __repr__(self) -> str:
return f"JahnTeller(T={self.temperature} K, λ_x={self.lambda_x}, λ_y={self.lambda_y})"