Source code for sim.hamiltonian.terms.optical

# ==============================================================================
#  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.
# ==============================================================================
"""
Optical coupling between ground and excited states.

Laser light couples the NV ground state (³A₂) to the excited state
(³E) through electric dipole transitions. This is used for optical
initialization, readout, and coherent optical control.

Physics
-------
The optical Hamiltonian in the rotating frame is:

    H_opt = (Ω_L/2) · [|g⟩⟨e| + |e⟩⟨g|]

where Ω_L is the optical Rabi frequency, proportional to the
laser electric field amplitude.

For spin-conserving transitions (Δms = 0):

    H_opt = (Ω_L/2) · Σ_{ms,mI} [|g,ms,mI⟩⟨e,ms,mI| + h.c.]

The optical Rabi frequency is related to laser parameters by:

    Ω_L = d · E_0 / ℏ

where d is the dipole moment and E_0 is the electric field amplitude.

Typical Values
--------------
- Zero-phonon line: 637 nm (1.945 eV)
- Green excitation: 532 nm
- Dipole moment: d ≈ 1.6 × 10⁻²⁹ C·m
- Typical Rabi frequencies: 1-100 MHz

References
----------
[1] Doherty et al., Physics Reports 528, 1-45 (2013)
[2] Robledo et al., Nature 477, 574 (2011)
"""

import numpy as np
from typing import Optional, Callable, Union

from .base import HamiltonianTerm
from ...core.constants import MHZ


[docs] class OpticalCoupling(HamiltonianTerm): """ Optical coupling between ground and excited states. Parameters ---------- omega : float or callable Optical Rabi frequency in MHz. Can be: - float: constant Rabi frequency - callable: omega(t) returning Rabi frequency at time t detuning : float Detuning from the optical transition in GHz. Default: 0 spin_conserving : bool If True, only spin-conserving transitions (Δms = 0). Default: True name : str, optional Custom name for the term Attributes ---------- omega : float or callable Optical Rabi frequency parameter detuning : float Optical detuning in GHz spin_conserving : bool Transition selection rule Examples -------- >>> from sim import HamiltonianBuilder >>> from sim.hamiltonian.terms import ZFS, OpticalCoupling >>> >>> # Constant optical drive >>> H = HamiltonianBuilder() >>> H.add(ZFS(D=2.87)) >>> H.add(OpticalCoupling(omega=50)) # 50 MHz Rabi frequency >>> >>> # Pulsed optical excitation >>> def laser_pulse(t): ... if 0 <= t < 10e-9: # 10 ns pulse ... return 100.0 # 100 MHz ... return 0.0 >>> >>> H.add(OpticalCoupling(omega=laser_pulse)) Notes ----- The optical coupling creates coherent superpositions of ground and excited states. In practice, spontaneous emission quickly destroys these superpositions (lifetime ~12 ns). For optical pumping (initialization), the Lindblad dissipation terms are more important than the coherent coupling. """
[docs] def __init__( self, omega: Union[float, Callable] = 0.0, # MHz detuning: float = 0.0, # GHz spin_conserving: bool = True, name: Optional[str] = None ): super().__init__(name=name) self._omega_param = omega self.detuning = detuning self.spin_conserving = spin_conserving # Determine if omega is a function self._omega_is_func = callable(omega)
@property def is_time_dependent(self) -> bool: """Optical coupling is always time-dependent.""" return True def _get_omega(self, t: float) -> float: """Get optical Rabi frequency at time t in MHz.""" if self._omega_is_func: return self._omega_param(t) return self._omega_param
[docs] def build(self, t: float = 0.0) -> np.ndarray: """ Build the 18×18 optical coupling Hamiltonian at time t. Parameters ---------- t : float Time in seconds Returns ------- np.ndarray 18×18 complex matrix in rad/s Notes ----- The optical coupling connects the ground state manifold (indices 0-8) to the excited state manifold (indices 9-17). For spin-conserving transitions: |g, ms, mI⟩ ↔ |e, ms, mI⟩ The coupling matrix has off-diagonal blocks: H[0:9, 9:18] = (Ω/2) · I_9 H[9:18, 0:9] = (Ω/2) · I_9 (conjugate) """ Omega = self._get_omega(t) * MHZ # Convert to rad/s H = np.zeros((18, 18), dtype=np.complex128) if self.spin_conserving: # Spin-conserving: |g,ms,mI⟩ ↔ |e,ms,mI⟩ # This is a 9×9 identity block connecting g and e manifolds coupling = (Omega / 2) * np.eye(9, dtype=np.complex128) # Off-diagonal blocks H[:9, 9:] = coupling # |g⟩ → |e⟩ H[9:, :9] = coupling # |e⟩ → |g⟩ (Hermitian) else: # Allow all transitions (for non-spin-conserving processes) # This would need a more detailed model coupling = (Omega / 2) * np.eye(9, dtype=np.complex128) H[:9, 9:] = coupling H[9:, :9] = coupling return H
[docs] def rabi_period(self) -> Optional[float]: """ Calculate Rabi oscillation period for constant Rabi frequency. Returns ------- float or None Period in seconds, or None if Rabi freq is time-dependent """ if self._omega_is_func: return None if self._omega_param == 0: return None # T = 2π / Ω return 2 * np.pi / (self._omega_param * MHZ)
def __repr__(self) -> str: if self._omega_is_func: return f"OpticalCoupling(omega=func)" else: return f"OpticalCoupling(omega={self._omega_param} MHz)"