Skip to content

Phonons

Phonon mode data and modulated-polarisation helpers. Docstrings are the source of truth, rendered with mkdocstrings (numpydoc style).

photonics_helper.phonon

Phonon module — multi-mode Raman-active phonon modeling.

Provides PhononMode dataclass and PhononResponse class for combining multiple Raman-active phonon modes into a unified response function.

TWO_PI_C_CM module-attribute

TWO_PI_C_CM = 2.0 * np.pi * 29979245800.0

HAS_PLOTLY module-attribute

HAS_PLOTLY = True

PHONON_MATERIALS module-attribute

PHONON_MATERIALS: dict[str, list[PhononMode]] = {'LiNbO3': [PhononMode(Wavenumber(254, '1/cm'), Wavenumber(14, '1/cm'), 'A₁', 1.0, note='Barker & Loudon (1967)'), PhononMode(Wavenumber(162, '1/cm'), Wavenumber(8, '1/cm'), 'A₁', 0.8, note='Ridah et al. (1997)'), PhononMode(Wavenumber(701, '1/cm'), Wavenumber(6, '1/cm'), 'A₁', 0.6, note='Barker & Loudon (1967)'), PhononMode(Wavenumber(637, '1/cm'), Wavenumber(5, '1/cm'), 'E', 0.7, note='Ridah et al. (1997)'), PhononMode(Wavenumber(576, '1/cm'), Wavenumber(4, '1/cm'), 'E', 0.5, note='Barker & Loudon (1967)'), PhononMode(Wavenumber(277, '1/cm'), Wavenumber(10, '1/cm'), 'E', 0.4, note='Ridah et al. (1997)'), PhononMode(Wavenumber(819, '1/cm'), Wavenumber(3, '1/cm'), 'E', 0.3, note='Barker & Loudon (1967)')], 'LiTaO3': [PhononMode(Wavenumber(255, '1/cm'), Wavenumber(12, '1/cm'), 'A₁', 1.0, note='Raptis (1988)'), PhononMode(Wavenumber(143, '1/cm'), Wavenumber(6, '1/cm'), 'A₁', 0.7, note='Margueron et al. (2012)'), PhononMode(Wavenumber(740, '1/cm'), Wavenumber(5, '1/cm'), 'A₁', 0.5, note='Raptis (1988)'), PhononMode(Wavenumber(690, '1/cm'), Wavenumber(4, '1/cm'), 'E', 0.6, note='Raptis (1988)'), PhononMode(Wavenumber(327, '1/cm'), Wavenumber(8, '1/cm'), 'E', 0.4, note='Margueron et al. (2012)')], 'BaTiO3': [PhononMode(Wavenumber(258, '1/cm'), Wavenumber(5, '1/cm'), 'A₁', 1.0, note='Scalabrin et al. (1977)'), PhononMode(Wavenumber(181, '1/cm'), Wavenumber(3, '1/cm'), 'A₁', 0.8, note='Chaves et al. (1974)'), PhononMode(Wavenumber(142, '1/cm'), Wavenumber(2, '1/cm'), 'A₁', 0.6, note='Scalabrin et al. (1977)'), PhononMode(Wavenumber(520, '1/cm'), Wavenumber(45, '1/cm'), 'A₁', 0.9, note='Scalabrin et al. (1977)'), PhononMode(Wavenumber(306, '1/cm'), Wavenumber(4, '1/cm'), 'E', 0.7, note='Chaves et al. (1974)'), PhononMode(Wavenumber(280, '1/cm'), Wavenumber(3, '1/cm'), 'E', 0.5, note='Scalabrin et al. (1977)'), PhononMode(Wavenumber(720, '1/cm'), Wavenumber(6, '1/cm'), 'E', 0.4, note='Chaves et al. (1974)'), PhononMode(Wavenumber(890, '1/cm'), Wavenumber(8, '1/cm'), 'B₁', 0.3, note='Scalabrin et al. (1977)')], 'YAG': [PhononMode(Wavenumber(784, '1/cm'), Wavenumber(8, '1/cm'), 'T₂g', 1.0, note='Hurrell et al. (1968)'), PhononMode(Wavenumber(360, '1/cm'), Wavenumber(5, '1/cm'), 'E_g', 0.6, note='Hurrell et al. (1968)'), PhononMode(Wavenumber(260, '1/cm'), Wavenumber(4, '1/cm'), 'E_g', 0.5, note='Hurrell et al. (1968)'), PhononMode(Wavenumber(1230, '1/cm'), Wavenumber(6, '1/cm'), 'T₂g', 0.7, note='Lamaignere et al. (2020)'), PhononMode(Wavenumber(1500, '1/cm'), Wavenumber(10, '1/cm'), 'A₁g', 0.4, note='Hurrell et al. (1968)')], 'Al2O3': [PhononMode(Wavenumber(418, '1/cm'), Wavenumber(5, '1/cm'), 'E_g', 1.0, note='Watson et al. (1981)'), PhononMode(Wavenumber(378, '1/cm'), Wavenumber(4, '1/cm'), 'E_g', 0.8, note='Major et al. (2004)'), PhononMode(Wavenumber(636, '1/cm'), Wavenumber(6, '1/cm'), 'A₁g', 0.6, note='Watson et al. (1981)'), PhononMode(Wavenumber(750, '1/cm'), Wavenumber(8, '1/cm'), 'E_g', 0.5, note='Watson et al. (1981)'), PhononMode(Wavenumber(1150, '1/cm'), Wavenumber(10, '1/cm'), 'A₁g', 0.4, note='Major et al. (2004)')], 'KTP': [PhononMode(Wavenumber(270, '1/cm'), Wavenumber(20, '1/cm'), 'A', 1.0, note='Neufeld et al. (2023) — dominant'), PhononMode(Wavenumber(500, '1/cm'), Wavenumber(15, '1/cm'), 'A', 0.8, note='Neufeld et al. (2023)'), PhononMode(Wavenumber(620, '1/cm'), Wavenumber(12, '1/cm'), 'B', 0.7, note='Neufeld et al. (2023)'), PhononMode(Wavenumber(750, '1/cm'), Wavenumber(10, '1/cm'), 'A', 0.6, note='Neufeld et al. (2023)'), PhononMode(Wavenumber(890, '1/cm'), Wavenumber(8, '1/cm'), 'B', 0.5, note='Neufeld et al. (2023)')], 'GaN': [PhononMode(Wavenumber(568, '1/cm'), Wavenumber(4, '1/cm'), 'E₂(high)', 1.0, note='Zeng et al. (2020)'), PhononMode(Wavenumber(144, '1/cm'), Wavenumber(3, '1/cm'), 'A₁(LO)', 0.6, note='Zeng et al. (2020)'), PhononMode(Wavenumber(532, '1/cm'), Wavenumber(5, '1/cm'), 'E₁(LO)', 0.5, note='Almeida et al. (2019)'), PhononMode(Wavenumber(736, '1/cm'), Wavenumber(6, '1/cm'), 'A₁(LO)', 0.4, note='Zeng et al. (2020)')], 'AlN': [PhononMode(Wavenumber(658, '1/cm'), Wavenumber(1, '1/cm'), 'E₂(high)', 1.0, note='Jung & Tang (2016)'), PhononMode(Wavenumber(615, '1/cm'), Wavenumber(2, '1/cm'), 'E₁(LO)', 0.7, note='Pandit et al. (2007)'), PhononMode(Wavenumber(895, '1/cm'), Wavenumber(3, '1/cm'), 'A₁(LO)', 0.5, note='Jung & Tang (2016)'), PhononMode(Wavenumber(330, '1/cm'), Wavenumber(2, '1/cm'), 'A₁(TO)', 0.4, note='Pandit et al. (2007)')], 'SiC_4H': [PhononMode(Wavenumber(777, '1/cm'), Wavenumber(5, '1/cm'), 'E₂(TO)', 1.0, note='Feldman et al. (1968)'), PhononMode(Wavenumber(983, '1/cm'), Wavenumber(8, '1/cm'), 'A₁(LO)', 0.6, note='Li et al. (2023)'), PhononMode(Wavenumber(750, '1/cm'), Wavenumber(4, '1/cm'), 'A₁(TO)', 0.5, note='Feldman et al. (1968)'), PhononMode(Wavenumber(250, '1/cm'), Wavenumber(3, '1/cm'), 'Folded TA', 0.3, note='Feldman et al. (1968)')], 'YLF': [PhononMode(Wavenumber(262, '1/cm'), Wavenumber(5, '1/cm'), 'B_g', 1.0, note='Miller et al. (1970)'), PhononMode(Wavenumber(170, '1/cm'), Wavenumber(4, '1/cm'), 'A_g', 0.7, note='Salaun et al. (1997)'), PhononMode(Wavenumber(380, '1/cm'), Wavenumber(6, '1/cm'), 'E_g', 0.6, note='Miller et al. (1970)'), PhononMode(Wavenumber(520, '1/cm'), Wavenumber(8, '1/cm'), 'B_g', 0.5, note='Miller et al. (1970)'), PhononMode(Wavenumber(640, '1/cm'), Wavenumber(5, '1/cm'), 'E_g', 0.4, note='Salaun et al. (1997)')]}

PhononMode

A single Raman-active phonon mode.

Attributes:

Name Type Description
shift_cm Wavenumber

Raman shift (e.g. Wavenumber(254, "1/cm")).

linewidth_cm Wavenumber

Full width at half maximum (e.g. Wavenumber(14, "1/cm")).

symmetry str or None

Symmetry label (e.g. "A₁g", "E_g", "A₁(TO)").

relative_strength float

Relative Raman cross-section (default 1.0).

lo_phonon_cm Wavenumber or None

LO phonon frequency (if different from Raman shift).

to_phonon_cm Wavenumber or None

TO phonon frequency.

note str or None

Annotation or source reference.

shift_cm instance-attribute

shift_cm: Wavenumber

linewidth_cm instance-attribute

linewidth_cm: Wavenumber

symmetry class-attribute instance-attribute

symmetry: str | None = None

relative_strength class-attribute instance-attribute

relative_strength: float = 1.0

lo_phonon_cm class-attribute instance-attribute

lo_phonon_cm: Wavenumber | None = None

to_phonon_cm class-attribute instance-attribute

to_phonon_cm: Wavenumber | None = None

note class-attribute instance-attribute

note: str | None = None

PhononResponse

Multi-mode Raman response function.

Combines multiple PhononMode instances into a unified response by summing individual mode responses weighted by their relative strengths.

Each mode produces a Lorentzian lineshape in frequency domain: L(ω) = (γ/2) / [(ω - ω₀)² + (γ/2)²] where ω₀ is the mode shift and γ is the linewidth.

The time-domain response is the inverse FFT of the frequency-domain response.

Attributes:

Name Type Description
modes list[PhononMode]

List of phonon modes.

fR float

Total Raman fraction. If None, computed as sum of relative strengths.

modes instance-attribute

modes: list[PhononMode]

fR class-attribute instance-attribute

fR: float | None = None

from_material classmethod

from_material(name: str, db: 'object | None' = None) -> 'PhononResponse'

Build a response for a material, database-first.

Resolution order:

  1. RamanDatabase.get_phonon_modes(name) — the shipped database, the same interface used for n/k data.
  2. The canonical :data:PHONON_MATERIALS table (offline / empty DB).

Parameters:

Name Type Description Default
name material name (e.g. ``"LiNbO3"``).
required
db optional existing ``RamanDatabase`` instance to reuse.
None

Raises:

Type Description
KeyError

If neither the database nor the canonical table has modes for the material; the message lists the available material names.

h_R

h_R(t: NDArray) -> NDArray

Causal, unit-integral delayed Raman response h_R(t).

A superposition of damped oscillators, one per phonon mode::

h_R(t) = Z^-1 * sum_i w_i * exp(-t/tau_i) * sin(omega_i t) * theta(t)

where omega_i is the mode's angular frequency from its Raman shift, gamma_i its angular-frequency FWHM from its linewidth (tau_i = 2/gamma_i, the damped-oscillator / Lorentzian relation delta_omega = 2/tau), w_i its relative strength, and Z is chosen so that integral_0^inf h_R(t) dt = 1. This is the multi-vibrational-mode form used with the standard GNLSE delayed response R(t) = (1 - f_R) delta(t) + f_R h_R(t).

References

Agrawal, Nonlinear Fiber Optics, 5th ed., Sec. 2.3.2 (normalization integral h_R dt = 1); Hollenbeck & Cantrell, J. Opt. Soc. Am. B 19, 2886 (2002) (multi-vibrational-mode Raman response); Stolen, Tomlinson, Haus & Gordon, J. Opt. Soc. Am. B 6, 1159 (1989).

Parameters:

Name Type Description Default
t NDArray

Time array in seconds.

required

Returns:

Type Description
NDArray

h_R(t): zero for t < 0, with unit integral over t >= 0.

frequency_domain

frequency_domain(w_cm: WavenumberArray | NDArray) -> NDArray

Frequency-domain response: sum of Lorentzian mode lineshapes.

Parameters:

Name Type Description Default
w_cm WavenumberArray | NDArray

Frequency axis in cm⁻¹ (a :class:WavenumberArray or a bare array).

required

Returns:

Type Description
NDArray — Total response (sum of weighted Lorentzians).

time_domain

time_domain(t: NDArray) -> NDArray

Time-domain response via inverse FFT of frequency-domain response.

The time-domain response is the inverse FFT of the frequency-domain response, representing the delayed Raman response in the time domain.

Parameters:

Name Type Description Default
t NDArray

Time array in seconds.

required

Returns:

Type Description
NDArray — Time-domain response (sum of damped oscillations).

plot_modes

plot_modes(backend: Literal['matplotlib', 'plotly'] = 'matplotlib')

Bar chart of all phonon modes.

Parameters:

Name Type Description Default
backend 'matplotlib' or 'plotly'
'matplotlib'

Returns:

Type Description
fig or None — Plot figure, or None if no modes.

plot_spectrum

plot_spectrum(shift_range_cm: float = 200, n_points: int = 1000, backend: Literal['matplotlib', 'plotly'] = 'matplotlib')

Overlay of all Lorentzian mode lineshapes.

Parameters:

Name Type Description Default
shift_range_cm float

Range around 0 to plot (cm⁻¹).

200
n_points int

Number of points.

1000
backend 'matplotlib' or 'plotly'
'matplotlib'

Returns:

Type Description
fig or None — Plot figure, or None if no modes.

demo

demo()

Self-check: verify basic functionality.

Returns:

Type Description
dict — Test results with pass/fail status.