"""Energy-dependent scattering model for a single parabolic band.""" from __future__ import annotations from dataclasses import dataclass from math import sqrt from .constants import ELEMENTARY_CHARGE as e, ELECTRON_MASS as me @dataclass(frozen=True, slots=True) class ScatteringModel: """Power-law mean-free-path model. The model follows the convention used by the original program:: tau(E) = sqrt(m* m_e / 2) * (l0 / e**r) * (E e)**(r - 1/2) where ``E`` is supplied in eV, ``l0`` is in m, and the returned relaxation time is in seconds. ``charge_sign`` is +1 for holes and -1 for electrons. """ charge_sign: int = 1 scattering_factor: float = 0.5 mean_free_path: float = 1.0e-8 def __post_init__(self) -> None: if self.charge_sign not in (-1, 1): raise ValueError("charge_sign must be +1 (hole) or -1 (electron)") if self.mean_free_path <= 0.0: raise ValueError("mean_free_path must be positive") if self.scattering_factor <= -1.0: raise ValueError( "scattering_factor must be greater than -1 for the transport integral" ) @property def normalized_mean_free_path(self) -> float: """Return ``l0/e**r`` in the SI normalization used by the model.""" return self.mean_free_path / e**self.scattering_factor def relaxation_time(self, energy_ev: float, effective_mass: float) -> float | None: """Return tau(E) in seconds, or ``None`` for non-positive energy.""" if energy_ev <= 0.0: return None if effective_mass <= 0.0: raise ValueError("effective_mass must be positive") return ( sqrt(0.5 * effective_mass * me) * self.normalized_mean_free_path * (energy_ev * e) ** (self.scattering_factor - 0.5) ) __all__ = ["ScatteringModel"]