"""Parabolic-band density-of-states utilities.""" from __future__ import annotations from math import pi, sqrt from .constants import ( BOLTZMANN_CONSTANT as kB, ELEMENTARY_CHARGE as e, ELECTRON_MASS as me, PLANCK_CONSTANT as h, REDUCED_PLANCK_CONSTANT as hbar, ) def _require_positive(name: str, value: float) -> float: value = float(value) if value <= 0.0: raise ValueError(f"{name} must be positive, got {value!r}") return value def effective_density_of_states(effective_mass: float, temperature: float) -> float: """Return the 3D parabolic-band effective DOS in cm^-3. ``effective_mass`` is measured in units of the free-electron mass. """ mstar = _require_positive("effective_mass", effective_mass) temperature = _require_positive("temperature", temperature) return 2.0 * (2.0 * pi * me * mstar * kB * temperature / h**2) ** 1.5 * 1.0e-6 def effective_mass_from_density_of_states( density_of_states: float, temperature: float ) -> float: """Invert :func:`effective_density_of_states`. Parameters ---------- density_of_states: Effective DOS in cm^-3. temperature: Temperature in K. """ nc = _require_positive("density_of_states", density_of_states) temperature = _require_positive("temperature", temperature) return (nc * 1.0e6 / 2.0) ** (2.0 / 3.0) * h**2 / (2.0 * pi * me * kB * temperature) def density_of_states_prefactor(effective_mass: float) -> float: """Return ``D0`` for ``D(E)=D0*sqrt(E-Eedge)``. The returned unit is cm^-3 eV^-3/2. Unlike the legacy function, this quantity is temperature independent and therefore has no temperature argument. """ mstar = _require_positive("effective_mass", effective_mass) return ( sqrt(2.0) / pi**2 * (me * mstar) ** 1.5 / hbar**3 * 1.0e-6 * e**1.5 ) __all__ = [ "effective_density_of_states", "effective_mass_from_density_of_states", "density_of_states_prefactor", ]